Merge "Use CallProperties on Telecomm Call." into lmp-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 43a1f5e..1fcfd23 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -71,7 +71,7 @@
              URL with the schemes "tel", "sip", and "voicemail". It also handles URLs linked to
              contacts provider entries. Any data not fitting the schema described is ignored. -->
         <activity android:name="CallActivity"
-                android:theme="@android:style/Theme.NoDisplay"
+                android:theme="@style/Theme.Telecomm.Transparent"
                 android:permission="android.permission.CALL_PHONE"
                 android:excludeFromRecents="true">
             <!-- CALL action intent filters for the various ways of initiating an outgoing call. -->
@@ -202,12 +202,19 @@
 
         <activity android:name=".PhoneAccountPreferencesActivity"
                   android:label="@string/phone_account_preferences_title"
-                  android:configChanges="orientation|screenSize|keyboardHidden">
-                  android:exported="true" >
+                  android:configChanges="orientation|screenSize|keyboardHidden"
+                  android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
             </intent-filter>
         </activity>
 
+        <activity android:name=".ErrorDialogActivity"
+                android:configChanges="orientation|screenSize|keyboardHidden"
+                android:excludeFromRecents="true"
+                android:launchMode="singleInstance"
+                android:theme="@style/Theme.Telecomm.Transparent">
+        </activity>
+
     </application>
 </manifest>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8f4a2e8..d50d830 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -95,6 +95,17 @@
          due to a user restriction -->
     <string name="outgoing_call_not_allowed">This user is not allowed to make non-emergency phone calls</string>
 
+    <!-- Call failure message displayed in an error dialog used to indicate that a phone number was not provided -->
+    <string name="outgoing_call_error_no_phone_number_supplied">Call not sent, no valid number entered.</string>
+
+    <!-- missing voicemail number -->
+    <!-- Title of the "Missing voicemail number" dialog -->
+    <string name="no_vm_number">Missing voicemail number</string>
+    <!-- Body text of the "Missing voicemail number" dialog -->
+    <string name="no_vm_number_msg">No voicemail number is stored on the SIM card.</string>
+    <!-- Button label on the "Missing voicemail number" dialog -->
+    <string name="add_vm_number_str">Add number</string>
+
     <!-- DO NOT TRANSLATE. Label for test Subscription 0. -->
     <string name="test_account_0_label">Q Mobile</string>
     <!-- DO NOT TRANSLATE. Label for test Subscription 1. -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
new file mode 100644
index 0000000..6b6c1bb
--- /dev/null
+++ b/res/values/styles.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+
+<resources>
+    <style name="Theme.Telecomm.Transparent" parent="@android:style/Theme.Material.Light">
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowContentOverlay">@null</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowIsFloating">true</item>
+        <item name="android:backgroundDimEnabled">true</item>
+        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
+    </style>
+</resources>
diff --git a/src/com/android/telecomm/CallActivity.java b/src/com/android/telecomm/CallActivity.java
index 95dee18..0d36c8a 100644
--- a/src/com/android/telecomm/CallActivity.java
+++ b/src/com/android/telecomm/CallActivity.java
@@ -26,6 +26,7 @@
 import android.os.UserManager;
 import android.telecomm.PhoneAccountHandle;
 import android.telecomm.TelecommManager;
+import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 import android.widget.Toast;
@@ -47,6 +48,7 @@
  * non-emergency numbers just like it did pre-L.
  */
 public class CallActivity extends Activity {
+
     private CallsManager mCallsManager = CallsManager.getInstance();
     private boolean mIsVoiceCapable;
 
@@ -149,9 +151,11 @@
 
         NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
                 mCallsManager, call, intent, isDefaultDialer());
-        final boolean success = broadcaster.processIntent();
+        final int result = broadcaster.processIntent();
+        final boolean success = result == DisconnectCause.NOT_DISCONNECTED;
+
         if (!success && call != null) {
-            call.disconnect();
+            disconnectCallAndShowErrorDialog(call, result);
         }
         setResult(success ? RESULT_OK : RESULT_CANCELED);
     }
@@ -209,4 +213,23 @@
         return getApplicationContext().getResources().getBoolean(
                 com.android.internal.R.bool.config_voice_capable);
     }
+
+    private void disconnectCallAndShowErrorDialog(Call call, int errorCode) {
+        call.disconnect();
+        final Intent errorIntent = new Intent(this, ErrorDialogActivity.class);
+        int errorMessageId = -1;
+        switch (errorCode) {
+            case DisconnectCause.INVALID_NUMBER:
+                errorMessageId = R.string.outgoing_call_error_no_phone_number_supplied;
+                break;
+            case DisconnectCause.VOICEMAIL_NUMBER_MISSING:
+                errorIntent.putExtra(ErrorDialogActivity.SHOW_MISSING_VOICEMAIL_NO_DIALOG_EXTRA,
+                        true);
+                break;
+        }
+        if (errorMessageId != -1) {
+            errorIntent.putExtra(ErrorDialogActivity.ERROR_MESSAGE_ID_EXTRA, errorMessageId);
+        }
+        startActivity(errorIntent);
+    }
 }
diff --git a/src/com/android/telecomm/ErrorDialogActivity.java b/src/com/android/telecomm/ErrorDialogActivity.java
new file mode 100644
index 0000000..098a15f
--- /dev/null
+++ b/src/com/android/telecomm/ErrorDialogActivity.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package com.android.telecomm;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.telecomm.TelecommManager;
+
+/**
+ * Used to display an error dialog from within the Telecomm service when an outgoing call fails
+ */
+public class ErrorDialogActivity extends Activity {
+    private static final String TAG = ErrorDialogActivity.class.getSimpleName();
+
+    public static final String SHOW_MISSING_VOICEMAIL_NO_DIALOG_EXTRA = "show_missing_voicemail";
+    public static final String ERROR_MESSAGE_ID_EXTRA = "error_message_id";
+
+    /**
+     * Intent action to bring up Voicemail Provider settings.
+     */
+    public static final String ACTION_ADD_VOICEMAIL =
+            "com.android.phone.CallFeaturesSetting.ADD_VOICEMAIL";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final boolean showVoicemailDialog = getIntent().getBooleanExtra(
+                SHOW_MISSING_VOICEMAIL_NO_DIALOG_EXTRA, false);
+
+        if (showVoicemailDialog) {
+            showMissingVoicemailErrorDialog();
+        } else {
+            final int error = getIntent().getIntExtra(ERROR_MESSAGE_ID_EXTRA, -1);
+            if (error == -1) {
+                Log.w(TAG, "ErrorDialogActivity called with no error type extra.");
+                finish();
+            } else {
+                showGenericErrorDialog(error);
+            }
+        }
+    }
+
+    private void showGenericErrorDialog(int resid) {
+        final CharSequence msg = getResources().getText(resid);
+        final DialogInterface.OnClickListener clickListener;
+        final DialogInterface.OnCancelListener cancelListener;
+
+        clickListener = new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                finish();
+            }
+        };
+
+        cancelListener = new DialogInterface.OnCancelListener() {
+            @Override
+            public void onCancel(DialogInterface dialog) {
+                finish();
+            }
+        };
+
+        final AlertDialog errorDialog = new AlertDialog.Builder(this)
+                .setMessage(msg).setPositiveButton(android.R.string.ok, clickListener)
+                        .setOnCancelListener(cancelListener).create();
+
+        errorDialog.show();
+    }
+
+    private void showMissingVoicemailErrorDialog() {
+        new AlertDialog.Builder(this)
+                .setTitle(R.string.no_vm_number)
+                .setMessage(R.string.no_vm_number_msg)
+                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            finish();
+                        }})
+                .setNegativeButton(R.string.add_vm_number_str,
+                        new DialogInterface.OnClickListener() {
+                                @Override
+                                public void onClick(DialogInterface dialog, int which) {
+                                    addVoiceMailNumberPanel(dialog);
+                                }})
+                .setOnCancelListener(new DialogInterface.OnCancelListener() {
+                        @Override
+                        public void onCancel(DialogInterface dialog) {
+                            finish();
+                        }}).show();
+    }
+
+
+    private void addVoiceMailNumberPanel(DialogInterface dialog) {
+        if (dialog != null) {
+            dialog.dismiss();
+        }
+
+        // Navigate to the Voicemail setting in the Call Settings activity.
+        Intent intent = new Intent(ACTION_ADD_VOICEMAIL);
+        startActivity(intent);
+        finish();
+    }
+
+    @Override
+    public void finish() {
+        super.finish();
+        // Don't show the return to previous task animation to avoid showing a black screen.
+        // Just dismiss the dialog and undim the previous activity immediately.
+        overridePendingTransition(0, 0);
+    }
+}
diff --git a/src/com/android/telecomm/InCallController.java b/src/com/android/telecomm/InCallController.java
index 0aa53df..21581f5 100644
--- a/src/com/android/telecomm/InCallController.java
+++ b/src/com/android/telecomm/InCallController.java
@@ -426,8 +426,10 @@
         if (CallsManager.getInstance().isAddCallCapable(call)) {
             capabilities |= PhoneCapabilities.ADD_CALL;
         }
-        if (!call.isEmergencyCall()) {
-            capabilities |= PhoneCapabilities.MUTE;
+
+        // Disable mute for emergency calls.
+        if (call.isEmergencyCall()) {
+            capabilities &= ~PhoneCapabilities.MUTE;
         }
 
         int properties = call.isConference() ? CallProperties.CONFERENCE : 0;
diff --git a/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java b/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java
index a45f4ef..1c44fb2 100644
--- a/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/telecomm/NewOutgoingCallIntentBroadcaster.java
@@ -26,6 +26,7 @@
 import android.telecomm.GatewayInfo;
 import android.telecomm.TelecommManager;
 import android.telecomm.VideoProfile;
+import android.telephony.DisconnectCause;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 
@@ -66,6 +67,7 @@
 
     private static final String SCHEME_TEL = "tel";
     private static final String SCHEME_SIP = "sip";
+    private static final String SCHEME_VOICEMAIL = "voicemail";
 
     private final CallsManager mCallsManager;
     private final Call mCall;
@@ -150,9 +152,10 @@
      * - CALL_PRIVILEGED (intent launched by system apps e.g. system Dialer, voice Dialer)
      * - CALL_EMERGENCY (intent launched by lock screen emergency dialer)
      *
-     * @return whether or not the caller was allowed to start the outgoing call.
+     * @return {@link CallActivity#OUTGOING_CALL_SUCCEEDED} if the call succeeded, and an
+     *         appropriate {@link DisconnectCause} if the call did not, describing why it failed.
      */
-    boolean processIntent() {
+    int processIntent() {
         Log.v(this, "Processing call intent in OutgoingCallIntentBroadcaster.");
 
         final Context context = TelecommApp.getInstance();
@@ -161,8 +164,14 @@
         String handle = PhoneNumberUtils.getNumberFromIntent(intent, context);
 
         if (TextUtils.isEmpty(handle)) {
-            Log.w(this, "Empty handle obtained from the call intent.");
-            return false;
+            final Uri data = intent.getData();
+            if (data != null && SCHEME_VOICEMAIL.equals(data.getScheme())) {
+                Log.w(this, "Voicemail scheme provided but no voicemail number set.");
+                return DisconnectCause.VOICEMAIL_NUMBER_MISSING;
+            } else {
+                Log.w(this, "Empty handle obtained from the call intent.");
+                return DisconnectCause.INVALID_NUMBER;
+            }
         }
 
         boolean isUriNumber = PhoneNumberUtils.isUriNumber(handle);
@@ -187,7 +196,7 @@
                     Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s "
                             + "unless caller is system or default dialer.", handle, intent);
                     launchSystemDialer(context, intent.getData());
-                    return false;
+                    return DisconnectCause.OUTGOING_CANCELED;
                 } else {
                     callImmediately = true;
                 }
@@ -196,12 +205,12 @@
             if (!isPotentialEmergencyNumber) {
                 Log.w(this, "Cannot call non-potential-emergency number %s with EMERGENCY_CALL "
                         + "Intent %s.", handle, intent);
-                return false;
+                return DisconnectCause.OUTGOING_CANCELED;
             }
             callImmediately = true;
         } else {
             Log.w(this, "Unhandled Intent %s. Ignoring and not placing call.", intent);
-            return false;
+            return DisconnectCause.INVALID_NUMBER;
         }
 
         if (callImmediately) {
@@ -223,7 +232,7 @@
         }
 
         broadcastIntent(intent, handle, context, !callImmediately);
-        return true;
+        return DisconnectCause.NOT_DISCONNECTED;
     }
 
     /**
diff --git a/src/com/android/telecomm/ProximitySensorManager.java b/src/com/android/telecomm/ProximitySensorManager.java
index c6b018a..287c6d4 100644
--- a/src/com/android/telecomm/ProximitySensorManager.java
+++ b/src/com/android/telecomm/ProximitySensorManager.java
@@ -74,7 +74,7 @@
         if (mProximityWakeLock.isHeld()) {
             Log.i(this, "Releasing proximity wake lock");
             int flags =
-                (screenOnImmediately ? 0 : PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
+                (screenOnImmediately ? 0 : PowerManager.WAIT_FOR_DISTANT_PROXIMITY);
             mProximityWakeLock.release(flags);
         } else {
             Log.i(this, "Proximity wake lock already released");