Enable HOLD capability for IMS-based CDMA connections.

+ Refactored method for checking whether a call is based on an IMS
connection into the parent TelephonyConnection class.
+ Changed CdmaConnection/GsmConnection to obtain a populated
call capabilities from their TelephonyConnection super class when
building call capabilities.
+ Add IMS-scenario handling for HOLD when building call capabilities.

Bug: 17913504
Change-Id: I03316a0bea509395fe9a0f0688047f96c72db87e
diff --git a/src/com/android/services/telephony/CdmaConnection.java b/src/com/android/services/telephony/CdmaConnection.java
index ddd732b..3242e64 100644
--- a/src/com/android/services/telephony/CdmaConnection.java
+++ b/src/com/android/services/telephony/CdmaConnection.java
@@ -27,7 +27,6 @@
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.Connection;
-import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 import com.android.internal.telephony.Phone;
 import com.android.phone.Constants;
 
@@ -157,9 +156,9 @@
 
     @Override
     protected int buildCallCapabilities() {
-        int capabilities = 0;
+        int capabilities = super.buildCallCapabilities();
         if (mAllowMute) {
-            capabilities = PhoneCapabilities.MUTE;
+            capabilities |= PhoneCapabilities.MUTE;
         }
         return capabilities;
     }
@@ -206,8 +205,7 @@
      * Read the settings to determine which type of DTMF method this CDMA phone calls.
      */
     private boolean useBurstDtmf() {
-        boolean isImsCall = getOriginalConnection() instanceof ImsPhoneConnection;
-        if (isImsCall) {
+        if (isImsConnection()) {
             Log.d(this,"in ims call, return false");
             return false;
         }
diff --git a/src/com/android/services/telephony/GsmConnection.java b/src/com/android/services/telephony/GsmConnection.java
index 479d247..da03fa1 100644
--- a/src/com/android/services/telephony/GsmConnection.java
+++ b/src/com/android/services/telephony/GsmConnection.java
@@ -64,7 +64,9 @@
 
     @Override
     protected int buildCallCapabilities() {
-        int capabilities = PhoneCapabilities.MUTE | PhoneCapabilities.SUPPORT_HOLD;
+        int capabilities = super.buildCallCapabilities();
+        capabilities |= PhoneCapabilities.MUTE;
+        capabilities |= PhoneCapabilities.SUPPORT_HOLD;
         if (getState() == STATE_ACTIVE || getState() == STATE_HOLDING) {
             capabilities |= PhoneCapabilities.HOLD;
         }
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 1cc6ad6..9c4ea30 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -324,7 +324,20 @@
 
     public void performConference(TelephonyConnection otherConnection) {}
 
-    protected abstract int buildCallCapabilities();
+    /**
+     * Builds call capabilities common to all TelephonyConnections. Namely, apply IMS-based
+     * capabilities.
+     */
+    protected int buildCallCapabilities() {
+        int callCapabilities = 0;
+        if (isImsConnection()) {
+            callCapabilities |= PhoneCapabilities.SUPPORT_HOLD;
+            if (getState() == STATE_ACTIVE || getState() == STATE_HOLDING) {
+                callCapabilities |= PhoneCapabilities.HOLD;
+            }
+        }
+        return callCapabilities;
+    }
 
     protected final void updateCallCapabilities() {
         int newCallCapabilities = buildCallCapabilities();
@@ -593,8 +606,7 @@
         int currentCapabilities = callCapabilities;
 
         // An IMS call cannot be individually disconnected or separated from its parent conference
-        boolean isImsCall = getOriginalConnection() instanceof ImsPhoneConnection;
-        if (!isImsCall) {
+        if (!isImsConnection()) {
             currentCapabilities |=
                     PhoneCapabilities.DISCONNECT_FROM_CONFERENCE
                     | PhoneCapabilities.SEPARATE_FROM_CONFERENCE;
@@ -677,6 +689,15 @@
         return false;
     }
 
+    /**
+     * Whether the original connection is an IMS connection.
+     * @return {@code True} if the original connection is an IMS connection, {@code false}
+     *     otherwise.
+     */
+    protected boolean isImsConnection() {
+        return getOriginalConnection() instanceof ImsPhoneConnection;
+    }
+
     private static Uri getAddressFromNumber(String number) {
         // Address can be null for blocked calls.
         if (number == null) {