Merge tag 'android-6.0.0_r26' into HEAD

Android 6.0.0 release 26

Conflicts:
	src/com/android/server/telecom/BluetoothPhoneServiceImpl.java
	src/com/android/server/telecom/CallIntentProcessor.java
	src/com/android/server/telecom/CallsManager.java
	src/com/android/server/telecom/components/UserCallIntentProcessor.java

Change-Id: I6282a22460bddf72fe1cd4b178d797c5f82f652e
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 2cf0fd8..5f5d386 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="telecommAppLabel" product="default" msgid="9166784827254469057">"Foonoproepbestuur"</string>
-    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"Foon"</string>
+    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"Bel"</string>
     <string name="unknown" msgid="6878797917991465859">"Onbekend"</string>
     <string name="notification_missedCallTitle" msgid="7554385905572364535">"Gemiste oproep"</string>
     <string name="notification_missedCallsTitle" msgid="1361677948941502522">"Gemiste oproepe"</string>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index ec359db..37f3dea 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="telecommAppLabel" product="default" msgid="9166784827254469057">"Гар утасны Дуудлагын Удирдлага"</string>
-    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"Гар утас"</string>
+    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"Утас"</string>
     <string name="unknown" msgid="6878797917991465859">"Тодорхойгүй"</string>
     <string name="notification_missedCallTitle" msgid="7554385905572364535">"Аваагүй дуудлага"</string>
     <string name="notification_missedCallsTitle" msgid="1361677948941502522">"Аваагүй дуудлагууд"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 06dc193..db7f713 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -39,7 +39,7 @@
     <string name="enable_account_preference_title" msgid="2021848090086481720">"Oproepaccounts"</string>
     <string name="outgoing_call_not_allowed_user_restriction" msgid="8504993498756056279">"Alleen noodoproepen zijn toegestaan door de apparaateigenaar."</string>
     <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"Deze app kan geen uitgaande oproepen starten zonder telefoonrechten."</string>
-    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Als u wilt bellen, moet u een geldig nummer invoeren."</string>
+    <string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"Als je wilt bellen, moet je een geldig nummer invoeren."</string>
     <string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"Oproep kan momenteel niet worden toegevoegd."</string>
     <string name="video_call_not_allowed_if_tty_enabled" msgid="7593649283571253283">"Schakel de TTY-modus uit om videogesprekken te voeren."</string>
     <string name="no_vm_number" msgid="4164780423805688336">"Voicemailnummer ontbreekt"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index b3dfff6..abfbb3d 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="telecommAppLabel" product="default" msgid="9166784827254469057">"Gestão de chamadas do telemóvel"</string>
-    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"Telemóvel"</string>
+    <string name="userCallActivityLabel" product="default" msgid="5415173590855187131">"Telefone"</string>
     <string name="unknown" msgid="6878797917991465859">"Desconhecido"</string>
     <string name="notification_missedCallTitle" msgid="7554385905572364535">"Chamada não atendida"</string>
     <string name="notification_missedCallsTitle" msgid="1361677948941502522">"Chamadas não atendidas"</string>
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 7be5847..e72c32c 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -369,7 +369,6 @@
         mContactsAsyncHelper = contactsAsyncHelper;
         mCallerInfoAsyncQueryFactory = callerInfoAsyncQueryFactory;
         setHandle(handle);
-        setHandle(handle, TelecomManager.PRESENTATION_ALLOWED);
         mGatewayInfo = gatewayInfo;
         setConnectionManagerPhoneAccount(connectionManagerPhoneAccountHandle);
         setTargetPhoneAccount(targetPhoneAccountHandle);
@@ -638,8 +637,12 @@
                 }
             }
 
-            mIsEmergencyCall = mHandle != null && PhoneNumberUtils.isLocalEmergencyNumber(mContext,
-                    mHandle.getSchemeSpecificPart());
+            // Let's not allow resetting of the emergency flag. Once a call becomes an emergency
+            // call, it will remain so for the rest of it's lifetime.
+            if (!mIsEmergencyCall) {
+                mIsEmergencyCall = mHandle != null && PhoneNumberUtils.isLocalEmergencyNumber(
+                        mContext, mHandle.getSchemeSpecificPart());
+            }
             startCallerInfoLookup();
             for (Listener l : mListeners) {
                 l.onHandleChanged(this);
@@ -1693,4 +1696,13 @@
         }
         return CallState.DISCONNECTED;
     }
+
+    /**
+     * Determines if this call is in disconnected state and waiting to be destroyed.
+     *
+     * @return {@code true} if this call is disconected.
+     */
+    public boolean isDisconnected() {
+        return (getState() == CallState.DISCONNECTED || getState() == CallState.ABORTED);
+    }
 }
diff --git a/src/com/android/server/telecom/CallAudioManager.java b/src/com/android/server/telecom/CallAudioManager.java
index 74b4cbb..86129ce 100644
--- a/src/com/android/server/telecom/CallAudioManager.java
+++ b/src/com/android/server/telecom/CallAudioManager.java
@@ -520,7 +520,8 @@
                 Log.v(this, "updateAudioStreamAndMode : no foreground, speeding up MT audio.");
                 requestAudioFocusAndSetMode(AudioManager.STREAM_VOICE_CALL,
                                                          AudioManager.MODE_IN_CALL);
-            } else if (foregroundCall != null && waitingForAccountSelectionCall == null) {
+            } else if (foregroundCall != null && !foregroundCall.isDisconnected() &&
+                    waitingForAccountSelectionCall == null) {
                 // In the case where there is a call that is waiting for account selection,
                 // this will fall back to abandonAudioFocus() below, which temporarily exits
                 // the in-call audio mode. This is to allow TalkBack to speak the "Call with"
@@ -538,7 +539,7 @@
                 Log.v(this, "updateAudioStreamAndMode : tone playing");
                 requestAudioFocusAndSetMode(
                         AudioManager.STREAM_VOICE_CALL, mMostRecentlyUsedMode);
-            } else if (!hasRingingForegroundCall()) {
+            } else if (!hasRingingForegroundCall() && mCallsManager.hasOnlyDisconnectedCalls()) {
                 Log.v(this, "updateAudioStreamAndMode : no ringing call");
                 abandonAudioFocus();
             } else {
diff --git a/src/com/android/server/telecom/CallIntentProcessor.java b/src/com/android/server/telecom/CallIntentProcessor.java
index 3faa4d6..3913de6 100644
--- a/src/com/android/server/telecom/CallIntentProcessor.java
+++ b/src/com/android/server/telecom/CallIntentProcessor.java
@@ -9,6 +9,7 @@
 import android.os.Bundle;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.telecom.Connection;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
@@ -129,6 +130,12 @@
                 + ", isAddParticipant = " + isAddParticipant
                 + ", isCallPull = " + isCallPull);
 
+        // Ensure call subject is passed on to the connection service.
+        if (intent.hasExtra(TelecomManager.EXTRA_CALL_SUBJECT)) {
+            String callsubject = intent.getStringExtra(TelecomManager.EXTRA_CALL_SUBJECT);
+            clientExtras.putString(TelecomManager.EXTRA_CALL_SUBJECT, callsubject);
+        }
+
         final boolean isPrivilegedDialer = intent.getBooleanExtra(KEY_IS_PRIVILEGED_DIALER, false);
 
         // Send to CallsManager to ensure the InCallUI gets kicked off before the broadcast returns
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index 2007f6e..1fe491e 100755
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -148,7 +148,8 @@
         // TODO(vt): Once data usage is available, wire it up here.
         int callFeatures = getCallFeatures(call.getVideoStateHistory());
         logCall(call.getCallerInfo(), logNumber, call.getHandlePresentation(),
-                callLogType, callFeatures, accountHandle, creationTime, age, null);
+                callLogType, callFeatures, accountHandle, creationTime, age, null,
+                call.isEmergencyCall());
     }
 
     /**
@@ -162,6 +163,7 @@
      * @param start The start time of the call, in milliseconds.
      * @param duration The duration of the call, in milliseconds.
      * @param dataUsage The data usage for the call, null if not applicable.
+     * @param isEmergency {@code true} if this is an emergency call, {@code false} otherwise.
      */
     private void logCall(
             CallerInfo callerInfo,
@@ -172,8 +174,8 @@
             PhoneAccountHandle accountHandle,
             long start,
             long duration,
-            Long dataUsage) {
-        boolean isEmergencyNumber = PhoneNumberUtils.isLocalEmergencyNumber(mContext, number);
+            Long dataUsage,
+            boolean isEmergency) {
 
         // On some devices, to avoid accidental redialing of emergency numbers, we *never* log
         // emergency calls to the Call Log.  (This behavior is set on a per-product basis, based
@@ -182,7 +184,7 @@
                 mContext.getResources().getBoolean(R.bool.allow_emergency_numbers_in_call_log);
 
         // Don't log emergency numbers if the device doesn't allow it.
-        final boolean isOkToLogThisCall = !isEmergencyNumber || okToLogEmergencyNumber;
+        final boolean isOkToLogThisCall = !isEmergency || okToLogEmergencyNumber;
 
         sendAddCallBroadcast(callType, duration);
 
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 82a20b6..d027086 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -93,6 +93,7 @@
     private static final int MAXIMUM_LIVE_CALLS = 1;
     private static final int MAXIMUM_HOLD_CALLS = 1;
     private static final int MAXIMUM_RINGING_CALLS = 1;
+    private static final int MAXIMUM_DIALING_CALLS = 1;
     private static final int MAXIMUM_OUTGOING_CALLS = 1;
     private static final int MAXIMUM_TOP_LEVEL_CALLS = 2;
     private static final int MAXIMUM_DSDA_LIVE_CALLS = 2;
@@ -277,7 +278,7 @@
                     new DisconnectCause(android.telephony.DisconnectCause.CALL_BLACKLISTED));
         } else {
             setCallState(incomingCall, CallState.RINGING, "ringing set explicitly");
-            if (hasMaximumRingingCalls(incomingCall.getTargetPhoneAccount().getId())) {
+            if (hasMaximumRingingCalls(incomingCall.getTargetPhoneAccount().getId()) || hasMaximumDialingCalls()) {
                 incomingCall.reject(false, null);
                 // since the call was not added to the list of calls, we have to call the missed
                 // call notifier and the call logger manually.
@@ -477,6 +478,15 @@
         return false;
     }
 
+    boolean hasOnlyDisconnectedCalls() {
+        for (Call call : mCalls) {
+            if (!call.isDisconnected()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     boolean hasVideoCall() {
         for (Call call : mCalls) {
             if (VideoProfile.isVideo(call.getVideoState())) {
@@ -690,13 +700,11 @@
 
         call.setTargetPhoneAccount(phoneAccountHandle);
 
-        boolean isEmergencyCall = TelephonyUtil.shouldProcessAsEmergency(mContext,
-                call.getHandle());
         boolean isPotentialInCallMMICode = isPotentialInCallMMICode(handle);
 
         // Do not support any more live calls.  Our options are to move a call to hold, disconnect
         // a call, or cancel this call altogether.
-        if (!isPotentialInCallMMICode && !makeRoomForOutgoingCall(call, isEmergencyCall)) {
+        if (!isPotentialInCallMMICode && !makeRoomForOutgoingCall(call, call.isEmergencyCall())) {
             // just cancel at this point.
             Log.i(this, "No remaining room for outgoing call: %s", call);
             if (mCalls.contains(call)) {
@@ -708,7 +716,7 @@
         }
 
         boolean needsAccountSelection = phoneAccountHandle == null && accounts.size() > 1 &&
-                !isEmergencyCall;
+                !call.isEmergencyCall();
 
         if (needsAccountSelection) {
             // This is the state where the user is expected to select an account
@@ -770,15 +778,13 @@
                 || mDockManager.isDocked());
         call.setVideoState(videoState);
 
-        boolean isEmergencyCall = TelephonyUtil.shouldProcessAsEmergency(mContext,
-                call.getHandle());
-        if (isEmergencyCall) {
+        if (call.isEmergencyCall()) {
             // Emergency -- CreateConnectionProcessor will choose accounts automatically
             call.setTargetPhoneAccount(null);
         }
 
-        if (call.getTargetPhoneAccount() != null || isEmergencyCall) {
-            if (!isEmergencyCall) {
+        if (call.getTargetPhoneAccount() != null || call.isEmergencyCall()) {
+            if (!call.isEmergencyCall()) {
                 updateLchStatus(call.getTargetPhoneAccount().getId());
             }
             // If the account has been set, proceed to place the outgoing call.
@@ -1756,6 +1762,10 @@
         return MAXIMUM_OUTGOING_CALLS <= getNumCallsWithState(OUTGOING_CALL_STATES);
     }
 
+    private boolean hasMaximumDialingCalls() {
+        return MAXIMUM_DIALING_CALLS <= getNumCallsWithState(CallState.DIALING);
+    }
+
     private boolean makeRoomForOutgoingCall(Call call, boolean isEmergency) {
         if (TelephonyManager.getDefault().getMultiSimConfiguration()
                 == TelephonyManager.MultiSimVariants.DSDA) {
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index 6126e66..b846470 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -297,7 +297,7 @@
     // If we are possibly attempting to call a local emergency number, ensure that the
     // plain PSTN connection services are listed, and nothing else.
     private void adjustAttemptsForEmergency()  {
-        if (TelephonyUtil.shouldProcessAsEmergency(mContext, mCall.getHandle())) {
+        if (mCall.isEmergencyCall()) {
             Log.i(this, "Emergency number detected");
             mAttemptRecords.clear();
             List<PhoneAccount> allAccounts = mPhoneAccountRegistrar.getAllPhoneAccounts();
diff --git a/src/com/android/server/telecom/CreateConnectionTimeout.java b/src/com/android/server/telecom/CreateConnectionTimeout.java
index 45305d5..06dc9ed 100644
--- a/src/com/android/server/telecom/CreateConnectionTimeout.java
+++ b/src/com/android/server/telecom/CreateConnectionTimeout.java
@@ -17,14 +17,10 @@
 package com.android.server.telecom;
 
 import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
 import android.os.Handler;
 import android.os.Looper;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.TelephonyManager;
-import android.telephony.PhoneStateListener;
-import android.telephony.ServiceState;
 
 import java.util.Collection;
 import java.util.Objects;
@@ -32,7 +28,7 @@
 /**
  * Registers a timeout for a call and disconnects the call when the timeout expires.
  */
-final class CreateConnectionTimeout extends PhoneStateListener implements Runnable {
+final class CreateConnectionTimeout implements Runnable {
     private final Context mContext;
     private final PhoneAccountRegistrar mPhoneAccountRegistrar;
     private final ConnectionServiceWrapper mConnectionService;
@@ -43,7 +39,6 @@
 
     CreateConnectionTimeout(Context context, PhoneAccountRegistrar phoneAccountRegistrar,
             ConnectionServiceWrapper service, Call call) {
-        super(Looper.getMainLooper());
         mContext = context;
         mPhoneAccountRegistrar = phoneAccountRegistrar;
         mConnectionService = service;
@@ -53,7 +48,7 @@
     boolean isTimeoutNeededForCall(Collection<PhoneAccountHandle> accounts,
             PhoneAccountHandle currentAccount) {
         // Non-emergency calls timeout automatically at the radio layer. No need for a timeout here.
-        if (!TelephonyUtil.shouldProcessAsEmergency(mContext, mCall.getHandle())) {
+        if (!mCall.isEmergencyCall()) {
             return false;
         }
 
@@ -69,27 +64,27 @@
             return false;
         }
 
-        // To reduce the number of scenarios where a timeout is needed, only use a timeout if
-        // we're connected to Wi-Fi. This ensures that the fallback connection manager has an
-        // alternate route to place the call. TODO: remove this condition or allow connection
-        // managers to specify transports. See http://b/19199181.
-        if (!isConnectedToWifi()) {
+        // Timeout is only supported for SIM call managers that are set by the carrier.
+        if (!Objects.equals(connectionManager.getComponentName(),
+                mPhoneAccountRegistrar.getSystemSimCallManagerComponent())) {
+            Log.d(this, "isTimeoutNeededForCall, not a system sim call manager");
             return false;
         }
 
-        Log.d(this, "isTimeoutNeededForCall, returning true");
+        Log.i(this, "isTimeoutNeededForCall, returning true");
         return true;
     }
 
     void registerTimeout() {
         Log.d(this, "registerTimeout");
         mIsRegistered = true;
-        // First find out the cellular service state. Based on the state we decide whether a timeout
-        // will actually be enforced and if so how long it should be.
-        TelephonyManager telephonyManager =
-            (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
-        telephonyManager.listen(this, PhoneStateListener.LISTEN_SERVICE_STATE);
-        telephonyManager.listen(this, 0);
+
+        long timeoutLengthMillis = getTimeoutLengthMillis();
+        if (timeoutLengthMillis <= 0) {
+            Log.d(this, "registerTimeout, timeout set to %d, skipping", timeoutLengthMillis);
+        } else {
+            mHandler.postDelayed(this, timeoutLengthMillis);
+        }
     }
 
     void unregisterTimeout() {
@@ -103,24 +98,9 @@
     }
 
     @Override
-    public void onServiceStateChanged(ServiceState serviceState) {
-        long timeoutLengthMillis = getTimeoutLengthMillis(serviceState);
-        if (!mIsRegistered) {
-            Log.d(this, "onServiceStateChanged, timeout no longer registered, skipping");
-        } else if (timeoutLengthMillis  <= 0) {
-            Log.d(this, "onServiceStateChanged, timeout set to %d, skipping", timeoutLengthMillis);
-        } else if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
-            // If cellular service is available then don't bother with a timeout.
-            Log.d(this, "onServiceStateChanged, cellular service available, skipping");
-        } else {
-            mHandler.postDelayed(this, timeoutLengthMillis);
-        }
-    }
-
-    @Override
     public void run() {
         if (mIsRegistered && isCallBeingPlaced(mCall)) {
-            Log.d(this, "run, call timed out, calling disconnect");
+            Log.i(this, "run, call timed out, calling disconnect");
             mIsCallTimedOut = true;
             mConnectionService.disconnect(mCall);
         }
@@ -133,24 +113,16 @@
             || state == CallState.DIALING;
     }
 
-    private long getTimeoutLengthMillis(ServiceState serviceState) {
+    private long getTimeoutLengthMillis() {
         // If the radio is off then use a longer timeout. This gives us more time to power on the
         // radio.
-        if (serviceState.getState() == ServiceState.STATE_POWER_OFF) {
+        TelephonyManager telephonyManager =
+            (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        if (telephonyManager.isRadioOn()) {
+            return Timeouts.getEmergencyCallTimeoutMillis(mContext.getContentResolver());
+        } else {
             return Timeouts.getEmergencyCallTimeoutRadioOffMillis(
                     mContext.getContentResolver());
-        } else {
-            return Timeouts.getEmergencyCallTimeoutMillis(mContext.getContentResolver());
         }
     }
-
-    private boolean isConnectedToWifi() {
-        ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
-            Context.CONNECTIVITY_SERVICE);
-        if (cm != null) {
-          NetworkInfo ni = cm.getActiveNetworkInfo();
-          return ni != null && ni.isConnected() && ni.getType() == ConnectivityManager.TYPE_WIFI;
-        }
-        return false;
-    }
 }
diff --git a/src/com/android/server/telecom/InCallWakeLockController.java b/src/com/android/server/telecom/InCallWakeLockController.java
index b6d3820..a6c63c3 100644
--- a/src/com/android/server/telecom/InCallWakeLockController.java
+++ b/src/com/android/server/telecom/InCallWakeLockController.java
@@ -40,6 +40,7 @@
 
         PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mFullWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
+        mFullWakeLock.setReferenceCounted(false);
 
         callsManager.addListener(this);
     }
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index 65847b8..a795d6f 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -286,6 +286,19 @@
         return getSimCallManager(user);
     }
 
+    public ComponentName getSystemSimCallManagerComponent() {
+        String defaultSimCallManager = null;
+        CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(
+                Context.CARRIER_CONFIG_SERVICE);
+        PersistableBundle configBundle = configManager.getConfig();
+        if (configBundle != null) {
+            defaultSimCallManager = configBundle.getString(
+                    CarrierConfigManager.KEY_DEFAULT_SIM_CALL_MANAGER_STRING);
+        }
+        return TextUtils.isEmpty(defaultSimCallManager)
+            ?  null : ComponentName.unflattenFromString(defaultSimCallManager);
+    }
+
     /**
      * Returns the {@link PhoneAccountHandle} corresponding to the currently active SIM Call
      * Manager. SIM Call Manager returned corresponds to the following priority order:
@@ -300,17 +313,7 @@
         String dialerPackage = DefaultDialerManager.getDefaultDialerApplication(mContext, user);
 
         // Check carrier config.
-        String defaultSimCallManager = null;
-        CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(
-                Context.CARRIER_CONFIG_SERVICE);
-        PersistableBundle configBundle = configManager.getConfig();
-        if (configBundle != null) {
-            defaultSimCallManager = configBundle.getString(
-                    CarrierConfigManager.KEY_DEFAULT_SIM_CALL_MANAGER_STRING);
-        }
-
-        ComponentName systemSimCallManagerComponent = TextUtils.isEmpty(defaultSimCallManager) ?
-                null : ComponentName.unflattenFromString(defaultSimCallManager);
+        ComponentName systemSimCallManagerComponent = getSystemSimCallManagerComponent();
 
         PhoneAccountHandle dialerSimCallManager = null;
         PhoneAccountHandle systemSimCallManager = null;
diff --git a/src/com/android/server/telecom/WiredHeadsetManager.java b/src/com/android/server/telecom/WiredHeadsetManager.java
index a61dd6e..ef5f38c 100644
--- a/src/com/android/server/telecom/WiredHeadsetManager.java
+++ b/src/com/android/server/telecom/WiredHeadsetManager.java
@@ -39,7 +39,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
-                boolean isPluggedIn = intent.getIntExtra("state", 0) == 1;
+                boolean isPluggedIn = mAudioManager.isWiredHeadsetOn();
                 Log.v(WiredHeadsetManager.this, "ACTION_HEADSET_PLUG event, plugged in: %b",
                         isPluggedIn);
                 onHeadsetPluggedInChanged(isPluggedIn);
@@ -48,6 +48,7 @@
     }
 
     private final WiredHeadsetBroadcastReceiver mReceiver;
+    private final AudioManager mAudioManager;
     private boolean mIsPluggedIn;
     /**
      * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
@@ -60,8 +61,8 @@
     WiredHeadsetManager(Context context) {
         mReceiver = new WiredHeadsetBroadcastReceiver();
 
-        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-        mIsPluggedIn = audioManager.isWiredHeadsetOn();
+        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        mIsPluggedIn = mAudioManager.isWiredHeadsetOn();
 
         // Register for misc other intent broadcasts.
         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
diff --git a/src/com/android/server/telecom/components/UserCallIntentProcessor.java b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
index d3cf7b4..4db6ba5 100644
--- a/src/com/android/server/telecom/components/UserCallIntentProcessor.java
+++ b/src/com/android/server/telecom/components/UserCallIntentProcessor.java
@@ -81,7 +81,7 @@
         if (Intent.ACTION_CALL.equals(action) ||
                 Intent.ACTION_CALL_PRIVILEGED.equals(action) ||
                 Intent.ACTION_CALL_EMERGENCY.equals(action)) {
-                processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency);
+            processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency);
         }
     }
 
diff --git a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
index f1d1078..ba97304 100644
--- a/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
+++ b/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
@@ -50,10 +50,13 @@
 import android.telecom.DisconnectCause;
 import android.telecom.PhoneAccount;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
 import android.text.BidiFormatter;
 import android.text.TextDirectionHeuristics;
 import android.text.TextUtils;
 
+import java.util.Locale;
+
 // TODO: Needed for move to system service: import com.android.internal.R;
 
 /**
@@ -158,7 +161,22 @@
                     mContext.getString(R.string.notification_missedCallsMsg, mMissedCallCount);
         }
 
-        // Create the notification.
+        // Create a public viewable version of the notification, suitable for display when sensitive
+        // notification content is hidden.
+        Notification.Builder publicBuilder = new Notification.Builder(mContext);
+        publicBuilder.setSmallIcon(android.R.drawable.stat_notify_missed_call)
+                .setColor(mContext.getResources().getColor(R.color.theme_color))
+                .setWhen(call.getCreationTimeMillis())
+                // Show "Phone" for notification title.
+                .setContentTitle(mContext.getText(R.string.userCallActivityLabel))
+                // Notification details shows that there are missed call(s), but does not reveal
+                // the missed caller information.
+                .setContentText(mContext.getText(titleResId))
+                .setContentIntent(createCallLogPendingIntent())
+                .setAutoCancel(true)
+                .setDeleteIntent(createClearMissedCallsPendingIntent());
+
+        // Create the notification suitable for display when sensitive information is showing.
         Notification.Builder builder = new Notification.Builder(mContext);
         builder.setSmallIcon(android.R.drawable.stat_notify_missed_call)
                 .setColor(mContext.getResources().getColor(R.color.theme_color))
@@ -167,7 +185,11 @@
                 .setContentText(expandedText)
                 .setContentIntent(createCallLogPendingIntent())
                 .setAutoCancel(true)
-                .setDeleteIntent(createClearMissedCallsPendingIntent());
+                .setDeleteIntent(createClearMissedCallsPendingIntent())
+                // Include a public version of the notification to be shown when the missed call
+                // notification is shown on the user's lock screen and they have chosen to hide
+                // sensitive notification information.
+                .setPublicVersion(publicBuilder.build());
 
         Uri handleUri = call.getHandle();
         String handle = handleUri == null ? null : handleUri.getSchemeSpecificPart();
@@ -234,6 +256,18 @@
         String handle = call.getHandle() == null ? null : call.getHandle().getSchemeSpecificPart();
         String name = call.getName();
 
+        if (!TextUtils.isEmpty(handle)) {
+            String formattedNumber = PhoneNumberUtils.formatNumber(handle,
+                    getCurrentCountryIso(mContext));
+
+            // The formatted number will be null if there was a problem formatting it, but we can
+            // default to using the unformatted number instead (e.g. a SIP URI may not be able to
+            // be formatted.
+            if (!TextUtils.isEmpty(formattedNumber)) {
+                handle = formattedNumber;
+            }
+        }
+
         if (!TextUtils.isEmpty(name) && TextUtils.isGraphic(name)) {
             return name;
         } else if (!TextUtils.isEmpty(handle)) {
@@ -249,6 +283,26 @@
     }
 
     /**
+     * @return The ISO 3166-1 two letters country code of the country the user is in based on the
+     *      network location.  If the network location does not exist, fall back to the locale
+     *      setting.
+     */
+    private String getCurrentCountryIso(Context context) {
+        // Without framework function calls, this seems to be the most accurate location service
+        // we can rely on.
+        final TelephonyManager telephonyManager =
+                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        String countryIso = telephonyManager.getNetworkCountryIso().toUpperCase();
+
+        if (countryIso == null) {
+            countryIso = Locale.getDefault().getCountry();
+            Log.w(this, "No CountryDetector; falling back to countryIso based on locale: "
+                    + countryIso);
+        }
+        return countryIso;
+    }
+
+    /**
      * Creates a new pending intent that sends the user to the call log.
      *
      * @return The pending intent.
diff --git a/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java b/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java
index cd0800e..c1ced80 100644
--- a/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java
+++ b/testapps/src/com/android/server/telecom/testapps/CallServiceNotifier.java
@@ -111,7 +111,8 @@
                 .setAddress(Uri.parse("tel:555-TEST"))
                 .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
-                        PhoneAccount.CAPABILITY_VIDEO_CALLING)
+                        PhoneAccount.CAPABILITY_VIDEO_CALLING |
+                        PhoneAccount.CAPABILITY_CALL_SUBJECT)
                 .setIcon(Icon.createWithResource(
                         context.getResources(), R.drawable.stat_sys_phone_call))
                 // TODO: Add icon tint (Color.RED)
@@ -129,7 +130,8 @@
                 .setSubscriptionAddress(Uri.parse("tel:555-TSIM"))
                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
-                        PhoneAccount.CAPABILITY_VIDEO_CALLING)
+                        PhoneAccount.CAPABILITY_VIDEO_CALLING |
+                        PhoneAccount.CAPABILITY_CALL_SUBJECT)
                 .setIcon(Icon.createWithResource(
                         context.getResources(), R.drawable.stat_sys_phone_call))
                 // TODO: Add icon tint (Color.GREEN)
diff --git a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
index 45896f4..7964355 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
@@ -36,6 +36,7 @@
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.util.Log;
+import android.widget.Toast;
 
 import com.android.server.telecom.testapps.R;
 
@@ -299,6 +300,13 @@
         String gatewayPackage = extras.getString(TelecomManager.GATEWAY_PROVIDER_PACKAGE);
         Uri originalHandle = extras.getParcelable(TelecomManager.GATEWAY_ORIGINAL_ADDRESS);
 
+        if (extras.containsKey(TelecomManager.EXTRA_CALL_SUBJECT)) {
+            String callSubject = extras.getString(TelecomManager.EXTRA_CALL_SUBJECT);
+            log("Got subject: " + callSubject);
+            Toast.makeText(getApplicationContext(), "Got subject :" + callSubject,
+                    Toast.LENGTH_SHORT).show();
+        }
+
         log("gateway package [" + gatewayPackage + "], original handle [" +
                 originalHandle + "]");
 
@@ -354,6 +362,24 @@
                     VideoProfile.STATE_BIDIRECTIONAL :
                     VideoProfile.STATE_AUDIO_ONLY;
             connection.setVideoState(videoState);
+
+            Bundle connectionExtras = connection.getExtras();
+            if (connectionExtras == null) {
+                connectionExtras = new Bundle();
+            }
+
+            // Randomly choose a varying length call subject.
+            int subjectFormat = mRandom.nextInt(3);
+            if (subjectFormat == 0) {
+                connectionExtras.putString(Connection.EXTRA_CALL_SUBJECT,
+                        "This is a test of call subject lines. Subjects for a call can be long " +
+                                " and can go even longer.");
+            } else if (subjectFormat == 1) {
+                connectionExtras.putString(Connection.EXTRA_CALL_SUBJECT,
+                        "This is a test of call subject lines.");
+            }
+            connection.setExtras(connectionExtras);
+
             setAddress(connection, address);
 
             addVideoProvider(connection);