IMS: Deflect call feature

Code changes to support IMS Deflect call feature.

CRs-Fixed: 713856

Conflicts:
telecomm/java/android/telecomm/ConnectionService.java
telecomm/java/android/telecom/InCallAdapter.java
Change-Id: I74b7fd34cad8d49f660fb05bd33becf6ae1de5d2
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 6ff5e1b..86c648b 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -422,6 +422,15 @@
     }
 
     /**
+     * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
+     * @param number The number to which the call will be deflected.
+     */
+    /** @hide */
+    public void deflectCall(String number) {
+        mInCallAdapter.deflectCall(mTelecommCallId, number);
+    }
+
+    /**
      * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
      *
      * @param rejectWithMessage Whether to reject with a text message.
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 73e0547..15d5cc7 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -1050,6 +1050,13 @@
 
     /**
      * Notifies this Connection, which is in {@link #STATE_RINGING}, of
+     * a request to deflect.
+     */
+    /** @hide */
+    public void onDeflect(String number) {}
+
+    /**
+     * Notifies this Connection, which is in {@link State#RINGING}, of
      * a request to reject.
      */
     public void onReject() {}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 400e656..cdca987 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -76,6 +76,7 @@
     private static final int MSG_SWAP_CONFERENCE = 19;
     private static final int MSG_SET_LOCAL_HOLD = 20;
     private static final int MSG_SET_ACTIVE_SUB = 21;
+    private static final int MSG_DEFLECT = 22;
 
     private static Connection sNullConnection;
 
@@ -139,6 +140,14 @@
         }
 
         @Override
+        public void deflect(String callId, String number) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = number;
+            mHandler.obtainMessage(MSG_DEFLECT, args).sendToTarget();
+        }
+
+        @Override
         public void reject(String callId) {
             mHandler.obtainMessage(MSG_REJECT, callId).sendToTarget();
         }
@@ -359,6 +368,17 @@
                     }
                     break;
                 }
+                case MSG_DEFLECT: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        String callId = (String) args.arg1;
+                        String number = (String) args.arg2;
+                        deflect(callId, number);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
                 default:
                     break;
             }
@@ -656,6 +676,11 @@
         findConnectionForAction(callId, "answer").onAnswer();
     }
 
+    private void deflect(String callId, String number) {
+        Log.d(this, "deflect %s - %s", callId, number);
+        findConnectionForAction(callId, "deflect").onDeflect(number);
+    }
+
     private void reject(String callId) {
         Log.d(this, "reject %s", callId);
         findConnectionForAction(callId, "reject").onReject();
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 1ad26fb..0585fcc 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -57,6 +57,22 @@
     }
 
     /**
+     * Instructs Telecomm to deflect the specified call.
+     *
+     * @param callId The identifier of the call to deflect.
+     * @param deflectNumber The number to deflect.
+     */
+    /**
+     * {@hide}
+     */
+    public void deflectCall(String callId, String deflectNumber) {
+        try {
+            mAdapter.deflectCall(callId, deflectNumber);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Instructs Telecom to reject the specified call.
      *
      * @param callId The identifier of the call to reject.
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 0da46eb..a804375 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -48,6 +48,8 @@
 
     void answer(String callId);
 
+    void deflect(String callId, String number);
+
     void reject(String callId);
 
     void disconnect(String callId);
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 7888427..2b3c336 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -28,6 +28,8 @@
 oneway interface IInCallAdapter {
     void answerCall(String callId, int videoState);
 
+    void deflectCall(String callId, String deflectNumber);
+
     void rejectCall(String callId, boolean rejectWithMessage, String textMessage);
 
     void disconnectCall(String callId);
diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
index 98b2d8a..b9503ad 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSession.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
@@ -128,6 +128,13 @@
     void accept(int callType, in ImsStreamMediaProfile profile);
 
     /**
+     * Deflects an incoming call to given number.
+     *
+     * @param deflectNumber number to deflect the call
+     */
+    void deflect(String deflectNumber);
+
+    /**
      * Rejects an incoming call or session update.
      *
      * @param reason reason code to reject an incoming call
diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
index 11da6e6..e383a17 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
@@ -114,4 +114,10 @@
      * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
      */
     void callSessionTtyModeReceived(in IImsCallSession session, in int mode);
+
+    /**
+     * Notifies the result of deflect request.
+     */
+    void callSessionDeflected(in IImsCallSession session);
+    void callSessionDeflectFailed(in IImsCallSession session, in ImsReasonInfo reasonInfo);
 }