Add connection properties to Connections.

- Per suggestion of API council, moving properties of a Connection from
CAPABILITIES_* to PROPERTIES_*.

Bug: 27458894
Change-Id: Id9c040c9baf3fae675c55d221b598cd250bd7b3b
diff --git a/src/com/android/services/telephony/CdmaConference.java b/src/com/android/services/telephony/CdmaConference.java
index 5926a9f..19572e9 100755
--- a/src/com/android/services/telephony/CdmaConference.java
+++ b/src/com/android/services/telephony/CdmaConference.java
@@ -17,7 +17,6 @@
 package com.android.services.telephony;
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.os.PersistableBundle;
 import android.telecom.Conference;
 import android.telecom.Connection;
@@ -36,14 +35,18 @@
  */
 public class CdmaConference extends Conference {
     private int mCapabilities;
+    private int mProperties;
 
     public CdmaConference(PhoneAccountHandle phoneAccount) {
         super(phoneAccount);
         setActive();
+
+        mProperties = Connection.PROPERTY_GENERIC_CONFERENCE;
+        setConnectionProperties(mProperties);
     }
 
     public void updateCapabilities(int capabilities) {
-        capabilities |= Connection.CAPABILITY_MUTE | Connection.CAPABILITY_GENERIC_CONFERENCE;
+        capabilities |= Connection.CAPABILITY_MUTE;
         setConnectionCapabilities(capabilities);
     }
 
diff --git a/src/com/android/services/telephony/CdmaConferenceController.java b/src/com/android/services/telephony/CdmaConferenceController.java
index f61f425..9aee300 100644
--- a/src/com/android/services/telephony/CdmaConferenceController.java
+++ b/src/com/android/services/telephony/CdmaConferenceController.java
@@ -35,7 +35,7 @@
  *    indication given to us as to what state they are in.
  *
  * To make life easier on the user we do the following: Whenever there exist 2 or more calls, we
- * say that we are in a conference call with {@link Connection#CAPABILITY_GENERIC_CONFERENCE}.
+ * say that we are in a conference call with {@link Connection#PROPERTY_GENERIC_CONFERENCE}.
  * Generic indicates that this is a simple conference that doesn't support conference management.
  * The conference call will also support "MERGE" to begin with and stop supporting it the first time
  * we are asked to actually execute a merge. I emphasize when "we are asked" because we get no
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 53e7289..69d57d7 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -179,6 +179,14 @@
         }
 
         @Override
+        public void onConnectionPropertiesChanged(Connection c, int connectionProperties) {
+            Log.d(this, "onConnectionPropertiesChanged: Connection: %s," +
+                    " connectionProperties: %s", c, connectionProperties);
+            int properties = ImsConference.this.getConnectionProperties();
+            setConnectionProperties(applyHostProperties(properties, connectionProperties));
+        }
+
+        @Override
         public void onStatusHintsChanged(Connection c, StatusHints statusHints) {
             Log.v(this, "onStatusHintsChanged");
             updateStatusHints();
@@ -282,30 +290,49 @@
      * @return The merged capabilities to be applied to the conference.
      */
     private int applyHostCapabilities(int conferenceCapabilities, int capabilities) {
-        conferenceCapabilities = changeCapability(conferenceCapabilities,
+        conferenceCapabilities = changeBitmask(conferenceCapabilities,
                     Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL,
                     can(capabilities, Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL));
 
-        conferenceCapabilities = changeCapability(conferenceCapabilities,
+        conferenceCapabilities = changeBitmask(conferenceCapabilities,
                     Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL,
                     can(capabilities, Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL));
 
-        conferenceCapabilities = changeCapability(conferenceCapabilities,
+        conferenceCapabilities = changeBitmask(conferenceCapabilities,
                     Connection.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO,
                     can(capabilities, Connection.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO));
 
-        conferenceCapabilities = changeCapability(conferenceCapabilities,
+        conferenceCapabilities = changeBitmask(conferenceCapabilities,
                     Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO,
                     can(capabilities, Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO));
 
-        conferenceCapabilities = changeCapability(conferenceCapabilities,
-                    Connection.CAPABILITY_HIGH_DEF_AUDIO,
-                    can(capabilities, Connection.CAPABILITY_HIGH_DEF_AUDIO));
-
         return conferenceCapabilities;
     }
 
     /**
+     * Transfers properties from the conference host to the conference itself.
+     *
+     * @param conferenceProperties The current conference properties.
+     * @param properties The new conference host properties.
+     * @return The merged properties to be applied to the conference.
+     */
+    private int applyHostProperties(int conferenceProperties, int properties) {
+        conferenceProperties = changeBitmask(conferenceProperties,
+                Connection.PROPERTY_HIGH_DEF_AUDIO,
+                can(properties, Connection.PROPERTY_HIGH_DEF_AUDIO));
+
+        conferenceProperties = changeBitmask(conferenceProperties,
+                Connection.PROPERTY_WIFI,
+                can(properties, Connection.PROPERTY_WIFI));
+
+        conferenceProperties = changeBitmask(conferenceProperties,
+                Connection.PROPERTY_IS_EXTERNAL_CALL,
+                can(properties, Connection.PROPERTY_IS_EXTERNAL_CALL));
+
+        return conferenceProperties;
+    }
+
+    /**
      * Not used by the IMS conference controller.
      *
      * @return {@code Null}.
@@ -455,18 +482,18 @@
     }
 
     /**
-     * Changes a capabilities bit-mask to add or remove a capability.
+     * Changes a bit-mask to add or remove a bit-field.
      *
-     * @param capabilities The capabilities bit-mask.
-     * @param capability The capability to change.
-     * @param enabled Whether the capability should be set or removed.
-     * @return The capabilities bit-mask with the capability changed.
+     * @param bitmask The bit-mask.
+     * @param bitfield The bit-field to change.
+     * @param enabled Whether the bit-field should be set or removed.
+     * @return The bit-mask with the bit-field changed.
      */
-    private int changeCapability(int capabilities, int capability, boolean enabled) {
+    private int changeBitmask(int bitmask, int bitfield, boolean enabled) {
         if (enabled) {
-            return capabilities | capability;
+            return bitmask | bitfield;
         } else {
-            return capabilities & ~capability;
+            return bitmask & ~bitfield;
         }
     }
 
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index d76281f..ba20e74 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -357,15 +357,15 @@
 
     /**
      * Determines if the {@link TelephonyConnection} is using wifi.
-     * This is used when {@link TelephonyConnection#updateConnectionCapabilities} is called to
-     * indicate wheter a call has the {@link Connection#CAPABILITY_WIFI} capability.
+     * This is used when {@link TelephonyConnection#updateConnectionProperties()} is called to
+     * indicate whether a call has the {@link Connection#PROPERTY_WIFI} property.
      */
     private boolean mIsWifi;
 
     /**
      * Determines the audio quality is high for the {@link TelephonyConnection}.
-     * This is used when {@link TelephonyConnection#updateConnectionCapabilities}} is called to
-     * indicate whether a call has the {@link Connection#CAPABILITY_HIGH_DEF_AUDIO} capability.
+     * This is used when {@link TelephonyConnection#updateConnectionProperties}} is called to
+     * indicate whether a call has the {@link Connection#PROPERTY_HIGH_DEF_AUDIO} property.
      */
     private boolean mHasHighDefAudio;
 
@@ -605,12 +605,6 @@
             }
         }
 
-        // If the phone is in ECM mode, mark the call to indicate that the callback number should be
-        // shown.
-        Phone phone = getPhone();
-        if (phone != null && phone.isInEcm()) {
-            callCapabilities |= CAPABILITY_SHOW_CALLBACK_NUMBER;
-        }
         return callCapabilities;
     }
 
@@ -618,10 +612,7 @@
         int newCapabilities = buildConnectionCapabilities();
 
         newCapabilities = applyOriginalConnectionCapabilities(newCapabilities);
-        newCapabilities = changeCapability(newCapabilities,
-                CAPABILITY_HIGH_DEF_AUDIO, mHasHighDefAudio);
-        newCapabilities = changeCapability(newCapabilities, CAPABILITY_WIFI, mIsWifi);
-        newCapabilities = changeCapability(newCapabilities, CAPABILITY_CAN_PAUSE_VIDEO,
+        newCapabilities = changeBitmask(newCapabilities, CAPABILITY_CAN_PAUSE_VIDEO,
                 mIsVideoPauseSupported && isVideoCapable());
         newCapabilities = applyConferenceTerminationCapabilities(newCapabilities);
 
@@ -630,8 +621,36 @@
         }
     }
 
+    protected int buildConnectionProperties() {
+        int connectionProperties = 0;
+
+        // If the phone is in ECM mode, mark the call to indicate that the callback number should be
+        // shown.
+        Phone phone = getPhone();
+        if (phone != null && phone.isInEcm()) {
+            connectionProperties |= PROPERTY_SHOW_CALLBACK_NUMBER;
+        }
+
+        return connectionProperties;
+    }
+
+    /**
+     * Updates the properties of the connection.
+     */
+    protected final void updateConnectionProperties() {
+        int newProperties = buildConnectionProperties();
+
+        newProperties = changeBitmask(newProperties, PROPERTY_HIGH_DEF_AUDIO, mHasHighDefAudio);
+        newProperties = changeBitmask(newProperties, PROPERTY_WIFI, mIsWifi);
+
+        if (getConnectionProperties() != newProperties) {
+            setConnectionProperties(newProperties);
+        }
+    }
+
     protected final void updateAddress() {
         updateConnectionCapabilities();
+        updateConnectionProperties();
         if (mOriginalConnection != null) {
             Uri address = getAddressFromNumber(mOriginalConnection.getAddress());
             int presentation = mOriginalConnection.getNumberPresentation();
@@ -986,6 +1005,7 @@
         updateStateInternal();
         updateStatusHints();
         updateConnectionCapabilities();
+        updateConnectionProperties();
         updateAddress();
         updateMultiparty();
     }
@@ -1108,6 +1128,7 @@
     public void setOriginalConnectionCapabilities(int connectionCapabilities) {
         mOriginalConnectionCapabilities = connectionCapabilities;
         updateConnectionCapabilities();
+        updateConnectionProperties();
     }
 
     /**
@@ -1126,13 +1147,13 @@
         boolean supportsDowngradeToAudio = can(mOriginalConnectionCapabilities,
                 Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL |
                         Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE);
-        capabilities = changeCapability(capabilities,
+        capabilities = changeBitmask(capabilities,
                 CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO, !supportsDowngradeToAudio);
 
-        capabilities = changeCapability(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL,
+        capabilities = changeBitmask(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL,
                 can(mOriginalConnectionCapabilities, Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL));
 
-        capabilities = changeCapability(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL,
+        capabilities = changeBitmask(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL,
                 can(mOriginalConnectionCapabilities, Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL));
 
         return capabilities;
@@ -1140,11 +1161,11 @@
 
     /**
      * Sets whether the call is using wifi. Used when rebuilding the capabilities to set or unset
-     * the {@link Connection#CAPABILITY_WIFI} capability.
+     * the {@link Connection#PROPERTY_WIFI} property.
      */
     public void setWifi(boolean isWifi) {
         mIsWifi = isWifi;
-        updateConnectionCapabilities();
+        updateConnectionProperties();
         updateStatusHints();
     }
 
@@ -1156,15 +1177,15 @@
     }
 
     /**
-     * Sets the current call audio quality. Used during rebuild of the capabilities
-     * to set or unset the {@link Connection#CAPABILITY_HIGH_DEF_AUDIO} capability.
+     * Sets the current call audio quality. Used during rebuild of the properties
+     * to set or unset the {@link Connection#PROPERTY_HIGH_DEF_AUDIO} property.
      *
      * @param audioQuality The audio quality.
      */
     public void setAudioQuality(int audioQuality) {
         mHasHighDefAudio = audioQuality ==
                 com.android.internal.telephony.Connection.AUDIO_QUALITY_HIGH_DEFINITION;
-        updateConnectionCapabilities();
+        updateConnectionProperties();
     }
 
     void resetStateForConference() {
@@ -1238,16 +1259,16 @@
     /**
      * Changes a capabilities bit-mask to add or remove a capability.
      *
-     * @param capabilities The capabilities bit-mask.
-     * @param capability The capability to change.
-     * @param enabled Whether the capability should be set or removed.
-     * @return The capabilities bit-mask with the capability changed.
+     * @param bitmask The bit-mask.
+     * @param bitfield The bit-field to change.
+     * @param enabled Whether the bit-field should be set or removed.
+     * @return The bit-mask with the bit-field changed.
      */
-    private int changeCapability(int capabilities, int capability, boolean enabled) {
+    private int changeBitmask(int bitmask, int bitfield, boolean enabled) {
         if (enabled) {
-            return capabilities | capability;
+            return bitmask | bitfield;
         } else {
-            return capabilities & ~capability;
+            return bitmask & ~bitfield;
         }
     }
 
@@ -1312,7 +1333,7 @@
      * Handles exiting ECM mode.
      */
     protected void handleExitedEcmMode() {
-        updateConnectionCapabilities();
+        updateConnectionProperties();
     }
 
     /**
@@ -1356,6 +1377,8 @@
         sb.append(Connection.stateToString(getState()));
         sb.append(" capabilities:");
         sb.append(capabilitiesToString(getConnectionCapabilities()));
+        sb.append(" properties:");
+        sb.append(propertiesToString(getConnectionProperties()));
         sb.append(" address:");
         sb.append(Log.pii(getAddress()));
         sb.append(" originalConnection:");