API declarations for Call Handover.
Design doc:
https://docs.google.com/document/d/1qY3oAzjff_4A1ttYb_CGrE_OwTRmXMG_KGsIuPT1ey8/edit#
Bug: 65415068
Test: manual.
Change-Id: I0c2f561d92ad6504f858eadde09980fc1ce8727f
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index e8e0680..f81c89a 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -856,6 +856,39 @@
*/
public static abstract class Callback {
/**
+ * @hide
+ */
+ @IntDef({HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_DEST_NOT_SUPPORTED,
+ HANDOVER_FAILURE_DEST_INVALID_PERM, HANDOVER_FAILURE_DEST_USER_REJECTED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface HandoverFailureErrors {}
+
+ /**
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
+ * to handover the call rejects handover.
+ */
+ public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
+
+ /**
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there is
+ * an error associated with unsupported handover.
+ */
+ public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2;
+
+ /**
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
+ * are some permission errors associated with APIs doing handover.
+ */
+ public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3;
+
+ /**
+ * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when user
+ * rejects handover.
+ */
+ public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4;
+
+
+ /**
* Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
*
* @param call The {@code Call} invoking this method.
@@ -990,6 +1023,21 @@
* {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
*/
public void onRttInitiationFailure(Call call, int reason) {}
+
+ /**
+ * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
+ * has completed successfully.
+ * @param call The call which had initiated handover.
+ */
+ public void onHandoverComplete(Call call) {}
+
+ /**
+ * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
+ * has failed.
+ * @param call The call which had initiated handover.
+ * @param failureReason Error reason for failure
+ */
+ public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
}
/**
@@ -1366,6 +1414,24 @@
}
/**
+ * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
+ * by {@code toHandle}. The videoState specified indicates the desired video state after the
+ * handover.
+ * <p>
+ * A handover request is initiated by the user from one app to indicate a desire
+ * to handover a call to another.
+ *
+ * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
+ * this call to.
+ * @param videoState Indicates the video state desired after the handover.
+ * @param extras Bundle containing extra information to be passed to the
+ * {@link ConnectionService}
+ */
+ public void handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras) {
+ mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
+ }
+
+ /**
* Terminate the RTT session on this call. The resulting state change will be notified via
* the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
*/
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 35804f6..da8ac5e 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -2033,6 +2033,43 @@
}
/**
+ * Called by Telecom on the initiating side of the handover to create an instance of a
+ * handover connection.
+ * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
+ * ConnectionService which needs to handover the call.
+ * @param request Details about the call which needs to be handover.
+ * @return Connection object corresponding to the handover call.
+ */
+ public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
+ ConnectionRequest request) {
+ return null;
+ }
+
+ /**
+ * Called by Telecom on the receiving side of the handover to request the
+ * {@link ConnectionService} to create an instance of a handover connection.
+ * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
+ * ConnectionService which needs to handover the call.
+ * @param request Details about the call which needs to be handover.
+ * @return {@link Connection} object corresponding to the handover call.
+ */
+ public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
+ ConnectionRequest request) {
+ return null;
+ }
+
+ /**
+ * Called by Telecom in response to a {@code TelecomManager#acceptHandover()}
+ * invocation which failed.
+ * @param request Details about the call which needs to be handover.
+ * @param error Reason for handover failure as defined in
+ * {@link android.telecom.Call.Callback#HANDOVER_FAILURE_DEST_INVALID_PERM}
+ */
+ public void onHandoverFailed(ConnectionRequest request, int error) {
+ return;
+ }
+
+ /**
* Create a {@code Connection} for a new unknown call. An unknown call is a call originating
* from the ConnectionService that was neither a user-initiated outgoing call, nor an incoming
* call created using
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 9bf0467..4bc2a9b 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -435,4 +435,21 @@
} catch (RemoteException ignored) {
}
}
+
+
+ /**
+ * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
+ * by destAcct.
+ * @param callId The callId of the Call which calls this function.
+ * @param destAcct ConnectionService to which the call should be handed over.
+ * @param videoState The video state desired after the handover.
+ * @param extras Extra information to be passed to ConnectionService
+ */
+ public void handoverTo(String callId, PhoneAccountHandle destAcct, int videoState,
+ Bundle extras) {
+ try {
+ mAdapter.handoverTo(callId, destAcct, videoState, extras);
+ } catch (RemoteException ignored) {
+ }
+ }
}
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 691e7cf..74b9465 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -86,13 +86,11 @@
/**
* Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
* indicates whether this {@link PhoneAccount} is capable of supporting a request to handover a
- * connection (see {@link android.telecom.Call#EVENT_REQUEST_HANDOVER}) to this
- * {@link PhoneAccount} from a {@link PhoneAccount} specifying
- * {@link #EXTRA_SUPPORTS_HANDOVER_FROM}.
+ * connection (see {@code android.telecom.Call#handoverTo()}) to this {@link PhoneAccount} from
+ * a {@link PhoneAccount} specifying {@link #EXTRA_SUPPORTS_HANDOVER_FROM}.
* <p>
* A handover request is initiated by the user from the default dialer app to indicate a desire
* to handover a call from one {@link PhoneAccount}/{@link ConnectionService} to another.
- * @hide
*/
public static final String EXTRA_SUPPORTS_HANDOVER_TO =
"android.telecom.extra.SUPPORTS_HANDOVER_TO";
@@ -113,12 +111,11 @@
* Boolean {@link PhoneAccount} extras key (see {@link PhoneAccount#getExtras()}) which
* indicates whether this {@link PhoneAccount} is capable of supporting a request to handover a
* connection from this {@link PhoneAccount} to another {@link PhoneAccount}.
- * (see {@link android.telecom.Call#EVENT_REQUEST_HANDOVER}) which specifies
+ * (see {@code android.telecom.Call#handoverTo()}) which specifies
* {@link #EXTRA_SUPPORTS_HANDOVER_TO}.
* <p>
* A handover request is initiated by the user from the default dialer app to indicate a desire
* to handover a call from one {@link PhoneAccount}/{@link ConnectionService} to another.
- * @hide
*/
public static final String EXTRA_SUPPORTS_HANDOVER_FROM =
"android.telecom.extra.SUPPORTS_HANDOVER_FROM";
@@ -132,7 +129,6 @@
* <p>
* By default, Self-Managed {@link PhoneAccount}s do not log their calls to the call log.
* Setting this extra to {@code true} provides a means for them to log their calls.
- * @hide
*/
public static final String EXTRA_LOG_SELF_MANAGED_CALLS =
"android.telecom.extra.LOG_SELF_MANAGED_CALLS";
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index aa2323d..4d2cb04 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1749,6 +1749,41 @@
return false;
}
+ /**
+ * Called from the recipient side of a handover to indicate a desire to accept the handover
+ * of an ongoing call to another {@link ConnectionService} identified by
+ * {@link PhoneAccountHandle} destAcct. For managed {@link ConnectionService}s, the specified
+ * {@link PhoneAccountHandle} must have been registered with {@link #registerPhoneAccount} and
+ * the user must have enabled the corresponding {@link PhoneAccount}. This can be checked using
+ * {@link #getPhoneAccount}. Self-managed {@link ConnectionService}s must have
+ * {@link android.Manifest.permission#MANAGE_OWN_CALLS} to handover a call to it.
+ * <p>
+ * Once invoked, this method will cause the system to bind to the {@link ConnectionService}
+ * associated with the {@link PhoneAccountHandle} destAcct and call
+ * (See {@link ConnectionService#onCreateIncomingHandoverConnection}).
+ * <p>
+ * For a managed {@link ConnectionService}, a {@link SecurityException} will be thrown if either
+ * the {@link PhoneAccountHandle} destAcct does not correspond to a registered
+ * {@link PhoneAccount} or the associated {@link PhoneAccount} is not currently enabled by the
+ * user.
+ * <p>
+ * For a self-managed {@link ConnectionService}, a {@link SecurityException} will be thrown if
+ * the calling app does not have {@link android.Manifest.permission#MANAGE_OWN_CALLS}.
+ *
+ * @param srcAddr The {@link android.net.Uri} of the ongoing call to handover to the caller’s
+ * {@link ConnectionService}.
+ * @param videoState Video state after the handover.
+ * @param destAcct The {@link PhoneAccountHandle} registered to the calling package.
+ */
+ public void acceptHandover(Uri srcAddr, int videoState, PhoneAccountHandle destAcct) {
+ try {
+ if (isServiceConnected()) {
+ getTelecomService().acceptHandover(srcAddr, videoState, destAcct);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException acceptHandover: " + e);
+ }
+ }
private ITelecomService getTelecomService() {
if (mTelecomServiceOverride != null) {
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index bce3392..23ac940 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -77,4 +77,7 @@
void stopRtt(String callId);
void setRttMode(String callId, int mode);
+
+ void handoverTo(String callId, in PhoneAccountHandle destAcct, int videoState,
+ in Bundle extras);
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 8ebac2c..3460754 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -274,4 +274,9 @@
* @see TelecomServiceImpl#waitOnHandler
*/
void waitOnHandlers();
+
+ /**
+ * @see TelecomServiceImpl#acceptHandover
+ */
+ void acceptHandover(in Uri srcAddr, int videoState, in PhoneAccountHandle destAcct);
}