Add hold support to frameworks/base/telecomm

Bug: 13169202

Change-Id: Ib01990c1f8654f95a4cfcca4a91f0ab143722d8e
diff --git a/api/current.txt b/api/current.txt
index 8302aba..cc4f2a0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24455,11 +24455,13 @@
     method public abstract void call(android.telecomm.CallInfo);
     method public abstract void disconnect(java.lang.String);
     method public final android.os.IBinder getBinder();
+    method public abstract void hold(java.lang.String);
     method public abstract void isCompatibleWith(android.telecomm.CallInfo);
     method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract void reject(java.lang.String);
     method public abstract void setCallServiceAdapter(android.telecomm.CallServiceAdapter);
     method public abstract void setIncomingCallId(java.lang.String, android.os.Bundle);
+    method public abstract void unhold(java.lang.String);
   }
 
   public final class CallServiceAdapter {
@@ -24470,6 +24472,7 @@
     method public void setDialing(java.lang.String);
     method public void setDisconnected(java.lang.String);
     method public void setIsCompatibleWith(java.lang.String, boolean);
+    method public void setOnHold(java.lang.String);
     method public void setRinging(java.lang.String);
   }
 
@@ -24523,13 +24526,16 @@
     enum_constant public static final android.telecomm.CallState ACTIVE;
     enum_constant public static final android.telecomm.CallState DIALING;
     enum_constant public static final android.telecomm.CallState DISCONNECTED;
+    enum_constant public static final android.telecomm.CallState ON_HOLD;
     enum_constant public static final android.telecomm.CallState RINGING;
   }
 
   public final class InCallAdapter {
     method public void answerCall(java.lang.String);
     method public void disconnectCall(java.lang.String);
+    method public void holdCall(java.lang.String);
     method public void rejectCall(java.lang.String);
+    method public void unholdCall(java.lang.String);
   }
 
   public abstract class InCallService extends android.app.Service {
@@ -24539,6 +24545,7 @@
     method protected abstract void setActive(java.lang.String);
     method protected abstract void setDisconnected(java.lang.String);
     method protected abstract void setInCallAdapter(android.telecomm.InCallAdapter);
+    method protected abstract void setOnHold(java.lang.String);
   }
 
   public final class TelecommConstants {
diff --git a/telecomm/java/android/telecomm/CallService.java b/telecomm/java/android/telecomm/CallService.java
index 52b2599..395bcc1 100644
--- a/telecomm/java/android/telecomm/CallService.java
+++ b/telecomm/java/android/telecomm/CallService.java
@@ -86,6 +86,12 @@
                 case MSG_DISCONNECT:
                     disconnect((String) msg.obj);
                     break;
+                case MSG_HOLD:
+                    hold((String) msg.obj);
+                    break;
+                case MSG_UNHOLD:
+                    unhold((String) msg.obj);
+                    break;
                 default:
                     break;
             }
@@ -139,6 +145,16 @@
         public void disconnect(String callId) {
             mMessageHandler.obtainMessage(MSG_DISCONNECT, callId).sendToTarget();
         }
+
+        @Override
+        public void hold(String callId) {
+            mMessageHandler.obtainMessage(MSG_HOLD, callId).sendToTarget();
+        }
+
+        @Override
+        public void unhold(String callId) {
+            mMessageHandler.obtainMessage(MSG_UNHOLD, callId).sendToTarget();
+        }
     }
 
     // Only used internally by this class.
@@ -154,7 +170,9 @@
             MSG_SET_INCOMING_CALL_ID = 5,
             MSG_ANSWER = 6,
             MSG_REJECT = 7,
-            MSG_DISCONNECT = 8;
+            MSG_DISCONNECT = 8,
+            MSG_HOLD = 9,
+            MSG_UNHOLD = 10;
 
     /**
      * Message handler for consolidating binder callbacks onto a single thread.
@@ -258,4 +276,18 @@
      * @param callId The ID of the call to disconnect.
      */
     public abstract void disconnect(String callId);
+
+    /**
+     * Puts the specified call on hold.
+     *
+     * @param callId The ID of the call to put on hold.
+     */
+    public abstract void hold(String callId);
+
+    /**
+     * Removes the specified call from hold.
+     *
+     * @param callId The ID of the call to unhold.
+     */
+    public abstract void unhold(String callId);
 }
diff --git a/telecomm/java/android/telecomm/CallServiceAdapter.java b/telecomm/java/android/telecomm/CallServiceAdapter.java
index a391f34..0527a6d 100644
--- a/telecomm/java/android/telecomm/CallServiceAdapter.java
+++ b/telecomm/java/android/telecomm/CallServiceAdapter.java
@@ -140,4 +140,18 @@
         } catch (RemoteException e) {
         }
     }
+
+    /**
+     * Sets a call's state to be on hold.
+     *
+     * @param callId - The unique ID of the call whose state is changing to be on hold.
+     */
+    public void setOnHold(String callId) {
+        try {
+            mAdapter.setOnHold(callId);
+        } catch (RemoteException e) {
+        }
+    }
+
+
 }
diff --git a/telecomm/java/android/telecomm/CallState.java b/telecomm/java/android/telecomm/CallState.java
index d699fbd..3937b08 100644
--- a/telecomm/java/android/telecomm/CallState.java
+++ b/telecomm/java/android/telecomm/CallState.java
@@ -56,6 +56,14 @@
     ACTIVE,
 
     /**
+     * Indicates that the call is currently on hold. In this state, the call is not terminated
+     * but no communication is allowed until the call is no longer on hold. The typical transition
+     * to this state is by the user putting an {@link #ACTIVE} call on hold by explicitly performing
+     * an action, such as clicking the hold button.
+     */
+    ON_HOLD,
+
+    /**
      * Indicates that a call is currently disconnected. All states can transition to this state
      * by the call service giving notice that the connection has been severed. When the user
      * explicitly ends a call, it will not transition to this state until the call service confirms
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index c9bd8c2..6649ef7 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -78,4 +78,28 @@
         } catch (RemoteException e) {
         }
     }
+
+    /**
+     * Instructs Telecomm to put the specified call on hold.
+     *
+     * @param callId The identifier of the call to put on hold.
+     */
+    public void holdCall(String callId) {
+        try {
+            mAdapter.holdCall(callId);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Instructs Telecomm to release the specified call from hold.
+     *
+     * @param callId The identifier of the call to release from hold.
+     */
+    public void unholdCall(String callId) {
+        try {
+            mAdapter.unholdCall(callId);
+        } catch (RemoteException e) {
+        }
+    }
 }
diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java
index 7819d44..cd6a882 100644
--- a/telecomm/java/android/telecomm/InCallService.java
+++ b/telecomm/java/android/telecomm/InCallService.java
@@ -39,6 +39,7 @@
     private static final int MSG_ADD_CALL = 2;
     private static final int MSG_SET_ACTIVE = 3;
     private static final int MSG_SET_DISCONNECTED = 4;
+    private static final int MSG_SET_HOLD = 5;
 
     /** Default Handler used to consolidate binder method calls onto a single thread. */
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -58,6 +59,8 @@
                 case MSG_SET_DISCONNECTED:
                     setDisconnected((String) msg.obj);
                     break;
+                case MSG_SET_HOLD:
+                    setOnHold((String) msg.obj);
                 default:
                     break;
             }
@@ -89,6 +92,12 @@
         public void setDisconnected(String callId) {
             mHandler.obtainMessage(MSG_SET_DISCONNECTED, callId).sendToTarget();
         }
+
+        /** {@inheritDoc} */
+        @Override
+        public void setOnHold(String callId) {
+            mHandler.obtainMessage(MSG_SET_HOLD, callId).sendToTarget();
+        }
     }
 
     private final InCallServiceBinder mBinder;
@@ -136,4 +145,12 @@
      * @param callId The identifier of the call that was disconnected.
      */
     protected abstract void setDisconnected(String callId);
+
+    /**
+     * Indicates to the in-call app that a call has been moved to the
+     * {@link android.telecomm.CallState#ON_HOLD} state and the user should be notified.
+     *
+     * @param callId The identifier of the call that was put on hold.
+     */
+    protected abstract void setOnHold(String callId);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/ICallService.aidl b/telecomm/java/com/android/internal/telecomm/ICallService.aidl
index 1df3f80..d05a3e0 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallService.aidl
@@ -39,7 +39,7 @@
     /**
      * Sets an implementation of ICallServiceAdapter which the call service can use to add new calls
      * and communicate state changes of existing calls. This is the first method that is called
-     * after a the framework binds to the call service.
+     * after the framework binds to the call service.
      *
      * @param callServiceAdapter Interface to CallsManager for adding and updating calls.
      */
@@ -120,4 +120,20 @@
      * @param callId The identifier of the call to disconnect.
      */
     void disconnect(String callId);
+
+    /**
+     * Puts the call identified by callId on hold. Telecomm invokes this method when a call should
+     * be placed on hold per user request or because a different call was made active.
+     *
+     * @param callId The identifier of the call to put on hold.
+     */
+    void hold(String callId);
+
+    /**
+     * Removes the call identified by callId from hold. Telecomm invokes this method when a call
+     * should be removed on hold per user request or because a different call was put on hold.
+     *
+     * @param callId The identifier of the call to remove from hold.
+     */
+    void unhold(String callId);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
index 7920b64..e96defe 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
@@ -91,4 +91,11 @@
      * @param callId The unique ID of the call whose state is changing to disconnected.
      */
     void setDisconnected(String callId);
+
+    /**
+     * Sets a call's state to be on hold.
+     *
+     * @param callId The unique ID of the call whose state is changing to be on hold.
+     */
+    void setOnHold(String callId);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
index d4e67fc..6ae055d 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
@@ -53,4 +53,18 @@
      * @param callId The identifier of the call to disconnect.
      */
     void disconnectCall(String callId);
+
+    /**
+     * Instructs Telecomm to put the specified call on hold.
+     *
+     * @param callId The identifier of the call to put on hold.
+     */
+    void holdCall(String callId);
+
+    /**
+     * Instructs Telecomm to release the specified call from hold.
+     *
+     * @param callId The identifier of the call to release from hold.
+     */
+    void unholdCall(String callId);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallService.aidl b/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
index 05b0d20..b3bd0a6 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallService.aidl
@@ -66,4 +66,12 @@
      * @param callId The identifier of the call that was disconnected.
      */
     void setDisconnected(String callId);
+
+    /**
+     * Indicates to the in-call app that a call has been moved to the
+     * {@link android.telecomm.CallState#HOLD} state and the user should be notified.
+     *
+     * @param callId The identifier of the call that was put on hold.
+     */
+    void setOnHold(String callId);
 }