Merge "Import translations. DO NOT MERGE" into lmp-preview-dev
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 5eb68f2..b62026b 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -160,7 +160,7 @@
         <item name="android:windowCloseOnTouchOutside">true</item>
     </style>
 
-    <style name="SettingsLight" parent="android:Theme.Quantum.Light">
+    <style name="SettingsLight" parent="android:Theme.Material.Light">
         <item name="android:windowBackground">@color/phone_settings_background_color</item>
         <item name="android:windowContentOverlay">@null</item>
         <item name="android:actionBarStyle">@style/DialtactsActionBarStyle</item>
@@ -235,7 +235,7 @@
     </style>
 
     <!-- Style for the call settings action bar.  Should be kept in sync with Dialer. -->
-    <style name="DialtactsActionBarStyle" parent="android:Widget.Quantum.ActionBar">
+    <style name="DialtactsActionBarStyle" parent="android:Widget.Material.ActionBar">
         <item name="android:background">@color/actionbar_background_color</item>
         <item name="android:titleTextStyle">@style/DialtactsActionBarTitleText</item>
         <item name="android:height">@dimen/action_bar_height</item>
diff --git a/src/com/android/phone/CallController.java b/src/com/android/phone/CallController.java
index cf8abea..0b9482d 100644
--- a/src/com/android/phone/CallController.java
+++ b/src/com/android/phone/CallController.java
@@ -356,9 +356,9 @@
         // (This is just a sanity-check; this policy *should* really be
         // enforced in OutgoingCallBroadcaster.onCreate(), which is the
         // main entry point for the CALL and CALL_* intents.)
-        boolean isEmergencyNumber = PhoneNumberUtils.isLocalEmergencyNumber(number, mApp);
+        boolean isEmergencyNumber = PhoneNumberUtils.isLocalEmergencyNumber(mApp, number);
         boolean isPotentialEmergencyNumber =
-                PhoneNumberUtils.isPotentialLocalEmergencyNumber(number, mApp);
+                PhoneNumberUtils.isPotentialLocalEmergencyNumber(mApp, number);
         boolean isEmergencyIntent = Intent.ACTION_CALL_EMERGENCY.equals(intent.getAction());
 
         if (isPotentialEmergencyNumber && !isEmergencyIntent) {
diff --git a/src/com/android/phone/CallLogger.java b/src/com/android/phone/CallLogger.java
index 9e76db4..8322101 100644
--- a/src/com/android/phone/CallLogger.java
+++ b/src/com/android/phone/CallLogger.java
@@ -109,8 +109,8 @@
      */
     public void logCall(CallerInfo ci, String number, int presentation, int callType, long start,
                         long duration) {
-        final boolean isEmergencyNumber = PhoneNumberUtils.isLocalEmergencyNumber(number,
-                mApplication);
+        final boolean isEmergencyNumber = PhoneNumberUtils.isLocalEmergencyNumber(mApplication,
+                number);
 
         // On some devices, to avoid accidental redialing of
         // emergency numbers, we *never* log emergency calls to
diff --git a/src/com/android/phone/CallModeler.java b/src/com/android/phone/CallModeler.java
index 61cf3e8..0b1cd0e 100644
--- a/src/com/android/phone/CallModeler.java
+++ b/src/com/android/phone/CallModeler.java
@@ -672,8 +672,8 @@
         // emergency callback mode (ECM) is active.
         boolean isEmergencyCall = false;
         if (connection != null) {
-            isEmergencyCall = PhoneNumberUtils.isLocalEmergencyNumber(connection.getAddress(),
-                    phone.getContext());
+            isEmergencyCall = PhoneNumberUtils.isLocalEmergencyNumber(phone.getContext(),
+                    connection.getAddress());
         }
         boolean isECM = PhoneUtils.isPhoneInEcm(phone);
         if (isEmergencyCall || isECM) {  // disable "Mute" item
diff --git a/src/com/android/phone/CallNotifier.java b/src/com/android/phone/CallNotifier.java
index 986c366..f7f5028 100644
--- a/src/com/android/phone/CallNotifier.java
+++ b/src/com/android/phone/CallNotifier.java
@@ -737,8 +737,8 @@
 
         if (fgPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
             Connection c = fgPhone.getForegroundCall().getLatestConnection();
-            if ((c != null) && (PhoneNumberUtils.isLocalEmergencyNumber(c.getAddress(),
-                                                                        mApplication))) {
+            if ((c != null) && (PhoneNumberUtils.isLocalEmergencyNumber(mApplication,
+                                                                        c.getAddress()))) {
                 if (VDBG) log("onPhoneStateChanged: it is an emergency call.");
                 Call.State callState = fgPhone.getForegroundCall().getState();
                 if (mEmergencyTonePlayerVibrator == null) {
@@ -1039,7 +1039,7 @@
             final String number = c.getAddress();
             final Phone phone = c.getCall().getPhone();
             final boolean isEmergencyNumber =
-                    PhoneNumberUtils.isLocalEmergencyNumber(number, mApplication);
+                    PhoneNumberUtils.isLocalEmergencyNumber(mApplication, number);
 
             if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
                 if ((isEmergencyNumber)
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index 26bfc73..db0bb17 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -533,7 +533,7 @@
      */
     private void placeCall() {
         mLastNumber = mDigits.getText().toString();
-        if (PhoneNumberUtils.isLocalEmergencyNumber(mLastNumber, this)) {
+        if (PhoneNumberUtils.isLocalEmergencyNumber(this, mLastNumber)) {
             if (DBG) Log.d(LOG_TAG, "placing call to " + mLastNumber);
 
             // place the call if it is a valid number
diff --git a/src/com/android/phone/OutgoingCallBroadcaster.java b/src/com/android/phone/OutgoingCallBroadcaster.java
index 200071c..636a259 100644
--- a/src/com/android/phone/OutgoingCallBroadcaster.java
+++ b/src/com/android/phone/OutgoingCallBroadcaster.java
@@ -240,7 +240,7 @@
                     && (app.phone.isOtaSpNumber(number))) {
                 if (DBG) Log.v(TAG, "Call is active, a 2nd OTA call cancelled -- returning.");
                 return false;
-            } else if (PhoneNumberUtils.isPotentialLocalEmergencyNumber(number, context)) {
+            } else if (PhoneNumberUtils.isPotentialLocalEmergencyNumber(context, number)) {
                 // Just like 3rd-party apps aren't allowed to place emergency
                 // calls via the ACTION_CALL intent, we also don't allow 3rd
                 // party apps to use the NEW_OUTGOING_CALL broadcast to rewrite
@@ -502,9 +502,9 @@
         // emergency number but might still result in an emergency call
         // with some networks.)
         final boolean isExactEmergencyNumber =
-                (number != null) && PhoneNumberUtils.isLocalEmergencyNumber(number, this);
+                (number != null) && PhoneNumberUtils.isLocalEmergencyNumber(this, number);
         final boolean isPotentialEmergencyNumber =
-                (number != null) && PhoneNumberUtils.isPotentialLocalEmergencyNumber(number, this);
+                (number != null) && PhoneNumberUtils.isPotentialLocalEmergencyNumber(this, number);
         if (VDBG) {
             Log.v(TAG, " - Checking restrictions for number '" + number + "':");
             Log.v(TAG, "     isExactEmergencyNumber     = " + isExactEmergencyNumber);
diff --git a/src/com/android/phone/PhoneUtils.java b/src/com/android/phone/PhoneUtils.java
index f79f057..291789d 100644
--- a/src/com/android/phone/PhoneUtils.java
+++ b/src/com/android/phone/PhoneUtils.java
@@ -2080,8 +2080,8 @@
 
     static boolean isInEmergencyCall(CallManager cm) {
         for (Connection cn : cm.getActiveFgCall().getConnections()) {
-            if (PhoneNumberUtils.isLocalEmergencyNumber(cn.getAddress(),
-                    PhoneGlobals.getInstance())) {
+            if (PhoneNumberUtils.isLocalEmergencyNumber(PhoneGlobals.getInstance(),
+                    cn.getAddress())) {
                 return true;
             }
         }
@@ -2227,8 +2227,8 @@
                      event.getRepeatCount() == 0) {
                 Connection c = phone.getForegroundCall().getLatestConnection();
                 // If it is NOT an emg #, toggle the mute state. Otherwise, ignore the hook.
-                if (c != null && !PhoneNumberUtils.isLocalEmergencyNumber(c.getAddress(),
-                                                                          PhoneGlobals.getInstance())) {
+                if (c != null && !PhoneNumberUtils.isLocalEmergencyNumber(
+                        PhoneGlobals.getInstance(), c.getAddress())) {
                     if (getMute()) {
                         if (DBG) log("handleHeadsetHook: UNmuting...");
                         setMute(false);
diff --git a/src/com/android/services/telephony/PstnConnection.java b/src/com/android/services/telephony/PstnConnection.java
index 6f2c07f..b11c9d0 100644
--- a/src/com/android/services/telephony/PstnConnection.java
+++ b/src/com/android/services/telephony/PstnConnection.java
@@ -95,6 +95,15 @@
         super.onDisconnect();
     }
 
+    @Override
+    public void onPostDialContinue(boolean proceed) {
+        if (proceed) {
+            getOriginalConnection().proceedAfterWaitChar();
+        } else {
+            getOriginalConnection().cancelPostDial();
+        }
+    }
+
     protected Phone getPhone() {
         return mPhone;
     }
diff --git a/src/com/android/services/telephony/PstnConnectionService.java b/src/com/android/services/telephony/PstnConnectionService.java
index cd3598e..21ee41c 100644
--- a/src/com/android/services/telephony/PstnConnectionService.java
+++ b/src/com/android/services/telephony/PstnConnectionService.java
@@ -18,14 +18,15 @@
 
 import android.net.Uri;
 
+import android.telephony.DisconnectCause;
+import android.telecomm.Connection;
+import android.telecomm.ConnectionRequest;
+import android.telecomm.Response;
 import android.telephony.PhoneNumberUtils;
 
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.Phone;
 import com.android.phone.Constants;
-import android.telecomm.Connection;
-import android.telecomm.ConnectionRequest;
-import android.telecomm.Response;
 
 import java.util.HashSet;
 import java.util.Set;
@@ -52,7 +53,11 @@
 
         if (!canCall(request.getHandle())) {
             Log.d(this, "Cannot place the call with %s", this.getClass().getSimpleName());
-            respondWithError(request, response, "Cannot place call.");
+            respondWithError(
+                    request,
+                    response,
+                    DisconnectCause.ERROR_UNSPECIFIED,  // TODO: Code for "ConnSvc cannot call"
+                    "Cannot place call.");
             return;
         }
 
@@ -71,7 +76,11 @@
                         if (isRadioReady) {
                             startCallWithPhone(phone, request, response);
                         } else {
-                            respondWithError(request, response, "Failed to turn on radio.");
+                            respondWithError(
+                                    request,
+                                    response,
+                                    DisconnectCause.POWER_OFF,
+                                    "Failed to turn on radio.");
                         }
                     }
                 }
@@ -103,6 +112,7 @@
                 respondWithError(
                         request,
                         response,
+                        DisconnectCause.ERROR_UNSPECIFIED,  // Internal error
                         "Cannot set incoming call ID, ringing connection already registered.");
             } else {
                 // Address can be null for blocked calls.
@@ -117,7 +127,11 @@
                 try {
                     telephonyConnection = createTelephonyConnection(request, connection);
                 } catch (Exception e) {
-                    respondWithError(request, response, e.getMessage());
+                    respondWithError(
+                            request,
+                            response,
+                            DisconnectCause.ERROR_UNSPECIFIED,  // Internal error
+                            e.getMessage());
                     return;
                 }
 
@@ -130,6 +144,7 @@
             respondWithError(
                     request,
                     response,
+                    DisconnectCause.INCOMING_MISSED,  // Most likely cause
                     String.format("Found no ringing call, call state: %s", call.getState()));
         }
         super.onCreateIncomingConnection(request, response);
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 185fa57..76d4291 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -17,10 +17,14 @@
 package com.android.services.telephony;
 
 import android.net.Uri;
+import android.telephony.DisconnectCause;
+import android.telephony.ServiceState;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection.PostDialListener;
 import com.android.internal.telephony.Phone;
+
 import android.telecomm.Connection;
 import android.telecomm.ConnectionRequest;
 import android.telecomm.ConnectionService;
@@ -46,7 +50,11 @@
         try {
             respondWithResult(handle, response, canCall(handle) ? new Subscription() : null);
         } catch (Exception e) {
-            respondWithError(handle, response, "onFindSubscriptions error: " + e.toString());
+            respondWithError(
+                    handle,
+                    response,
+                    DisconnectCause.ERROR_UNSPECIFIED,  // Internal error
+                    "onFindSubscriptions error: " + e.toString());
         }
     }
 
@@ -64,18 +72,34 @@
         Log.d(this, "startCallWithPhone: %s.", request);
 
         if (phone == null) {
-            respondWithError(request, response, "Phone is null");
+            respondWithError(
+                    request,
+                    response,
+                    DisconnectCause.ERROR_UNSPECIFIED,  // Generic internal error
+                    "Phone is null");
             return;
         }
 
         if (request.getHandle() == null) {
-            respondWithError(request, response, "Handle is null");
+            respondWithError(
+                    request,
+                    response,
+                    DisconnectCause.NO_PHONE_NUMBER_SUPPLIED,
+                    "Handle is null");
             return;
         }
 
         String number = request.getHandle().getSchemeSpecificPart();
         if (TextUtils.isEmpty(number)) {
-            respondWithError(request, response, "Unable to parse number");
+            respondWithError(
+                    request,
+                    response,
+                    DisconnectCause.INVALID_NUMBER,
+                    "Unable to parse number");
+            return;
+        }
+
+        if (!checkServiceStateForOutgoingCall(phone, request, response)) {
             return;
         }
 
@@ -84,29 +108,96 @@
             connection = phone.dial(number);
         } catch (CallStateException e) {
             Log.e(this, e, "Call to Phone.dial failed with exception");
-            respondWithError(request, response, e.getMessage());
+            respondWithError(
+                    request,
+                    response,
+                    DisconnectCause.ERROR_UNSPECIFIED,  // Generic internal error
+                    e.getMessage());
             return;
         }
 
         if (connection == null) {
-            respondWithError(request, response, "Call to phone.dial failed");
+            respondWithError(
+                    request,
+                    response,
+                    DisconnectCause.ERROR_UNSPECIFIED,  // Generic internal error
+                    "Call to phone.dial failed");
             return;
         }
 
         try {
-            respondWithResult(request, response, createTelephonyConnection(request, connection));
+            final TelephonyConnection telephonyConnection =
+                    createTelephonyConnection(request, connection);
+            respondWithResult(request, response, telephonyConnection);
+
+            final com.android.internal.telephony.Connection connectionCopy = connection;
+            PostDialListener postDialListener = new PostDialListener() {
+                @Override
+                public void onPostDialWait() {
+                    TelephonyConnectionService.this.onPostDialWait(telephonyConnection,
+                            connectionCopy.getRemainingPostDialString());
+                }
+            };
+            connection.addPostDialListener(postDialListener);
         } catch (Exception e) {
             Log.e(this, e, "Call to createConnection failed with exception");
-            respondWithError(request, response, e.getMessage());
+            respondWithError(
+                    request,
+                    response,
+                    DisconnectCause.ERROR_UNSPECIFIED,  // Generic internal error
+                    e.getMessage());
         }
     }
 
+    private boolean checkServiceStateForOutgoingCall(
+            Phone phone,
+            ConnectionRequest request,
+            Response<ConnectionRequest, Connection> response) {
+        int state = phone.getServiceState().getState();
+        switch (state) {
+            case ServiceState.STATE_IN_SERVICE:
+                return true;
+            case ServiceState.STATE_OUT_OF_SERVICE:
+                respondWithError(
+                        request,
+                        response,
+                        DisconnectCause.OUT_OF_SERVICE,
+                        null);
+                break;
+            case ServiceState.STATE_EMERGENCY_ONLY:
+                respondWithError(
+                        request,
+                        response,
+                        DisconnectCause.EMERGENCY_ONLY,
+                        null);
+                break;
+            case ServiceState.STATE_POWER_OFF:
+                respondWithError(
+                        request,
+                        response,
+                        DisconnectCause.POWER_OFF,
+                        null);
+                break;
+            default:
+                // Internal error, but we pass it upwards and do not crash.
+                Log.d(this, "Unrecognized service state %d", state);
+                respondWithError(
+                        request,
+                        response,
+                        DisconnectCause.ERROR_UNSPECIFIED,
+                        "Unrecognized service state " + state);
+                break;
+        }
+        return false;
+    }
+
     protected <REQUEST, RESULT> void respondWithError(
             REQUEST request,
             Response<REQUEST, RESULT> response,
-            String reason) {
-        Log.d(this, "respondWithError %s: %s", request, reason);
-        response.onError(request, reason);
+            int errorCode,
+            String errorMsg) {
+        Log.d(this, "respondWithError %s: %d %s", request, errorCode, errorMsg);
+        response.onError(request, errorCode, errorMsg);
     }
 
     protected void respondWithResult(
@@ -138,6 +229,7 @@
                 sKnownConnections.remove(connection);
             }
         });
+
         return telephonyConnection;
     }