Implement Call handover initiation side APIs.

Bug: 65415068
Test: Manual

Design doc:
https://docs.google.com/document/d/1qY3oAzjff_4A1ttYb_CGrE_OwTRmXMG_KGsIuPT1ey8/edit#

Change-Id: I692bb14fba66733154378c2dda525aa85c471a38
diff --git a/api/current.txt b/api/current.txt
index 182dd3a..5d98e39 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -39273,6 +39273,7 @@
     field public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3; // 0x3
     field public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2; // 0x2
     field public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4; // 0x4
+    field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5; // 0x5
   }
 
   public static class Call.Details {
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a07f2bb..16150ba 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -858,7 +858,8 @@
          * @hide
          */
         @IntDef({HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_DEST_NOT_SUPPORTED,
-                HANDOVER_FAILURE_DEST_INVALID_PERM, HANDOVER_FAILURE_DEST_USER_REJECTED})
+                HANDOVER_FAILURE_DEST_INVALID_PERM, HANDOVER_FAILURE_DEST_USER_REJECTED,
+                HANDOVER_FAILURE_ONGOING_EMERG_CALL})
         @Retention(RetentionPolicy.SOURCE)
         public @interface HandoverFailureErrors {}
 
@@ -886,6 +887,12 @@
          */
         public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4;
 
+        /**
+         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
+         * is ongoing emergency call.
+         */
+        public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5;
+
 
         /**
          * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
@@ -1935,6 +1942,15 @@
         }
     }
 
+    /** {@hide} */
+    final void internalOnHandoverFailed(int error) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(() -> callback.onHandoverFailed(call, error));
+        }
+    }
+
     private void fireStateChanged(final int newState) {
         for (CallbackRecord<Callback> record : mCallbackRecords) {
             final Call call = this;
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 7e83306..2834201 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -1371,9 +1371,19 @@
                 isIncoming,
                 isUnknown);
 
-        Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
-                : isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
-                : onCreateOutgoingConnection(callManagerAccount, request);
+        Connection connection = null;
+        if (request.getExtras() != null && request.getExtras().getBoolean(
+                TelecomManager.EXTRA_IS_HANDOVER,false)) {
+            if (!isIncoming) {
+                connection = onCreateOutgoingHandoverConnection(callManagerAccount, request);
+            } else {
+                // Todo: Call onCreateIncommingHandoverConnection()
+            }
+        } else {
+            connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
+                    : isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
+                    : onCreateOutgoingConnection(callManagerAccount, request);
+        }
         Log.d(this, "createConnection, connection: %s", connection);
         if (connection == null) {
             connection = Connection.createFailedConnection(
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index d558bba..74fa62d 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -80,6 +80,7 @@
     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;
+    private static final int MSG_ON_HANDOVER_FAILED = 12;
 
     /** Default Handler used to consolidate binder method calls onto a single thread. */
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -150,6 +151,12 @@
                     mPhone.internalOnRttInitiationFailure(callId, reason);
                     break;
                 }
+                case MSG_ON_HANDOVER_FAILED: {
+                    String callId = (String) msg.obj;
+                    int error = msg.arg1;
+                    mPhone.internalOnHandoverFailed(callId, error);
+                    break;
+                }
                 default:
                     break;
             }
@@ -225,6 +232,11 @@
         public void onRttInitiationFailure(String callId, int reason) {
             mHandler.obtainMessage(MSG_ON_RTT_INITIATION_FAILURE, reason, 0, callId).sendToTarget();
         }
+
+        @Override
+        public void onHandoverFailed(String callId, int error) {
+            mHandler.obtainMessage(MSG_ON_HANDOVER_FAILED, error, 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 421b1a4..b5394b9 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -223,6 +223,13 @@
         }
     }
 
+    final void internalOnHandoverFailed(String callId, int error) {
+        Call call = mCallByTelecomCallId.get(callId);
+        if (call != null) {
+            call.internalOnHandoverFailed(error);
+        }
+    }
+
     /**
      * Called to destroy the phone and cleanup any lingering calls.
      */
diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
index e8cf8e9..110109e 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
@@ -54,4 +54,6 @@
     void onRttUpgradeRequest(String callId, int id);
 
     void onRttInitiationFailure(String callId, int reason);
+
+    void onHandoverFailed(String callId, int error);
 }