Merge from master

Change-Id: I20c8bb451376e78b306ac231cf3d6a239a72267e
diff --git a/src/com/android/phone/CallNotifier.java b/src/com/android/phone/CallNotifier.java
index 2b7d2ff..dd1eaab 100644
--- a/src/com/android/phone/CallNotifier.java
+++ b/src/com/android/phone/CallNotifier.java
@@ -18,18 +18,14 @@
 
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallManager;
-import com.android.internal.telephony.CallerInfo;
-import com.android.internal.telephony.CallerInfoAsyncQuery;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.TelephonyCapabilities;
 import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaDisplayInfoRec;
 import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec;
 import com.android.internal.telephony.cdma.SignalToneUtil;
 
-import android.app.ActivityManagerNative;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothProfile;
@@ -37,14 +33,10 @@
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.ToneGenerator;
-import android.net.Uri;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemProperties;
-import android.os.SystemVibrator;
-import android.os.Vibrator;
-import android.provider.CallLog.Calls;
 import android.provider.Settings;
 import android.telecom.TelecomManager;
 import android.telephony.DisconnectCause;
@@ -55,7 +47,6 @@
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
-import android.util.EventLog;
 import android.util.Log;
 
 import java.util.Iterator;
diff --git a/src/com/android/phone/EmergencyCallbackModeService.java b/src/com/android/phone/EmergencyCallbackModeService.java
index 3310df1..997be83 100644
--- a/src/com/android/phone/EmergencyCallbackModeService.java
+++ b/src/com/android/phone/EmergencyCallbackModeService.java
@@ -35,7 +35,6 @@
 import android.os.SystemProperties;
 import android.util.Log;
 
-import com.android.internal.telephony.cdma.CDMAPhone;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneFactory;
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index 100a38c..103d51e 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -33,7 +33,6 @@
 import android.os.UserManager;
 import android.preference.PreferenceManager;
 import android.provider.ContactsContract.PhoneLookup;
-import android.provider.Settings;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
@@ -49,16 +48,13 @@
 import android.widget.Toast;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.TelephonyCapabilities;
 import com.android.phone.settings.VoicemailSettingsActivity;
 import com.android.phone.vvm.omtp.sync.VoicemailStatusQueryHelper;
 import com.android.phone.settings.VoicemailNotificationSettingsUtil;
-import com.android.phone.settings.VoicemailProviderSettingsUtil;
 
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 /**
@@ -681,10 +677,10 @@
                 SharedPreferences sp =
                         PreferenceManager.getDefaultSharedPreferences(mContext);
                 String networkSelection =
-                        sp.getString(PhoneBase.NETWORK_SELECTION_NAME_KEY + subId, "");
+                        sp.getString(Phone.NETWORK_SELECTION_NAME_KEY + subId, "");
                 if (TextUtils.isEmpty(networkSelection)) {
                     networkSelection =
-                            sp.getString(PhoneBase.NETWORK_SELECTION_KEY + subId, "");
+                            sp.getString(Phone.NETWORK_SELECTION_KEY + subId, "");
                 }
 
                 if (DBG) log("updateNetworkSelection()..." + "state = " +
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index d61ef59..6f828db 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -80,12 +80,9 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Objects;
 
 /**
  * Implementation of the ITelephony interface.
@@ -2460,14 +2457,20 @@
     public String getLine1NumberForDisplay(int subId, String callingPackage) {
         // This is open to apps with WRITE_SMS.
         if (!canReadPhoneNumber(callingPackage, "getLine1NumberForDisplay")) {
+            if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
             return null;
         }
 
         String iccId = getIccId(subId);
         if (iccId != null) {
             String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
+            if (DBG_MERGE) {
+                log("getLine1NumberForDisplay returning " +
+                        mTelephonySharedPreferences.getString(numberPrefKey, null));
+            }
             return mTelephonySharedPreferences.getString(numberPrefKey, null);
         }
+        if (DBG_MERGE) log("getLine1NumberForDisplay returning null as iccId is null");
         return null;
     }
 
@@ -2748,7 +2751,7 @@
     }
 
     /**
-     * Besides READ_PHONE_STATE, WRITE_SMS also allows apps to get phone numbers.
+     * Besides READ_PHONE_STATE, WRITE_SMS and READ_SMS also allow apps to get phone numbers.
      */
     private boolean canReadPhoneNumber(String callingPackage, String message) {
         // Default SMS app can always read it.
@@ -2758,11 +2761,19 @@
         }
         try {
             return canReadPhoneState(callingPackage, message);
-        } catch (SecurityException e) {
-            // Can be read with READ_SMS too.
-            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_SMS, message);
-            return mAppOps.noteOp(AppOpsManager.OP_READ_SMS,
-                    Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
+        } catch (SecurityException readPhoneStateSecurityException) {
+            try {
+                // Can be read with READ_SMS too.
+                mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_SMS, message);
+                return mAppOps.noteOp(AppOpsManager.OP_READ_SMS,
+                        Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
+            } catch (SecurityException readSmsSecurityException) {
+                // Throw exception with message including both READ_PHONE_STATE and READ_SMS
+                // permissions
+                throw new SecurityException(message + ": Neither user " + Binder.getCallingUid() +
+                        " nor current process has " + android.Manifest.permission.READ_PHONE_STATE +
+                        " or " + android.Manifest.permission.READ_SMS + ".");
+            }
         }
     }
 
@@ -2880,4 +2891,23 @@
     public ModemActivityInfo getModemActivityInfo() {
         return (ModemActivityInfo) sendRequest(CMD_GET_MODEM_ACTIVITY_INFO, null);
     }
+
+    /**
+     * {@hide}
+     * Returns the service state information on specified subscription.
+     */
+    @Override
+    public ServiceState getServiceStateForSubscriber(int subId, String callingPackage) {
+
+        if (!canReadPhoneState(callingPackage, "getServiceStateForSubscriber")) {
+            return null;
+        }
+
+        final Phone phone = getPhone(subId);
+        if (phone == null) {
+            return null;
+        }
+
+        return phone.getServiceState();
+    }
 }
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
index 3eefbee..0ecf341 100644
--- a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
@@ -62,6 +62,12 @@
         }
 
         SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
+
+        if (messages == null) {
+            Log.w(TAG, "Message does not exist in the intent.");
+            return;
+        }
+
         StringBuilder messageBody = new StringBuilder();
 
         for (int i = 0; i < messages.length; i++) {
@@ -162,4 +168,4 @@
                     /* isEnabled */ false, /* isUserSet */ true);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/services/telephony/CdmaConnection.java b/src/com/android/services/telephony/CdmaConnection.java
index d13f66f..98755be 100644
--- a/src/com/android/services/telephony/CdmaConnection.java
+++ b/src/com/android/services/telephony/CdmaConnection.java
@@ -63,7 +63,7 @@
     /**
      * {@code True} if the CDMA connection should allow mute.
      */
-    private final boolean mAllowMute;
+    private boolean mAllowMute;
     private final boolean mIsOutgoing;
     // Queue of pending short-DTMF characters.
     private final Queue<Character> mDtmfQueue = new LinkedList<>();
@@ -77,8 +77,9 @@
             Connection connection,
             EmergencyTonePlayer emergencyTonePlayer,
             boolean allowMute,
-            boolean isOutgoing) {
-        super(connection);
+            boolean isOutgoing,
+            String telecomCallId) {
+        super(connection, telecomCallId);
         mEmergencyTonePlayer = emergencyTonePlayer;
         mAllowMute = allowMute;
         mIsOutgoing = isOutgoing;
@@ -145,7 +146,7 @@
     @Override
     public TelephonyConnection cloneConnection() {
         CdmaConnection cdmaConnection = new CdmaConnection(getOriginalConnection(),
-                mEmergencyTonePlayer, mAllowMute, mIsOutgoing);
+                mEmergencyTonePlayer, mAllowMute, mIsOutgoing, getTelecomCallId());
         return cdmaConnection;
     }
 
@@ -285,4 +286,15 @@
                 PhoneNumberUtils.isLocalEmergencyNumber(
                     phone.getContext(), getAddress().getSchemeSpecificPart());
     }
+
+    /**
+     * Called when ECM mode is exited; set the connection to allow mute and update the connection
+     * capabilities.
+     */
+    @Override
+    protected void handleExitedEcmMode() {
+        // We allow mute upon existing ECM mode and rebuild the capabilities.
+        mAllowMute = true;
+        super.handleExitedEcmMode();
+    }
 }
diff --git a/src/com/android/services/telephony/GsmConnection.java b/src/com/android/services/telephony/GsmConnection.java
index 1273c60..4bd7a32 100644
--- a/src/com/android/services/telephony/GsmConnection.java
+++ b/src/com/android/services/telephony/GsmConnection.java
@@ -22,8 +22,8 @@
  * Manages a single phone call handled by GSM.
  */
 final class GsmConnection extends TelephonyConnection {
-    GsmConnection(Connection connection) {
-        super(connection);
+    GsmConnection(Connection connection, String telecomCallId) {
+        super(connection, telecomCallId);
     }
 
     /**
@@ -35,7 +35,8 @@
      */
     @Override
     public TelephonyConnection cloneConnection() {
-        GsmConnection gsmConnection = new GsmConnection(getOriginalConnection());
+        GsmConnection gsmConnection = new GsmConnection(getOriginalConnection(),
+                getTelecomCallId());
         return gsmConnection;
     }
 
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 8ccc8f9..790cc13 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -780,7 +780,7 @@
             PhoneAccountHandle phoneAccountHandle =
                     PhoneUtils.makePstnPhoneAccountHandle(mConferenceHost.getPhone());
             if (mConferenceHost.getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
-                GsmConnection c = new GsmConnection(originalConnection);
+                GsmConnection c = new GsmConnection(originalConnection, getTelecomCallId());
                 c.updateState();
                 // Copy the connect time from the conferenceHost
                 c.setConnectTimeMillis(mConferenceHost.getConnectTimeMillis());
@@ -867,6 +867,8 @@
         StringBuilder sb = new StringBuilder();
         sb.append("[ImsConference objId:");
         sb.append(System.identityHashCode(this));
+        sb.append(" telecomCallID:");
+        sb.append(getTelecomCallId());
         sb.append(" state:");
         sb.append(Connection.stateToString(getState()));
         sb.append(" hostConnection:");
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index 7c45657..d0b1c49 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -327,6 +327,7 @@
         conference.addListener(mConferenceListener);
         conference.updateConferenceParticipantsAfterCreation();
         mConnectionService.addConference(conference);
+        conferenceHostConnection.setTelecomCallId(conference.getTelecomCallId());
 
         // Cleanup TelephonyConnection which backed the original connection and remove from telecom.
         // Use the "Other" disconnect cause to ensure the call is logged to the call log but the
diff --git a/src/com/android/services/telephony/PstnIncomingCallNotifier.java b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
index 5f64f6d..6e43e36 100644
--- a/src/com/android/services/telephony/PstnIncomingCallNotifier.java
+++ b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
@@ -27,14 +27,12 @@
 import android.os.Message;
 import android.telecom.PhoneAccount;
 import android.telecom.TelecomManager;
-import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
 import com.android.phone.PhoneUtils;
@@ -53,8 +51,8 @@
     private static final int EVENT_CDMA_CALL_WAITING = 101;
     private static final int EVENT_UNKNOWN_CONNECTION = 102;
 
-    /** The phone proxy object to listen to. */
-    private final PhoneProxy mPhoneProxy;
+    /** The phone object to listen to. */
+    private final Phone mPhone;
 
     /**
      * The base phone implementation behind phone proxy. The underlying phone implementation can
@@ -105,23 +103,23 @@
     /**
      * Persists the specified parameters and starts listening to phone events.
      *
-     * @param phoneProxy The phone object for listening to incoming calls.
+     * @param phone The phone object for listening to incoming calls.
      */
-    PstnIncomingCallNotifier(PhoneProxy phoneProxy) {
-        Preconditions.checkNotNull(phoneProxy);
+    PstnIncomingCallNotifier(Phone phone) {
+        Preconditions.checkNotNull(phone);
 
-        mPhoneProxy = phoneProxy;
+        mPhone = phone;
 
         registerForNotifications();
 
         IntentFilter intentFilter =
                 new IntentFilter(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
-        mPhoneProxy.getContext().registerReceiver(mRATReceiver, intentFilter);
+        mPhone.getContext().registerReceiver(mRATReceiver, intentFilter);
     }
 
     void teardown() {
         unregisterForNotifications();
-        mPhoneProxy.getContext().unregisterReceiver(mRATReceiver);
+        mPhone.getContext().unregisterReceiver(mRATReceiver);
     }
 
     /**
@@ -135,7 +133,7 @@
      * change in opt/telephony code.
      */
     private void registerForNotifications() {
-        Phone newPhone = mPhoneProxy.getActivePhone();
+        Phone newPhone = mPhone;
         if (newPhone != mPhoneBase) {
             unregisterForNotifications();
 
@@ -230,8 +228,8 @@
                 Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, connection.getAddress(), null);
                 extras.putParcelable(TelecomManager.EXTRA_UNKNOWN_CALL_HANDLE, uri);
             }
-            TelecomManager.from(mPhoneProxy.getContext()).addNewUnknownCall(
-                    PhoneUtils.makePstnPhoneAccountHandle(mPhoneProxy), extras);
+            TelecomManager.from(mPhone.getContext()).addNewUnknownCall(
+                    PhoneUtils.makePstnPhoneAccountHandle(mPhone), extras);
         } else {
             Log.i(this, "swapped an old connection, new one is: %s", connection);
         }
@@ -248,8 +246,8 @@
             Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, connection.getAddress(), null);
             extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, uri);
         }
-        TelecomManager.from(mPhoneProxy.getContext()).addNewIncomingCall(
-                PhoneUtils.makePstnPhoneAccountHandle(mPhoneProxy), extras);
+        TelecomManager.from(mPhone.getContext()).addNewIncomingCall(
+                PhoneUtils.makePstnPhoneAccountHandle(mPhone), extras);
     }
 
     /**
diff --git a/src/com/android/services/telephony/PstnPhoneCapabilitiesNotifier.java b/src/com/android/services/telephony/PstnPhoneCapabilitiesNotifier.java
index 7a2adf1..ff3f6d2 100644
--- a/src/com/android/services/telephony/PstnPhoneCapabilitiesNotifier.java
+++ b/src/com/android/services/telephony/PstnPhoneCapabilitiesNotifier.java
@@ -16,10 +16,6 @@
 
 package com.android.services.telephony;
 
-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.Message;
@@ -28,9 +24,6 @@
 import android.telecom.TelecomManager;
 
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.PhoneProxy;
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.Preconditions;
 import com.android.phone.PhoneUtils;
 
@@ -48,9 +41,8 @@
         public void onVideoCapabilitiesChanged(boolean isVideoCapable);
     }
 
-    private final PhoneProxy mPhoneProxy;
+    private final Phone mPhone;
     private final Listener mListener;
-    private Phone mPhoneBase;
 
     private final Handler mHandler = new Handler() {
         @Override
@@ -65,57 +57,33 @@
         }
     };
 
-    private final BroadcastReceiver mRatReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED.equals(action)) {
-                String newPhone = intent.getStringExtra(PhoneConstants.PHONE_NAME_KEY);
-                Log.d(this, "Radio technology switched. Now %s is active.", newPhone);
-
-                registerForNotifications();
-            }
-        }
-    };
-
     /*package*/
-    PstnPhoneCapabilitiesNotifier(PhoneProxy phoneProxy, Listener listener) {
-        Preconditions.checkNotNull(phoneProxy);
+    PstnPhoneCapabilitiesNotifier(Phone phone, Listener listener) {
+        Preconditions.checkNotNull(phone);
 
-        mPhoneProxy = phoneProxy;
+        mPhone = phone;
         mListener = listener;
 
         registerForNotifications();
-
-        IntentFilter intentFilter =
-                new IntentFilter(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
-        mPhoneProxy.getContext().registerReceiver(mRatReceiver, intentFilter);
     }
 
     /*package*/
     void teardown() {
         unregisterForNotifications();
-        mPhoneProxy.getContext().unregisterReceiver(mRatReceiver);
     }
 
     private void registerForNotifications() {
-        Phone newPhone = mPhoneProxy.getActivePhone();
-        if (newPhone != mPhoneBase) {
-            unregisterForNotifications();
-
-            if (newPhone != null) {
-                Log.d(this, "Registering: " + newPhone);
-                mPhoneBase = newPhone;
-                mPhoneBase.registerForVideoCapabilityChanged(
-                        mHandler, EVENT_VIDEO_CAPABILITIES_CHANGED, null);
-            }
+        if (mPhone != null) {
+            Log.d(this, "Registering: " + mPhone);
+            mPhone.registerForVideoCapabilityChanged(mHandler, EVENT_VIDEO_CAPABILITIES_CHANGED,
+                    null);
         }
     }
 
     private void unregisterForNotifications() {
-        if (mPhoneBase != null) {
-            Log.d(this, "Unregistering: " + mPhoneBase);
-            mPhoneBase.unregisterForVideoCapabilityChanged(mHandler);
+        if (mPhone != null) {
+            Log.d(this, "Unregistering: " + mPhone);
+            mPhone.unregisterForVideoCapabilityChanged(mHandler);
         }
     }
 
@@ -124,9 +92,9 @@
             boolean isVideoCapable = (Boolean) ar.result;
             Log.d(this, "handleVideoCapabilitesChanged. Video capability - " + isVideoCapable);
             PhoneAccountHandle accountHandle =
-                    PhoneUtils.makePstnPhoneAccountHandle(mPhoneProxy);
+                    PhoneUtils.makePstnPhoneAccountHandle(mPhone);
 
-            TelecomManager telecomMgr = TelecomManager.from(mPhoneProxy.getContext());
+            TelecomManager telecomMgr = TelecomManager.from(mPhone.getContext());
             PhoneAccount oldPhoneAccount = telecomMgr.getPhoneAccount(accountHandle);
             PhoneAccount.Builder builder = new PhoneAccount.Builder(oldPhoneAccount);
 
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index a07e2e6..4603f3d 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -18,7 +18,6 @@
 
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -41,7 +40,6 @@
 
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
-import com.android.internal.telephony.PhoneProxy;
 import com.android.phone.PhoneGlobals;
 import com.android.phone.PhoneUtils;
 import com.android.phone.R;
@@ -75,8 +73,8 @@
             mAccount = registerPstnPhoneAccount(isEmergency, isDummy);
             Log.i(this, "Registered phoneAccount: %s with handle: %s",
                     mAccount, mAccount.getAccountHandle());
-            mIncomingCallNotifier = new PstnIncomingCallNotifier((PhoneProxy) mPhone);
-            mPhoneCapabilitiesNotifier = new PstnPhoneCapabilitiesNotifier((PhoneProxy) mPhone,
+            mIncomingCallNotifier = new PstnIncomingCallNotifier((Phone) mPhone);
+            mPhoneCapabilitiesNotifier = new PstnPhoneCapabilitiesNotifier((Phone) mPhone,
                     this);
         }
 
diff --git a/src/com/android/services/telephony/TelephonyConferenceController.java b/src/com/android/services/telephony/TelephonyConferenceController.java
index 9724a32..4759982 100644
--- a/src/com/android/services/telephony/TelephonyConferenceController.java
+++ b/src/com/android/services/telephony/TelephonyConferenceController.java
@@ -34,8 +34,6 @@
 import com.android.phone.PhoneUtils;
 
 import com.android.internal.telephony.Call;
-import com.android.internal.telephony.gsm.GsmConnection;
-import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 
 /**
  * Maintains a list of all the known TelephonyConnections connections and controls GSM and
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 5995e53..6068063 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -276,6 +276,15 @@
         public void onExtrasChanged(Bundle extras) {
             mHandler.obtainMessage(MSG_CONNECTION_EXTRAS_CHANGED, extras).sendToTarget();
         }
+
+        /**
+         * Handles the phone exiting ECM mode by updating the connection capabilities.  During an
+         * ongoing call, if ECM mode is exited, we will re-enable mute for CDMA calls.
+         */
+        @Override
+        public void onExitedEcmMode() {
+            handleExitedEcmMode();
+        }
     };
 
     private com.android.internal.telephony.Connection mOriginalConnection;
@@ -339,7 +348,9 @@
     private final Set<TelephonyConnectionListener> mTelephonyListeners = Collections.newSetFromMap(
             new ConcurrentHashMap<TelephonyConnectionListener, Boolean>(8, 0.9f, 1));
 
-    protected TelephonyConnection(com.android.internal.telephony.Connection originalConnection) {
+    protected TelephonyConnection(com.android.internal.telephony.Connection originalConnection,
+            String callId) {
+        setTelecomCallId(callId);
         if (originalConnection != null) {
             setOriginalConnection(originalConnection);
         }
@@ -606,6 +617,7 @@
         clearOriginalConnection();
         mOriginalConnectionExtras.clear();
         mOriginalConnection = originalConnection;
+        mOriginalConnection.setTelecomCallId(getTelecomCallId());
         getPhone().registerForPreciseCallStateChanged(
                 mHandler, MSG_PRECISE_CALL_STATE_CHANGED, null);
         getPhone().registerForHandoverStateChanged(
@@ -911,7 +923,7 @@
      * Note: We post this to the mHandler to ensure that if a conference must be created as a
      * result of the multiparty state change, the conference creation happens on the correct
      * thread.  This ensures that the thread check in
-     * {@link com.android.internal.telephony.PhoneBase#checkCorrectThread(android.os.Handler)}
+     * {@link com.android.internal.telephony.Phone#checkCorrectThread(android.os.Handler)}
      * does not fire.
      *
      * @param isMultiParty {@code true} if this connection is multiparty, {@code false} otherwise.
@@ -1182,6 +1194,12 @@
         }
     }
 
+    /**
+     * Handles exiting ECM mode.
+     */
+    protected void handleExitedEcmMode() {
+        updateConnectionCapabilities();
+    }
 
     /**
      * Provides a mapping from extras keys which may be found in the
@@ -1210,6 +1228,8 @@
         StringBuilder sb = new StringBuilder();
         sb.append("[TelephonyConnection objId:");
         sb.append(System.identityHashCode(this));
+        sb.append(" telecomCallID:");
+        sb.append(getTelecomCallId());
         sb.append(" type:");
         if (isImsConnection()) {
             sb.append("ims");
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index a14a884..5f68d9a 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -41,9 +41,7 @@
 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 com.android.phone.PhoneUtils;
 import com.android.phone.R;
@@ -278,7 +276,8 @@
         }
 
         final TelephonyConnection connection =
-                createConnectionFor(phone, null, true /* isOutgoing */, request.getAccountHandle());
+                createConnectionFor(phone, null, true /* isOutgoing */, request.getAccountHandle(),
+                        request.getTelecomCallId());
         if (connection == null) {
             return Connection.createFailedConnection(
                     DisconnectCauseUtil.toTelecomDisconnectCause(
@@ -353,7 +352,7 @@
 
         Connection connection =
                 createConnectionFor(phone, originalConnection, false /* isOutgoing */,
-                        request.getAccountHandle());
+                        request.getAccountHandle(), request.getTelecomCallId());
         if (connection == null) {
             return Connection.createCanceledConnection();
         } else {
@@ -419,7 +418,7 @@
         TelephonyConnection connection =
                 createConnectionFor(phone, unknownConnection,
                         !unknownConnection.isIncoming() /* isOutgoing */,
-                        request.getAccountHandle());
+                        request.getAccountHandle(), request.getTelecomCallId());
 
         if (connection == null) {
             return Connection.createCanceledConnection();
@@ -481,15 +480,16 @@
             Phone phone,
             com.android.internal.telephony.Connection originalConnection,
             boolean isOutgoing,
-            PhoneAccountHandle phoneAccountHandle) {
+            PhoneAccountHandle phoneAccountHandle,
+            String telecomCallId) {
         TelephonyConnection returnConnection = null;
         int phoneType = phone.getPhoneType();
         if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
-            returnConnection = new GsmConnection(originalConnection);
+            returnConnection = new GsmConnection(originalConnection, telecomCallId);
         } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
             boolean allowMute = allowMute(phone);
             returnConnection = new CdmaConnection(
-                    originalConnection, mEmergencyTonePlayer, allowMute, isOutgoing);
+                    originalConnection, mEmergencyTonePlayer, allowMute, isOutgoing, telecomCallId);
         }
         if (returnConnection != null) {
             // Listen to Telephony specific callbacks from the connection
@@ -578,12 +578,8 @@
         // 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;
-                }
+            if (phone.isInEcm()) {
+                return false;
             }
         }