merge in lmp-mr1-release history after reset to 8e4dae587f8a4dd20b06c16e4f7fd3723ff56774
diff --git a/res/xml/call_feature_setting.xml b/res/xml/call_feature_setting.xml
index e1bc216..6dedd1d 100644
--- a/res/xml/call_feature_setting.xml
+++ b/res/xml/call_feature_setting.xml
@@ -90,6 +90,12 @@
     </PreferenceScreen>
 
     <CheckBoxPreference
+        android:key="button_enable_video_calling"
+        android:title="@string/enable_video_calling_title"
+        android:persistent="true"
+        android:defaultValue="true" />
+
+    <CheckBoxPreference
         android:key="button_auto_retry_key"
         android:title="@string/auto_retry_mode_title"
         android:persistent="false"
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 6fae770..e59f4fb 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -184,6 +184,8 @@
     private static final String PHONE_ACCOUNT_SETTINGS_KEY =
             "phone_account_settings_preference_screen";
 
+    private static final String ENABLE_VIDEO_CALLING_KEY = "button_enable_video_calling";
+
     private Intent mContactListIntent;
 
     /** Event for Async voicemail change call */
@@ -257,6 +259,7 @@
     private Preference mVoicemailNotificationRingtone;
     private CheckBoxPreference mVoicemailNotificationVibrate;
     private AccountSelectionPreference mDefaultOutgoingAccount;
+    private CheckBoxPreference mEnableVideoCalling;
 
     private class VoiceMailProvider {
         public VoiceMailProvider(String name, Intent intent) {
@@ -534,7 +537,7 @@
     @Override
     public boolean onPreferenceChange(Preference preference, Object objValue) {
         if (DBG) {
-            log("onPreferenceChange(). preferenece: \"" + preference + "\""
+            log("onPreferenceChange(). preference: \"" + preference + "\""
                     + ", value: \"" + objValue + "\"");
         }
 
@@ -577,6 +580,8 @@
                 mChangingVMorFwdDueToProviderChange = true;
                 saveVoiceMailAndForwardingNumber(newProviderKey, newProviderSettings);
             }
+        } else if (preference == mEnableVideoCalling) {
+            PhoneGlobals.getInstance().phoneMgr.enableVideoCalling((boolean) objValue);
         }
         // always let the preference setting proceed.
         return true;
@@ -1557,6 +1562,8 @@
         mButtonHAC = (CheckBoxPreference) findPreference(BUTTON_HAC_KEY);
         mButtonTTY = (ListPreference) findPreference(BUTTON_TTY_KEY);
         mVoicemailProviders = (ListPreference) findPreference(BUTTON_VOICEMAIL_PROVIDER_KEY);
+        CheckBoxPreference mEnableVideoCalling =
+                (CheckBoxPreference) findPreference(ENABLE_VIDEO_CALLING_KEY);
 
         if (mVoicemailProviders != null) {
             mVoicemailProviders.setOnPreferenceChangeListener(this);
@@ -1670,6 +1677,11 @@
                     BUTTON_VOICEMAIL_NOTIFICATION_VIBRATE_KEY, false));
         }
 
+        mEnableVideoCalling.setChecked(PhoneGlobals.getInstance().phoneMgr.isVideoCallingEnabled());
+        mEnableVideoCalling.setOnPreferenceChangeListener(this);
+        // TODO: Perform checks to determine whether we should remove the preference.
+        prefSet.removePreference(mEnableVideoCalling);
+
         // Look up the voicemail ringtone name asynchronously and update its preference.
         new Thread(mVoicemailRingtoneLookupRunnable).start();
     }
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index f9a0989..ffbdebf 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -136,11 +136,12 @@
     AppOpsManager mAppOps;
     MainThreadHandler mMainThreadHandler;
 
-    SharedPreferences carrierPrivilegeConfigs;
+    SharedPreferences mTelephonySharedPreferences;
     private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
     private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
     private static final String PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX =
             "carrier_simplified_network_settings_";
+    private static final String PREF_ENABLE_VIDEO_CALLING = "enable_video_calling";
 
     /**
      * A request object to use for transmitting data to an ICC.
@@ -703,7 +704,7 @@
         mCM = PhoneGlobals.getInstance().mCM;
         mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
         mMainThreadHandler = new MainThreadHandler();
-        carrierPrivilegeConfigs =
+        mTelephonySharedPreferences =
                 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
         publish();
     }
@@ -1947,7 +1948,7 @@
         String iccId = getIccId(subId);
         if (iccId != null) {
             String snsPrefKey = PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX + iccId;
-            SharedPreferences.Editor editor = carrierPrivilegeConfigs.edit();
+            SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
             if (enable) {
                 editor.putBoolean(snsPrefKey, true);
             } else {
@@ -1963,7 +1964,7 @@
         String iccId = getIccId(subId);
         if (iccId != null) {
             String snsPrefKey = PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX + iccId;
-            return carrierPrivilegeConfigs.getBoolean(snsPrefKey, false);
+            return mTelephonySharedPreferences.getBoolean(snsPrefKey, false);
         }
         return false;
     }
@@ -1975,7 +1976,7 @@
         String iccId = getIccId(subId);
         if (iccId != null) {
             String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
-            SharedPreferences.Editor editor = carrierPrivilegeConfigs.edit();
+            SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
             if (alphaTag == null) {
                 editor.remove(alphaTagPrefKey);
             } else {
@@ -1999,7 +2000,7 @@
         String iccId = getIccId(subId);
         if (iccId != null) {
             String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
-            return carrierPrivilegeConfigs.getString(numberPrefKey, null);
+            return mTelephonySharedPreferences.getString(numberPrefKey, null);
         }
         return null;
     }
@@ -2011,7 +2012,7 @@
         String iccId = getIccId(subId);
         if (iccId != null) {
             String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
-            return carrierPrivilegeConfigs.getString(alphaTagPrefKey, null);
+            return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
         }
         return null;
     }
@@ -2067,4 +2068,18 @@
     public int getRadioAccessFamily(int phoneId) {
         return ProxyController.getInstance().getRadioAccessFamily(phoneId);
     }
+
+    @Override
+    public void enableVideoCalling(boolean enable) {
+        enforceModifyPermission();
+        SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
+        editor.putBoolean(PREF_ENABLE_VIDEO_CALLING, enable);
+        editor.commit();
+    }
+
+    @Override
+    public boolean isVideoCallingEnabled() {
+        enforceReadPermission();
+        return mTelephonySharedPreferences.getBoolean(PREF_ENABLE_VIDEO_CALLING, true);
+    }
 }
diff --git a/src/com/android/phone/TelephonyDebugService.java b/src/com/android/phone/TelephonyDebugService.java
index fdfe8f5..8503574 100644
--- a/src/com/android/phone/TelephonyDebugService.java
+++ b/src/com/android/phone/TelephonyDebugService.java
@@ -47,6 +47,8 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
+                                       "Requires DUMP");
         mDebugService.dump(fd, pw, args);
     }
 }
diff --git a/src/com/android/services/telephony/GsmConference.java b/src/com/android/services/telephony/TelephonyConference.java
similarity index 83%
rename from src/com/android/services/telephony/GsmConference.java
rename to src/com/android/services/telephony/TelephonyConference.java
index 44abc77..b493523 100644
--- a/src/com/android/services/telephony/GsmConference.java
+++ b/src/com/android/services/telephony/TelephonyConference.java
@@ -28,11 +28,12 @@
 import java.util.List;
 
 /**
- * GSM-based conference call.
+ * TelephonyConnection-based conference call for GSM conferences and IMS conferences (which may
+ * be either GSM-based or CDMA-based).
  */
-public class GsmConference extends Conference {
+public class TelephonyConference extends Conference {
 
-    public GsmConference(PhoneAccountHandle phoneAccount) {
+    public TelephonyConference(PhoneAccountHandle phoneAccount) {
         super(phoneAccount);
         setCapabilities(
                 PhoneCapabilities.SUPPORT_HOLD |
@@ -94,7 +95,7 @@
      */
     @Override
     public void onHold() {
-        final GsmConnection connection = getFirstConnection();
+        final TelephonyConnection connection = getFirstConnection();
         if (connection != null) {
             connection.performHold();
         }
@@ -105,7 +106,7 @@
      */
     @Override
     public void onUnhold() {
-        final GsmConnection connection = getFirstConnection();
+        final TelephonyConnection connection = getFirstConnection();
         if (connection != null) {
             connection.performUnhold();
         }
@@ -113,7 +114,7 @@
 
     @Override
     public void onPlayDtmfTone(char c) {
-        final GsmConnection connection = getFirstConnection();
+        final TelephonyConnection connection = getFirstConnection();
         if (connection != null) {
             connection.onPlayDtmfTone(c);
         }
@@ -121,7 +122,7 @@
 
     @Override
     public void onStopDtmfTone() {
-        final GsmConnection connection = getFirstConnection();
+        final TelephonyConnection connection = getFirstConnection();
         if (connection != null) {
             connection.onStopDtmfTone();
         }
@@ -142,19 +143,19 @@
     private com.android.internal.telephony.Connection getOriginalConnection(
             Connection connection, String tag) {
 
-        if (connection instanceof GsmConnection) {
-            return ((GsmConnection) connection).getOriginalConnection();
+        if (connection instanceof TelephonyConnection) {
+            return ((TelephonyConnection) connection).getOriginalConnection();
         } else {
-            Log.e(this, null, "Non GSM connection found in a Gsm conference (%s)", tag);
+            Log.e(this, null, "Non TelephonyConnection found in a TelephonyConference (%s)", tag);
             return null;
         }
     }
 
-    private GsmConnection getFirstConnection() {
+    private TelephonyConnection getFirstConnection() {
         final List<Connection> connections = getConnections();
         if (connections.isEmpty()) {
             return null;
         }
-        return (GsmConnection) connections.get(0);
+        return (TelephonyConnection) connections.get(0);
     }
 }
diff --git a/src/com/android/services/telephony/GsmConferenceController.java b/src/com/android/services/telephony/TelephonyConferenceController.java
similarity index 67%
rename from src/com/android/services/telephony/GsmConferenceController.java
rename to src/com/android/services/telephony/TelephonyConferenceController.java
index b6aaaf9..5786b25 100644
--- a/src/com/android/services/telephony/GsmConferenceController.java
+++ b/src/com/android/services/telephony/TelephonyConferenceController.java
@@ -29,11 +29,13 @@
 import com.android.internal.telephony.Call;
 
 /**
- * Maintains a list of all the known GSM connections and implements GSM-specific conference
- * call functionality.
+ * Maintains a list of all the known TelephonyConnections connections and controls GSM and
+ * default IMS conference call behavior. This functionality is characterized by the support of
+ * two top-level calls, in contrast to a CDMA conference call which automatically starts a
+ * conference when there are two calls.
  */
-final class GsmConferenceController {
-    private static final int GSM_CONFERENCE_MAX_SIZE = 5;
+final class TelephonyConferenceController {
+    private static final int TELEPHONY_CONFERENCE_MAX_SIZE = 5;
 
     private final Connection.Listener mConnectionListener = new Connection.Listener() {
         @Override
@@ -49,31 +51,31 @@
 
         @Override
         public void onDestroyed(Connection connection) {
-            remove((GsmConnection) connection);
+            remove((TelephonyConnection) connection);
         }
     };
 
-    /** The known GSM connections. */
-    private final List<GsmConnection> mGsmConnections = new ArrayList<>();
+    /** The known connections. */
+    private final List<TelephonyConnection> mTelephonyConnections = new ArrayList<>();
 
     private final TelephonyConnectionService mConnectionService;
 
-    public GsmConferenceController(TelephonyConnectionService connectionService) {
+    public TelephonyConferenceController(TelephonyConnectionService connectionService) {
         mConnectionService = connectionService;
     }
 
-    /** The GSM conference connection object. */
-    private Conference mGsmConference;
+    /** The TelephonyConference connection object. */
+    private TelephonyConference mTelephonyConference;
 
-    void add(GsmConnection connection) {
-        mGsmConnections.add(connection);
+    void add(TelephonyConnection connection) {
+        mTelephonyConnections.add(connection);
         connection.addConnectionListener(mConnectionListener);
         recalculate();
     }
 
-    void remove(GsmConnection connection) {
+    void remove(TelephonyConnection connection) {
         connection.removeConnectionListener(mConnectionListener);
-        mGsmConnections.remove(connection);
+        mTelephonyConnections.remove(connection);
         recalculate();
     }
 
@@ -83,7 +85,7 @@
     }
 
     private boolean isFullConference(Conference conference) {
-        return conference.getConnections().size() >= GSM_CONFERENCE_MAX_SIZE;
+        return conference.getConnections().size() >= TELEPHONY_CONFERENCE_MAX_SIZE;
     }
 
     private boolean participatesInFullConference(Connection connection) {
@@ -95,13 +97,13 @@
      * Calculates the conference-capable state of all GSM connections in this connection service.
      */
     private void recalculateConferenceable() {
-        Log.v(this, "recalculateConferenceable : %d", mGsmConnections.size());
+        Log.v(this, "recalculateConferenceable : %d", mTelephonyConnections.size());
 
-        List<Connection> activeConnections = new ArrayList<>(mGsmConnections.size());
-        List<Connection> backgroundConnections = new ArrayList<>(mGsmConnections.size());
+        List<Connection> activeConnections = new ArrayList<>(mTelephonyConnections.size());
+        List<Connection> backgroundConnections = new ArrayList<>(mTelephonyConnections.size());
 
         // Loop through and collect all calls which are active or holding
-        for (GsmConnection connection : mGsmConnections) {
+        for (Connection connection : mTelephonyConnections) {
             Log.d(this, "recalc - %s %s", connection.getState(), connection);
 
             if (!participatesInFullConference(connection)) {
@@ -136,23 +138,24 @@
         }
 
         // Set the conference as conferenceable with all the connections
-        if (mGsmConference != null && !isFullConference(mGsmConference)) {
-            List<Connection> nonConferencedConnections = new ArrayList<>(mGsmConnections.size());
-            for (GsmConnection c : mGsmConnections) {
+        if (mTelephonyConference != null && !isFullConference(mTelephonyConference)) {
+            List<Connection> nonConferencedConnections =
+                    new ArrayList<>(mTelephonyConnections.size());
+            for (TelephonyConnection c : mTelephonyConnections) {
                 if (c.getConference() == null) {
                     nonConferencedConnections.add(c);
                 }
             }
-            mGsmConference.setConferenceableConnections(nonConferencedConnections);
+            mTelephonyConference.setConferenceableConnections(nonConferencedConnections);
         }
 
         // TODO: Do not allow conferencing of already conferenced connections.
     }
 
     private void recalculateConference() {
-        Set<GsmConnection> conferencedConnections = new HashSet<>();
+        Set<TelephonyConnection> conferencedConnections = new HashSet<>();
 
-        for (GsmConnection connection : mGsmConnections) {
+        for (TelephonyConnection connection : mTelephonyConnections) {
             com.android.internal.telephony.Connection radioConnection =
                 connection.getOriginalConnection();
 
@@ -167,50 +170,50 @@
         }
 
         Log.d(this, "Recalculate conference calls %s %s.",
-                mGsmConference, conferencedConnections);
+                mTelephonyConference, conferencedConnections);
 
         if (conferencedConnections.size() < 2) {
             Log.d(this, "less than two conference calls!");
             // No more connections are conferenced, destroy any existing conference.
-            if (mGsmConference != null) {
+            if (mTelephonyConference != null) {
                 Log.d(this, "with a conference to destroy!");
-                mGsmConference.destroy();
-                mGsmConference = null;
+                mTelephonyConference.destroy();
+                mTelephonyConference = null;
             }
         } else {
-            if (mGsmConference != null) {
-                List<Connection> existingConnections = mGsmConference.getConnections();
+            if (mTelephonyConference != null) {
+                List<Connection> existingConnections = mTelephonyConference.getConnections();
                 // Remove any that no longer exist
                 for (Connection connection : existingConnections) {
                     if (!conferencedConnections.contains(connection)) {
-                        mGsmConference.removeConnection(connection);
+                        mTelephonyConference.removeConnection(connection);
                     }
                 }
 
                 // Add any new ones
                 for (Connection connection : conferencedConnections) {
                     if (!existingConnections.contains(connection)) {
-                        mGsmConference.addConnection(connection);
+                        mTelephonyConference.addConnection(connection);
                     }
                 }
             } else {
-                mGsmConference = new GsmConference(null);
+                mTelephonyConference = new TelephonyConference(null);
                 for (Connection connection : conferencedConnections) {
                     Log.d(this, "Adding a connection to a conference call: %s %s",
-                            mGsmConference, connection);
-                    mGsmConference.addConnection(connection);
+                            mTelephonyConference, connection);
+                    mTelephonyConference.addConnection(connection);
                 }
-                mConnectionService.addConference(mGsmConference);
+                mConnectionService.addConference(mTelephonyConference);
             }
 
             // Set the conference state to the same state as its child connections.
-            Connection conferencedConnection = mGsmConference.getConnections().get(0);
+            Connection conferencedConnection = mTelephonyConference.getConnections().get(0);
             switch (conferencedConnection.getState()) {
                 case Connection.STATE_ACTIVE:
-                    mGsmConference.setActive();
+                    mTelephonyConference.setActive();
                     break;
                 case Connection.STATE_HOLDING:
-                    mGsmConference.setOnHold();
+                    mTelephonyConference.setOnHold();
                     break;
             }
         }
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 73a57d3..9d309dc 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -48,8 +48,8 @@
  * Service for making GSM and CDMA connections.
  */
 public class TelephonyConnectionService extends ConnectionService {
-    private final GsmConferenceController mGsmConferenceController =
-            new GsmConferenceController(this);
+    private final TelephonyConferenceController mTelephonyConferenceController =
+            new TelephonyConferenceController(this);
     private final CdmaConferenceController mCdmaConferenceController =
             new CdmaConferenceController(this);
     private ComponentName mExpectedComponentName = null;
@@ -348,13 +348,17 @@
         int phoneType = phone.getPhoneType();
         if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
             GsmConnection connection = new GsmConnection(originalConnection);
-            mGsmConferenceController.add(connection);
+            mTelephonyConferenceController.add(connection);
             return connection;
         } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
             boolean allowMute = allowMute(phone);
             CdmaConnection connection = new CdmaConnection(
                     originalConnection, mEmergencyTonePlayer, allowMute, isOutgoing);
-            mCdmaConferenceController.add(connection);
+            if (connection.isImsConnection()) {
+                mTelephonyConferenceController.add(connection);
+            } else {
+                mCdmaConferenceController.add(connection);
+            }
             return connection;
         } else {
             return null;