Merge "Add carrier privilege check and update several APIs."
diff --git a/src/com/android/services/telephony/CdmaConnection.java b/src/com/android/services/telephony/CdmaConnection.java
index f46e64f..abd0a08 100644
--- a/src/com/android/services/telephony/CdmaConnection.java
+++ b/src/com/android/services/telephony/CdmaConnection.java
@@ -16,6 +16,8 @@
 
 package com.android.services.telephony;
 
+import android.telecomm.CallCapabilities;
+
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
 
@@ -46,4 +48,10 @@
         // no-op, we only play timed dtmf tones for cdma.
         super.onStopDtmfTone();
     }
+
+    @Override
+    protected int buildCallCapabilities() {
+        int capabilities = CallCapabilities.MUTE;
+        return capabilities;
+    }
 }
diff --git a/src/com/android/services/telephony/GsmConnection.java b/src/com/android/services/telephony/GsmConnection.java
index 7019068..f7ab344 100644
--- a/src/com/android/services/telephony/GsmConnection.java
+++ b/src/com/android/services/telephony/GsmConnection.java
@@ -16,6 +16,8 @@
 
 package com.android.services.telephony;
 
+import android.telecomm.CallCapabilities;
+
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
@@ -24,6 +26,7 @@
  * Manages a single phone call handled by GSM.
  */
 public class GsmConnection extends PstnConnection {
+    private boolean mIsConferenceCapable;
 
     public GsmConnection(Phone phone, Connection connection) {
         super(phone, connection);
@@ -43,6 +46,13 @@
         super.onStopDtmfTone();
     }
 
+    void setIsConferenceCapable(boolean isConferenceCapable) {
+        if (mIsConferenceCapable != isConferenceCapable) {
+            mIsConferenceCapable = isConferenceCapable;
+            updateCallCapabilities();
+        }
+    }
+
     public void performConference() {
         try {
             Log.d(this, "conference - %s", this);
@@ -51,4 +61,16 @@
             Log.e(this, e, "Failed to conference call.");
         }
     }
+
+    @Override
+    protected int buildCallCapabilities() {
+        int capabilities = CallCapabilities.MUTE | CallCapabilities.SUPPORT_HOLD;
+        if (getState() == State.ACTIVE || getState() == State.HOLDING) {
+            capabilities |= CallCapabilities.HOLD;
+        }
+        if (mIsConferenceCapable) {
+            capabilities |= CallCapabilities.MERGE_CALLS;
+        }
+        return capabilities;
+    }
 }
diff --git a/src/com/android/services/telephony/PstnConnectionService.java b/src/com/android/services/telephony/PstnConnectionService.java
index 82165da..f60cd73 100644
--- a/src/com/android/services/telephony/PstnConnectionService.java
+++ b/src/com/android/services/telephony/PstnConnectionService.java
@@ -19,6 +19,7 @@
 import android.net.Uri;
 
 import android.telephony.DisconnectCause;
+import android.telecomm.CallCapabilities;
 import android.telecomm.Connection;
 import android.telecomm.ConnectionRequest;
 import android.telecomm.Response;
@@ -200,7 +201,7 @@
         // TODO: Create a more general framework for conferencing. At the moment, our goal is
         // simply not to break the previous GSM-specific conferencing functionality.
         if (connection instanceof GsmConnection || connection instanceof ConferenceConnection) {
-            if (connection.isConferenceCapable()) {
+            if ((connection.getCallCapabilities() & CallCapabilities.MERGE_CALLS) != 0) {
                 callback.onResult(token,
                         mGsmConferenceController.createConferenceConnection(connection));
             }
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 1cfabbb..17ab1c9 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -29,7 +29,7 @@
 /**
  * Manages a single phone call in Telephony.
  */
-class TelephonyConnection extends Connection {
+abstract class TelephonyConnection extends Connection {
     private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 1;
 
     private final StateHandler mHandler = new StateHandler();
@@ -135,6 +135,15 @@
         super.onSetAudioState(audioState);
     }
 
+    protected abstract int buildCallCapabilities();
+
+    final void updateCallCapabilities() {
+        int newCallCapabilities = buildCallCapabilities();
+        if (getCallCapabilities() != newCallCapabilities) {
+            setCallCapabilities(newCallCapabilities);
+        }
+    }
+
     protected void hangup(int disconnectCause) {
         if (mOriginalConnection != null) {
             try {
@@ -188,6 +197,7 @@
                 case DISCONNECTING:
                     break;
             }
+            updateCallCapabilities();
         }
     }
 
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 717049c..0cefab6 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -111,12 +111,14 @@
             final TelephonyConnection telephonyConnection =
                     createTelephonyConnection(request, phone, connection);
             respondWithResult(request, response, telephonyConnection);
+            telephonyConnection.updateCallCapabilities();
 
             final com.android.internal.telephony.Connection connectionFinal = connection;
             PostDialListener postDialListener = new PostDialListener() {
                 @Override
                 public void onPostDialWait() {
-                    telephonyConnection.setPostDialWait(connectionFinal.getRemainingPostDialString());
+                    telephonyConnection.setPostDialWait(
+                            connectionFinal.getRemainingPostDialString());
                 }
             };
             connection.addPostDialListener(postDialListener);