Merge "Update GsmConference state to the same as its child calls." into lmp-dev
diff --git a/res/drawable-hdpi/ic_emergency_callback_mode.png b/res/drawable-hdpi/ic_emergency_callback_mode.png
new file mode 100644
index 0000000..1902e72
--- /dev/null
+++ b/res/drawable-hdpi/ic_emergency_callback_mode.png
Binary files differ
diff --git a/res/drawable-hdpi/picture_emergency25x25.png b/res/drawable-hdpi/picture_emergency25x25.png
deleted file mode 100644
index 0a6d3c4..0000000
--- a/res/drawable-hdpi/picture_emergency25x25.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/picture_emergency32x32.png b/res/drawable-hdpi/picture_emergency32x32.png
deleted file mode 100644
index 89c05e3..0000000
--- a/res/drawable-hdpi/picture_emergency32x32.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-ldrtl-hdpi/ic_emergency_callback_mode.png b/res/drawable-ldrtl-hdpi/ic_emergency_callback_mode.png
new file mode 100644
index 0000000..0c796b5
--- /dev/null
+++ b/res/drawable-ldrtl-hdpi/ic_emergency_callback_mode.png
Binary files differ
diff --git a/res/drawable-ldrtl-hdpi/picture_emergency25x25.png b/res/drawable-ldrtl-hdpi/picture_emergency25x25.png
deleted file mode 100644
index 9a70b6d..0000000
--- a/res/drawable-ldrtl-hdpi/picture_emergency25x25.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-ldrtl-hdpi/picture_emergency32x32.png b/res/drawable-ldrtl-hdpi/picture_emergency32x32.png
deleted file mode 100644
index 89e1b07..0000000
--- a/res/drawable-ldrtl-hdpi/picture_emergency32x32.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-ldrtl-mdpi/ic_emergency_callback_mode.png b/res/drawable-ldrtl-mdpi/ic_emergency_callback_mode.png
new file mode 100644
index 0000000..1507310
--- /dev/null
+++ b/res/drawable-ldrtl-mdpi/ic_emergency_callback_mode.png
Binary files differ
diff --git a/res/drawable-ldrtl-mdpi/picture_emergency25x25.png b/res/drawable-ldrtl-mdpi/picture_emergency25x25.png
deleted file mode 100644
index 9a70b6d..0000000
--- a/res/drawable-ldrtl-mdpi/picture_emergency25x25.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-ldrtl-mdpi/picture_emergency32x32.png b/res/drawable-ldrtl-mdpi/picture_emergency32x32.png
deleted file mode 100644
index 89e1b07..0000000
--- a/res/drawable-ldrtl-mdpi/picture_emergency32x32.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-ldrtl-xhdpi/ic_emergency_callback_mode.png b/res/drawable-ldrtl-xhdpi/ic_emergency_callback_mode.png
new file mode 100644
index 0000000..7c2f9f1
--- /dev/null
+++ b/res/drawable-ldrtl-xhdpi/ic_emergency_callback_mode.png
Binary files differ
diff --git a/res/drawable-ldrtl-xhdpi/picture_emergency25x25.png b/res/drawable-ldrtl-xhdpi/picture_emergency25x25.png
deleted file mode 100644
index e4b9342..0000000
--- a/res/drawable-ldrtl-xhdpi/picture_emergency25x25.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-ldrtl-xhdpi/picture_emergency32x32.png b/res/drawable-ldrtl-xhdpi/picture_emergency32x32.png
deleted file mode 100644
index ddc2642..0000000
--- a/res/drawable-ldrtl-xhdpi/picture_emergency32x32.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-ldrtl-xxhdpi/ic_emergency_callback_mode.png b/res/drawable-ldrtl-xxhdpi/ic_emergency_callback_mode.png
new file mode 100644
index 0000000..c08186b
--- /dev/null
+++ b/res/drawable-ldrtl-xxhdpi/ic_emergency_callback_mode.png
Binary files differ
diff --git a/res/drawable-ldrtl-xxxhdpi/ic_emergency_callback_mode.png b/res/drawable-ldrtl-xxxhdpi/ic_emergency_callback_mode.png
new file mode 100644
index 0000000..9487cf4
--- /dev/null
+++ b/res/drawable-ldrtl-xxxhdpi/ic_emergency_callback_mode.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_emergency_callback_mode.png b/res/drawable-mdpi/ic_emergency_callback_mode.png
new file mode 100644
index 0000000..d4e5f5d
--- /dev/null
+++ b/res/drawable-mdpi/ic_emergency_callback_mode.png
Binary files differ
diff --git a/res/drawable-mdpi/picture_emergency25x25.png b/res/drawable-mdpi/picture_emergency25x25.png
deleted file mode 100644
index 0a6d3c4..0000000
--- a/res/drawable-mdpi/picture_emergency25x25.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/picture_emergency32x32.png b/res/drawable-mdpi/picture_emergency32x32.png
deleted file mode 100644
index 89c05e3..0000000
--- a/res/drawable-mdpi/picture_emergency32x32.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_emergency_callback_mode.png b/res/drawable-xhdpi/ic_emergency_callback_mode.png
new file mode 100644
index 0000000..cde9cea
--- /dev/null
+++ b/res/drawable-xhdpi/ic_emergency_callback_mode.png
Binary files differ
diff --git a/res/drawable-xhdpi/picture_emergency25x25.png b/res/drawable-xhdpi/picture_emergency25x25.png
deleted file mode 100644
index 1284dcc..0000000
--- a/res/drawable-xhdpi/picture_emergency25x25.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/picture_emergency32x32.png b/res/drawable-xhdpi/picture_emergency32x32.png
deleted file mode 100644
index 75fdec2..0000000
--- a/res/drawable-xhdpi/picture_emergency32x32.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_emergency_callback_mode.png b/res/drawable-xxhdpi/ic_emergency_callback_mode.png
new file mode 100644
index 0000000..b761bc4
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_emergency_callback_mode.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_emergency_callback_mode.png b/res/drawable-xxxhdpi/ic_emergency_callback_mode.png
new file mode 100644
index 0000000..0e71cf0
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_emergency_callback_mode.png
Binary files differ
diff --git a/res/values-mcc001-mnc01/config.xml b/res/values-mcc001-mnc01/config.xml
new file mode 100644
index 0000000..3e6a69b
--- /dev/null
+++ b/res/values-mcc001-mnc01/config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Phone app resources that may need to be customized
+     for different hardware or product builds. -->
+<resources>
+    <!-- Show APN Settings for some CDMA carriers -->
+    <bool name="config_show_apn_setting_cdma">true</bool>
+</resources>
diff --git a/res/values-mcc001-mnc010/config.xml b/res/values-mcc001-mnc010/config.xml
new file mode 100644
index 0000000..3e6a69b
--- /dev/null
+++ b/res/values-mcc001-mnc010/config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Phone app resources that may need to be customized
+     for different hardware or product builds. -->
+<resources>
+    <!-- Show APN Settings for some CDMA carriers -->
+    <bool name="config_show_apn_setting_cdma">true</bool>
+</resources>
diff --git a/res/values-mcc246-mnc081/config.xml b/res/values-mcc246-mnc081/config.xml
new file mode 100644
index 0000000..3e6a69b
--- /dev/null
+++ b/res/values-mcc246-mnc081/config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Phone app resources that may need to be customized
+     for different hardware or product builds. -->
+<resources>
+    <!-- Show APN Settings for some CDMA carriers -->
+    <bool name="config_show_apn_setting_cdma">true</bool>
+</resources>
diff --git a/res/values-mcc310-mnc028/config.xml b/res/values-mcc310-mnc028/config.xml
new file mode 100644
index 0000000..3e6a69b
--- /dev/null
+++ b/res/values-mcc310-mnc028/config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Phone app resources that may need to be customized
+     for different hardware or product builds. -->
+<resources>
+    <!-- Show APN Settings for some CDMA carriers -->
+    <bool name="config_show_apn_setting_cdma">true</bool>
+</resources>
diff --git a/res/values-mcc311-mnc390/config.xml b/res/values-mcc311-mnc390/config.xml
new file mode 100644
index 0000000..3e6a69b
--- /dev/null
+++ b/res/values-mcc311-mnc390/config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Phone app resources that may need to be customized
+     for different hardware or product builds. -->
+<resources>
+    <!-- Show APN Settings for some CDMA carriers -->
+    <bool name="config_show_apn_setting_cdma">true</bool>
+</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index cfca00b..0ced13f 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -138,11 +138,9 @@
     <string name="carrier_settings" translatable="false"></string>
     <string name="carrier_settings_menu" translatable="false"></string>
 
-    <!-- Default connection service setting.
-         TODO: This is GSM specific. Need to define a generic "use the builtin SIMs" Connection
-         Service and use it as the default. -->
-    <string name="connection_service_default" translatable="false">com.android.phone/com.android.services.telephony.TelephonyConnectionService</string>
-
     <!-- Does not display additional call seting for IMS phone based on GSM Phone -->
     <bool name="config_additional_call_setting">true</bool>
+
+    <!-- Show APN Settings for some CDMA carriers -->
+    <bool name="config_show_apn_setting_cdma">false</bool>
 </resources>
diff --git a/res/xml/cdma_options.xml b/res/xml/cdma_options.xml
index 60889a6..d4eaeba 100644
--- a/res/xml/cdma_options.xml
+++ b/res/xml/cdma_options.xml
@@ -34,6 +34,15 @@
         android:dialogTitle="@string/cdma_subscription_dialogtitle" />
 
     <PreferenceScreen
+        android:key="button_apn_key"
+        android:title="@string/apn_settings"
+        android:persistent="false">
+
+        <!-- The launching Intent will be defined thru code as we need to pass some Extra -->
+
+    </PreferenceScreen>
+
+    <PreferenceScreen
         android:key="cdma_activate_device_key"
         android:title="@string/cdma_activate_device">
         <intent android:action="com.android.phone.PERFORM_VOICELESS_CDMA_PROVISIONING">
diff --git a/src/com/android/phone/BluetoothPhoneService.java b/src/com/android/phone/BluetoothPhoneService.java
index 87940a0..653d671 100644
--- a/src/com/android/phone/BluetoothPhoneService.java
+++ b/src/com/android/phone/BluetoothPhoneService.java
@@ -22,8 +22,10 @@
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.IBluetoothHeadsetPhone;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.IBinder;
@@ -97,6 +99,20 @@
 
     private static final int GSM_MAX_CONNECTIONS = 6;  // Max connections allowed by GSM
     private static final int CDMA_MAX_CONNECTIONS = 2;  // Max connections allowed by CDMA
+    private IntentFilter mIntentFilter;
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
+            if (VDBG) Log.d(TAG, "Received BLUETOOTH_STATE_CHANGED_ACTION state:" + state);
+            if(state == BluetoothAdapter.STATE_ON) {
+                if (DBG) Log.d(TAG, "Bluetooth Turned ON, query phone state");
+                Message msg = Message.obtain(mHandler, QUERY_PHONE_STATE);
+                mHandler.sendMessage(msg);
+            }
+        }
+    };
 
     @Override
     public void onCreate() {
@@ -124,12 +140,14 @@
 
         handlePreciseCallStateChange(null);
 
-        if(VDBG) Log.d(TAG, "registerForServiceStateChanged");
+        if(VDBG) Log.d(TAG, "onCreate register for updates");
         // register for updates
         mCM.registerForPreciseCallStateChanged(mHandler, PRECISE_CALL_STATE_CHANGED, null);
         mCM.registerForCallWaiting(mHandler, PHONE_CDMA_CALL_WAITING, null);
         mCM.registerForDisconnect(mHandler, PHONE_ON_DISCONNECT, null);
 
+        mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
+        this.registerReceiver(mReceiver, mIntentFilter);
         // TODO(BT) registerForIncomingRing?
         mClccTimestamps = new long[GSM_MAX_CONNECTIONS];
         mClccUsed = new boolean[GSM_MAX_CONNECTIONS];
@@ -151,6 +169,7 @@
     public void onDestroy() {
         super.onDestroy();
         if (DBG) log("Stopping Bluetooth BluetoothPhoneService Service");
+        this.unregisterReceiver(mReceiver);
     }
 
     @Override
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 103606a..aa01862 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -160,7 +160,6 @@
 
     // String keys for preference lookup
     // TODO: Naming these "BUTTON_*" is confusing since they're not actually buttons(!)
-    private static final String BUTTON_DEFAULT_CONNECTION_SERVICE = "button_connection_service";
     private static final String BUTTON_VOICEMAIL_KEY = "button_voicemail_key";
     private static final String BUTTON_VOICEMAIL_PROVIDER_KEY = "button_voicemail_provider_key";
     private static final String BUTTON_VOICEMAIL_SETTING_KEY = "button_voicemail_setting_key";
@@ -261,14 +260,11 @@
     private ListPreference mButtonSipCallOptions;
     private Preference mWifiCallOptionsPreference;
     private Preference mWifiCallAccountPreference;
-    private ListPreference mConnectionService;
     private ListPreference mVoicemailProviders;
     private PreferenceScreen mVoicemailSettings;
     private Preference mVoicemailNotificationRingtone;
     private CheckBoxPreference mVoicemailNotificationVibrate;
     private SipSharedPreferences mSipSharedPreferences;
-    private final Map<String, CharSequence> mConnectionServiceLabelByComponentName =
-            new HashMap<>();
 
     private class VoiceMailProvider {
         public VoiceMailProvider(String name, Intent intent) {
@@ -576,8 +572,6 @@
             }
         } else if (preference == mButtonSipCallOptions) {
             handleSipCallOptionsChange(objValue);
-        } else if (preference == mConnectionService) {
-            updateConnectionServiceSummary((String) objValue);
         }
         // always let the preference setting proceed.
         return true;
@@ -1515,8 +1509,6 @@
         mButtonAutoRetry = (CheckBoxPreference) findPreference(BUTTON_RETRY_KEY);
         mButtonHAC = (CheckBoxPreference) findPreference(BUTTON_HAC_KEY);
         mButtonTTY = (ListPreference) findPreference(BUTTON_TTY_KEY);
-        mConnectionService = (ListPreference)
-                findPreference(BUTTON_DEFAULT_CONNECTION_SERVICE);
         mVoicemailProviders = (ListPreference) findPreference(BUTTON_VOICEMAIL_PROVIDER_KEY);
 
         if (mVoicemailProviders != null) {
@@ -1646,12 +1638,6 @@
             actionBar.setDisplayHomeAsUpEnabled(true);
             actionBar.setDisplayShowTitleEnabled(true);
         }
-
-        if (mConnectionService != null) {
-            mConnectionService.setOnPreferenceChangeListener(this);
-            setupConnectionServiceOptions();
-            updateConnectionServiceSummary(null);
-        }
     }
 
     private void createSipCallSettings() {
@@ -2106,66 +2092,6 @@
         return super.onOptionsItemSelected(item);
     }
 
-    private void setupConnectionServiceOptions() {
-        loadConnectionServiceEntries();
-        String[] entryValues = new String[mConnectionServiceLabelByComponentName.size()];
-        CharSequence[] entries = new CharSequence[mConnectionServiceLabelByComponentName.size()];
-        int i = 0;
-        for (String entryValue : mConnectionServiceLabelByComponentName.keySet()) {
-            entryValues[i] = entryValue;
-            entries[i] = mConnectionServiceLabelByComponentName.get(entryValue);
-            i++;
-        }
-        mConnectionService.setEntryValues(entryValues);
-        mConnectionService.setEntries(entries);
-
-        if (mConnectionService.getValue() == null) {
-            mConnectionService.setValue(getString(R.string.connection_service_default));
-        }
-    }
-
-    private void updateConnectionServiceSummary(String value) {
-        CharSequence label = mConnectionServiceLabelByComponentName.get(
-                value == null ? mConnectionService.getValue() : value);
-        if (label == null) {
-            Log.w(LOG_TAG, "Unknown default connection service entry " +
-                    mConnectionService.getValue());
-            mConnectionService.setSummary("");
-        }
-        mConnectionService.setSummary(label);
-    }
-
-    private void loadConnectionServiceEntries() {
-        Intent intent = new Intent(ConnectionService.SERVICE_INTERFACE);
-        for (ResolveInfo entry : getPackageManager().queryIntentServices(intent, 0)) {
-            ServiceInfo serviceInfo = entry.serviceInfo;
-            if (serviceInfo != null) {
-                // The entry resolves to a proper service, add it to the list of service names
-                ComponentName componentName =
-                        new ComponentName(serviceInfo.packageName, serviceInfo.name);
-                mConnectionServiceLabelByComponentName.put(
-                        componentName.flattenToString(),
-                        serviceInfo.loadLabel(getPackageManager()));
-            }
-        }
-
-        // If the default built-in ConnectionService is not installed, according to the package
-        // manager, then in a newly initialized system, Telecomm is going to read the preference
-        // and find the service to be nonexistent. Telecomm should have error checking for this
-        // case, but it is problematic and it's hard to program around it. Here we simply pretend
-        // like the built-in default is installed anyway (so the default value defined in the XML
-        // for the ListPreference points to something useful and does not throw an NPE) and proceed.
-        String connectionServiceDefault = getString(R.string.connection_service_default);
-        if (!mConnectionServiceLabelByComponentName.containsKey(connectionServiceDefault)) {
-            Log.w(LOG_TAG, "Package manager reports built-in ConnectionService not installed: "
-                    + connectionServiceDefault);
-        } else {
-            mConnectionServiceLabelByComponentName.put(
-                    connectionServiceDefault,
-                    getString(R.string.connection_service_default_label));
-        }
-    }
-
     /**
      * Finish current Activity and go up to the top level Settings ({@link CallFeaturesSetting}).
      * This is useful for implementing "HomeAsUp" capability for second-level Settings.
diff --git a/src/com/android/phone/CdmaOptions.java b/src/com/android/phone/CdmaOptions.java
index 8971fa4..50a6def 100644
--- a/src/com/android/phone/CdmaOptions.java
+++ b/src/com/android/phone/CdmaOptions.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.net.Uri;
 import android.os.SystemProperties;
 import android.preference.Preference;
@@ -39,11 +40,13 @@
 
     private CdmaSystemSelectListPreference mButtonCdmaSystemSelect;
     private CdmaSubscriptionListPreference mButtonCdmaSubscription;
+    private PreferenceScreen mButtonAPNExpand;
 
     private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key";
     private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key";
     private static final String BUTTON_CDMA_ACTIVATE_DEVICE_KEY = "cdma_activate_device_key";
     private static final String BUTTON_CARRIER_SETTINGS_KEY = "carrier_settings_key";
+    private static final String BUTTON_APN_EXPAND_KEY = "button_apn_key";
 
     private PreferenceActivity mPrefActivity;
     private PreferenceScreen mPrefScreen;
@@ -59,6 +62,31 @@
     protected void create() {
         mPrefActivity.addPreferencesFromResource(R.xml.cdma_options);
 
+        mButtonAPNExpand = (PreferenceScreen) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
+        boolean removedAPNExpand = false;
+        Resources res = mPrefActivity.getResources();
+        // Some CDMA carriers want the APN settings
+        if (!res.getBoolean(R.bool.config_show_apn_setting_cdma) && mButtonAPNExpand != null) {
+            mPrefScreen.removePreference(mButtonAPNExpand);
+            removedAPNExpand = true;
+        }
+        if (!removedAPNExpand) {
+            mButtonAPNExpand.setOnPreferenceClickListener(
+                    new Preference.OnPreferenceClickListener() {
+                        @Override
+                        public boolean onPreferenceClick(Preference preference) {
+                            // We need to build the Intent by hand as the Preference Framework
+                            // does not allow to add an Intent with some extras into a Preference
+                            // XML file
+                            final Intent intent = new Intent(Settings.ACTION_APN_SETTINGS);
+                            // This will setup the Home and Search affordance
+                            intent.putExtra(":settings:show_fragment_as_subsetting", true);
+                            mPrefActivity.startActivity(intent);
+                            return true;
+                        }
+            });
+        }
+
         mButtonCdmaSystemSelect = (CdmaSystemSelectListPreference)mPrefScreen
                 .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY);
 
diff --git a/src/com/android/phone/EmergencyCallbackModeExitDialog.java b/src/com/android/phone/EmergencyCallbackModeExitDialog.java
index 7758b23..921b7f7 100644
--- a/src/com/android/phone/EmergencyCallbackModeExitDialog.java
+++ b/src/com/android/phone/EmergencyCallbackModeExitDialog.java
@@ -205,7 +205,7 @@
         case EXIT_ECM_DIALOG:
             CharSequence text = getDialogText(mEcmTimeout);
             mAlertDialog = new AlertDialog.Builder(EmergencyCallbackModeExitDialog.this)
-                    .setIcon(R.drawable.picture_emergency32x32)
+                    .setIcon(R.drawable.ic_emergency_callback_mode)
                     .setTitle(R.string.phone_in_ecm_notification_title)
                     .setMessage(text)
                     .setPositiveButton(R.string.alert_dialog_yes,
@@ -233,7 +233,7 @@
 
         case EXIT_ECM_IN_EMERGENCY_CALL_DIALOG:
             mAlertDialog = new AlertDialog.Builder(EmergencyCallbackModeExitDialog.this)
-                    .setIcon(R.drawable.picture_emergency32x32)
+                    .setIcon(R.drawable.ic_emergency_callback_mode)
                     .setTitle(R.string.phone_in_ecm_notification_title)
                     .setMessage(R.string.alert_dialog_in_ecm_call)
                     .setNeutralButton(R.string.alert_dialog_dismiss,
diff --git a/src/com/android/phone/EmergencyCallbackModeService.java b/src/com/android/phone/EmergencyCallbackModeService.java
index 5309eaf..e1f7fb3 100644
--- a/src/com/android/phone/EmergencyCallbackModeService.java
+++ b/src/com/android/phone/EmergencyCallbackModeService.java
@@ -25,6 +25,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Resources;
+import android.graphics.BitmapFactory;
 import android.os.AsyncResult;
 import android.os.Binder;
 import android.os.CountDownTimer;
@@ -163,16 +164,19 @@
      * Shows notification for Emergency Callback Mode
      */
     private void showNotification(long millisUntilFinished) {
-
-        // Set the icon and text
-        Notification notification = new Notification(
-                R.drawable.picture_emergency25x25,
-                getText(R.string.phone_entered_ecm_text), 0);
+        final Notification.Builder builder = new Notification.Builder(getApplicationContext());
+        builder.setOngoing(true);
+        builder.setPriority(Notification.PRIORITY_HIGH);
+        builder.setSmallIcon(R.drawable.ic_emergency_callback_mode);
+        builder.setTicker(getText(R.string.phone_entered_ecm_text));
+        builder.setContentTitle(getText(R.string.phone_in_ecm_notification_title));
+        builder.setColor(getResources().getColor(R.color.dialer_theme_color));
 
         // PendingIntent to launch Emergency Callback Mode Exit activity if the user selects
         // this notification
         PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                 new Intent(EmergencyCallbackModeExitDialog.ACTION_SHOW_ECM_EXIT_DIALOG), 0);
+        builder.setContentIntent(contentIntent);
 
         // Format notification string
         String text = null;
@@ -184,14 +188,10 @@
             text = String.format(getResources().getQuantityText(
                      R.plurals.phone_in_ecm_notification_time, minutes).toString(), time);
         }
-        // Set the info in the notification
-        notification.setLatestEventInfo(this, getText(R.string.phone_in_ecm_notification_title),
-                text, contentIntent);
-
-        notification.flags = Notification.FLAG_ONGOING_EVENT;
+        builder.setContentText(text);
 
         // Show notification
-        mNotificationManager.notify(R.string.phone_in_ecm_notification_title, notification);
+        mNotificationManager.notify(R.string.phone_in_ecm_notification_title, builder.build());
     }
 
     /**
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 5ca4481..98db518 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -1957,13 +1957,13 @@
     }
 
     @Override
-    public List<String> getCarrierPackageNamesForBroadcastIntent(Intent intent) {
+    public List<String> getCarrierPackageNamesForIntent(Intent intent) {
         UiccCard card = UiccController.getInstance().getUiccCard();
         if (card == null) {
-            loge("getCarrierPackageNamesForBroadcastIntent: No UICC");
+            loge("getCarrierPackageNamesForIntent: No UICC");
             return null ;
         }
-        return card.getCarrierPackageNamesForBroadcastIntent(
+        return card.getCarrierPackageNamesForIntent(
             mPhone.getContext().getPackageManager(), intent);
     }
 
diff --git a/src/com/android/services/telephony/CdmaConnection.java b/src/com/android/services/telephony/CdmaConnection.java
index f13676a..67104b5 100644
--- a/src/com/android/services/telephony/CdmaConnection.java
+++ b/src/com/android/services/telephony/CdmaConnection.java
@@ -24,8 +24,15 @@
  * Manages a single phone call handled by CDMA.
  */
 final class CdmaConnection extends TelephonyConnection {
-    CdmaConnection(Connection connection) {
+
+    /**
+     * {@code True} if the CDMA connection should allow mute.
+     */
+    private final boolean mAllowMute;
+
+    CdmaConnection(Connection connection, boolean allowMute) {
         super(connection);
+        mAllowMute = allowMute;
     }
 
     /** {@inheritDoc} */
@@ -49,7 +56,10 @@
 
     @Override
     protected int buildCallCapabilities() {
-        int capabilities = PhoneCapabilities.MUTE;
+        int capabilities = 0;
+        if (mAllowMute) {
+            capabilities = PhoneCapabilities.MUTE;
+        }
         return capabilities;
     }
 }
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index adb430c..4d9709a 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -39,6 +39,7 @@
 abstract class TelephonyConnection extends Connection {
     private static final int MSG_PRECISE_CALL_STATE_CHANGED = 1;
     private static final int MSG_RINGBACK_TONE = 2;
+    private static final int MSG_HANDOVER_STATE_CHANGED = 3;
 
     private final Handler mHandler = new Handler() {
         @Override
@@ -48,6 +49,13 @@
                     Log.v(TelephonyConnection.this, "MSG_PRECISE_CALL_STATE_CHANGED");
                     updateState();
                     break;
+                case MSG_HANDOVER_STATE_CHANGED:
+                    Log.v(TelephonyConnection.this, "MSG_HANDOVER_STATE_CHANGED");
+                    AsyncResult ar = (AsyncResult) msg.obj;
+                    com.android.internal.telephony.Connection connection =
+                         (com.android.internal.telephony.Connection) ar.result;
+                    setOriginalConnection(connection);
+                    break;
                 case MSG_RINGBACK_TONE:
                     Log.v(TelephonyConnection.this, "MSG_RINGBACK_TONE");
                     // TODO: This code assumes that there is only one connection in the foreground
@@ -289,8 +297,26 @@
         Log.v(this, "performUnhold");
         if (Call.State.HOLDING == mOriginalConnectionState) {
             try {
-                // TODO: This doesn't handle multiple calls across connection services yet
-                mOriginalConnection.getCall().getPhone().switchHoldingAndActive();
+                // Here's the deal--Telephony hold/unhold is weird because whenever there exists
+                // more than one call, one of them must always be active. In other words, if you
+                // have an active call and holding call, and you put the active call on hold, it
+                // will automatically activate the holding call. This is weird with how Telecomm
+                // sends its commands. When a user opts to "unhold" a background call, telecomm
+                // issues hold commands to all active calls, and then the unhold command to the
+                // background call. This means that we get two commands...each of which reduces to
+                // switchHoldingAndActive(). The result is that they simply cancel each other out.
+                // To fix this so that it works well with telecomm we add a minor hack. If we
+                // have one telephony call, everything works as normally expected. But if we have
+                // two or more calls, we will ignore all requests to "unhold" knowing that the hold
+                // requests already do what we want. If you've read up to this point, I'm very sorry
+                // that we are doing this. I didn't think of a better solution that wouldn't also
+                // make the Telecomm APIs very ugly.
+
+                if (!hasMultipleTopLevelCalls()) {
+                    mOriginalConnection.getCall().getPhone().switchHoldingAndActive();
+                } else {
+                    Log.i(this, "Skipping unhold command for %s", this);
+                }
             } catch (CallStateException e) {
                 Log.e(this, e, "Exception occurred while trying to release call from hold.");
             }
@@ -340,9 +366,16 @@
 
     void setOriginalConnection(com.android.internal.telephony.Connection originalConnection) {
         Log.v(this, "new TelephonyConnection, originalConnection: " + originalConnection);
+        if (mOriginalConnection != null) {
+            getPhone().unregisterForPreciseCallStateChanged(mHandler);
+            getPhone().unregisterForRingbackTone(mHandler);
+            getPhone().unregisterForHandoverStateChanged(mHandler);
+        }
         mOriginalConnection = originalConnection;
         getPhone().registerForPreciseCallStateChanged(
                 mHandler, MSG_PRECISE_CALL_STATE_CHANGED, null);
+        getPhone().registerForHandoverStateChanged(
+                mHandler, MSG_HANDOVER_STATE_CHANGED, null);
         getPhone().registerForRingbackTone(mHandler, MSG_RINGBACK_TONE, null);
         mOriginalConnection.addPostDialListener(mPostDialListener);
         mOriginalConnection.addListener(mOriginalConnectionListener);
@@ -360,7 +393,12 @@
     private void hangup(int disconnectCause) {
         if (mOriginalConnection != null) {
             try {
-                mOriginalConnection.hangup();
+                Call call = getCall();
+                if (call != null) {
+                    call.hangup();
+                } else {
+                    Log.w(this, "Attempting to hangup a connection without backing call.");
+                }
             } catch (CallStateException e) {
                 Log.e(this, e, "Call to Connection.hangup failed with exception");
             }
@@ -391,6 +429,23 @@
         return null;
     }
 
+    private boolean hasMultipleTopLevelCalls() {
+        int numCalls = 0;
+        Phone phone = getPhone();
+        if (phone != null) {
+            if (!phone.getRingingCall().isIdle()) {
+                numCalls++;
+            }
+            if (!phone.getForegroundCall().isIdle()) {
+                numCalls++;
+            }
+            if (!phone.getBackgroundCall().isIdle()) {
+                numCalls++;
+            }
+        }
+        return numCalls > 1;
+    }
+
     private com.android.internal.telephony.Connection getForegroundConnection() {
         if (getPhone() != null) {
             return getPhone().getForegroundCall().getEarliestConnection();
@@ -467,6 +522,7 @@
         if (getPhone() != null) {
             getPhone().unregisterForPreciseCallStateChanged(mHandler);
             getPhone().unregisterForRingbackTone(mHandler);
+            getPhone().unregisterForHandoverStateChanged(mHandler);
         }
         mOriginalConnection = null;
         destroy();
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 7c4d1ae..851269d 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -36,7 +36,9 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.SubscriptionController;
+import com.android.internal.telephony.cdma.CDMAPhone;
 import com.android.phone.MMIDialogActivity;
 
 import java.util.Objects;
@@ -120,7 +122,7 @@
             }
         }
 
-        final TelephonyConnection connection = createConnectionFor(phone.getPhoneType(), null);
+        final TelephonyConnection connection = createConnectionFor(phone, null);
         if (connection == null) {
             return Connection.createFailedConnection(
                     DisconnectCause.OUTGOING_FAILURE, "Invalid phone type");
@@ -182,7 +184,7 @@
             return Connection.createCanceledConnection();
         }
 
-        Connection connection = createConnectionFor(phone.getPhoneType(), originalConnection);
+        Connection connection = createConnectionFor(phone, originalConnection);
         if (connection == null) {
             connection = Connection.createCanceledConnection();
             return Connection.createCanceledConnection();
@@ -248,11 +250,13 @@
     }
 
     private TelephonyConnection createConnectionFor(
-            int phoneType, com.android.internal.telephony.Connection originalConnection) {
+            Phone phone, com.android.internal.telephony.Connection originalConnection) {
+        int phoneType = phone.getPhoneType();
         if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
             return new GsmConnection(originalConnection);
         } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
-            return new CdmaConnection(originalConnection);
+            boolean allowMute = allowMute(phone);
+            return new CdmaConnection(originalConnection, allowMute);
         } else {
             return null;
         }
@@ -289,4 +293,26 @@
         }
         return null;
     }
+
+    /**
+     * Determines if the connection should allow mute.
+     *
+     * @param phone The current phone.
+     * @return {@code True} if the connection should allow mute.
+     */
+    private boolean allowMute(Phone phone) {
+        // For CDMA phones, check if we are in Emergency Callback Mode (ECM).  Mute is disallowed
+        // in ECM mode.
+        if (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
+            PhoneProxy phoneProxy = (PhoneProxy)phone;
+            CDMAPhone cdmaPhone = (CDMAPhone)phoneProxy.getActivePhone();
+            if (cdmaPhone != null) {
+                if (cdmaPhone.isInEcm()) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
 }