Merge "Don't update on voicemail fetch if no activity." into ub-contactsdialer-a-dev
diff --git a/res/layout/blocked_number_header.xml b/res/layout/blocked_number_header.xml
index ce1d4fe..29a05bd 100644
--- a/res/layout/blocked_number_header.xml
+++ b/res/layout/blocked_number_header.xml
@@ -17,7 +17,8 @@
     xmlns:card_view="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    android:focusable="false">
 
     <LinearLayout android:id="@+id/blocked_numbers_disabled_for_emergency"
         android:layout_width="match_parent"
@@ -25,6 +26,7 @@
         android:orientation="vertical"
         android:layout_marginBottom="8dp"
         android:padding="16dp"
+        android:focusable="true"
         android:visibility="gone">
 
         <TextView
@@ -58,7 +60,8 @@
             android:gravity="center_vertical"
             android:padding="16dp"
             android:paddingEnd="8dp"
-            android:background="@android:color/white">
+            android:background="@android:color/white"
+            android:focusable="true">
 
             <TextView
                 android:layout_width="0dp"
@@ -70,7 +73,8 @@
             <Switch android:id="@+id/hide_blocked_calls_switch"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginLeft="40dp" />
+                android:layout_marginLeft="40dp"
+                android:focusable="false" />
 
         </LinearLayout>
 
@@ -85,7 +89,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:background="@android:color/white">
+            android:background="@android:color/white"
+            android:focusable="true">
 
             <TextView android:id="@+id/textView"
                 android:layout_width="wrap_content"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b5703c6..f74d2ea 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -883,12 +883,6 @@
     <!-- Heading for the block list in the "Spam and blocked cal)ls" settings. [CHAR LIMIT=64] -->
     <string name="blockList">Block list</string>
 
-    <!-- Label for progress dialog when validating a number to be added to the block list.
-        [CHAR LIMIT=64] -->
-    <string name="checkingNumber">Checking
-        <xliff:g id="number" example="(555) 555-5555">%1$s</xliff:g>
-    </string>
-
     <!-- Error message shown when user tries to add invalid number to the block list.
         [CHAR LIMIT=64] -->
     <string name="invalidNumber"><xliff:g id="number" example="(555) 555-5555">%1$s</xliff:g>
@@ -899,6 +893,19 @@
     <string name="alreadyBlocked"><xliff:g id="number" example="(555) 555-5555">%1$s</xliff:g>
         is already blocked.</string>
 
+    <!-- Title of notification telling the user that call blocking has been temporarily disabled.
+         [CHAR LIMIT=56] -->
+    <string name="call_blocking_disabled_notification_title">
+        Call blocking disabled for 48 hours
+    </string>
+
+    <!-- Text for notification which provides the reason that call blocking has been temporarily
+         disabled. Namely, we disable call blocking after an emergency call in case of return
+         phone calls made by emergency services. [CHAR LIMIT=64] -->
+    <string name="call_blocking_disabled_notification_text">
+        Disabled because an emergency call was made.
+    </string>
+
     <!-- Label for the phone account settings [CHAR LIMIT=30] -->
     <string name="phone_account_settings_label">Calling accounts</string>
 
diff --git a/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
index 25613a6..a8fa06d 100644
--- a/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
+++ b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
@@ -78,6 +78,14 @@
         public void onUnblockComplete(int rows, ContentValues values);
     }
 
+    public interface OnHasBlockedNumbersListener {
+        /**
+         * @param hasBlockedNumbers {@code true} if any blocked numbers are stored.
+         *     {@code false} otherwise.
+         */
+        public void onHasBlockedNumbers(boolean hasBlockedNumbers);
+    }
+
     @Override
     protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
         if (cookie != null) {
@@ -120,6 +128,21 @@
                 null, null, null);
     }
 
+    public final void hasBlockedNumbersAsync(final OnHasBlockedNumbersListener listener) {
+        startQuery(NO_TOKEN,
+                new Listener() {
+                    @Override
+                    protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
+                        listener.onHasBlockedNumbers(cursor.getCount() > 0);
+                    }
+                },
+                getContentUri(null),
+                new String[]{ FilteredNumberColumns._ID },
+                FilteredNumberColumns.TYPE + "=" + FilteredNumberTypes.BLOCKED_NUMBER,
+                null,
+                null);
+    }
+
     /**
      * Check if the number + country iso given has been blocked.
      * This method normalizes the number for the lookup if normalizedNumber is null.
@@ -129,7 +152,7 @@
     public final boolean startBlockedQuery(final OnCheckBlockedListener listener,
                                         String normalizedNumber, String number, String countryIso) {
         if (normalizedNumber == null) {
-            normalizedNumber = getNormalizedNumber(number, countryIso);
+            normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso);
             if (normalizedNumber == null) {
                 return true;
             }
@@ -138,14 +161,6 @@
         return false;
     }
 
-    public static String getNormalizedNumber(String number, String countryIso) {
-        if (PhoneNumberHelper.isUriNumber(number)) {
-            return number;
-        } else {
-            return PhoneNumberUtils.formatNumberToE164(number, countryIso);
-        }
-    }
-
     /**
      * Check if the normalized number given has been blocked.
      */
@@ -182,7 +197,7 @@
     public final void blockNumber(final OnBlockNumberListener listener,
                                   String normalizedNumber, String number, String countryIso) {
         if (normalizedNumber == null) {
-            normalizedNumber = getNormalizedNumber(number, countryIso);
+            normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso);
         }
         ContentValues v = new ContentValues();
         v.put(FilteredNumberColumns.NORMALIZED_NUMBER, normalizedNumber);
diff --git a/src/com/android/dialer/filterednumber/BlockedNumbersFragment.java b/src/com/android/dialer/filterednumber/BlockedNumbersFragment.java
index 56f5fcd..571c94b 100644
--- a/src/com/android/dialer/filterednumber/BlockedNumbersFragment.java
+++ b/src/com/android/dialer/filterednumber/BlockedNumbersFragment.java
@@ -80,6 +80,13 @@
                 FilteredNumbersUtil.setShouldHideBlockedCalls(getActivity(), isChecked);
             }
         });
+        getActivity().findViewById(R.id.hide_blocked_calls_setting).setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(final View view) {
+                        mHideSettingSwitch.toggle();
+                    }
+                });
 
         mImportSettings = getActivity().findViewById(R.id.import_settings);
         mBlockedNumbersDisabledForEmergency =
diff --git a/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
index 8473e32..d7608d8 100644
--- a/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
+++ b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
@@ -21,11 +21,13 @@
 import android.app.DialogFragment;
 import android.app.FragmentManager;
 import android.content.ContentValues;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Bundle;
 import android.support.design.widget.Snackbar;
+import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 import android.view.View;
 import android.widget.Toast;
@@ -58,8 +60,10 @@
     private static final String ARG_DISPLAY_NUMBER = "argDisplayNumber";
     private static final String ARG_PARENT_VIEW_ID = "parentViewId";
 
+    private String mNumber;
     private String mDisplayNumber;
     private String mNormalizedNumber;
+    private String mCountryIso;
 
     private FilteredNumberAsyncQueryHandler mHandler;
     private View mParentView;
@@ -109,12 +113,16 @@
         super.onCreateDialog(savedInstanceState);
         final boolean isBlocked = getArguments().containsKey(ARG_BLOCK_ID);
 
+        mNumber = getArguments().getString(ARG_NUMBER);
         mDisplayNumber = getArguments().getString(ARG_DISPLAY_NUMBER);
+        mNormalizedNumber = getArguments().getString(ARG_NORMALIZED_NUMBER);
+        mCountryIso = getArguments().getString(ARG_COUNTRY_ISO);
+
         if (TextUtils.isEmpty(mNormalizedNumber)) {
-            String number = getArguments().getString(ARG_NUMBER);
-            String countryIso = getArguments().getString(ARG_COUNTRY_ISO);
-            mNormalizedNumber =
-                    FilteredNumberAsyncQueryHandler.getNormalizedNumber(number, countryIso);
+            mNormalizedNumber = PhoneNumberUtils.formatNumberToE164(mNumber, mCountryIso);
+        }
+        if (TextUtils.isEmpty(mDisplayNumber)) {
+            mDisplayNumber = mNumber;
         }
 
         mHandler = new FilteredNumberAsyncQueryHandler(getContext().getContentResolver());
@@ -148,11 +156,9 @@
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
-        String number = getArguments().getString(ARG_NUMBER);
-        if (TextUtils.isEmpty(mNormalizedNumber) ||
-                !FilteredNumbersUtil.canBlockNumber(getActivity(), number)) {
+        if (!FilteredNumbersUtil.canBlockNumber(getActivity(), mNormalizedNumber)) {
             dismiss();
-            Toast.makeText(getContext(), getString(R.string.invalidNumber, number),
+            Toast.makeText(getContext(), getString(R.string.invalidNumber, mDisplayNumber),
                     Toast.LENGTH_SHORT).show();
         }
     }
@@ -187,6 +193,7 @@
         final String undoMessage = getUnblockedMessage();
         final Callback callback = mCallback;
         final int actionTextColor = getActionTextColor();
+        final Context context = getContext();
 
         final OnUnblockNumberListener onUndoListener = new OnUnblockNumberListener() {
             @Override
@@ -217,14 +224,18 @@
                 if (callback != null) {
                     callback.onChangeFilteredNumberSuccess();
                 }
+
+                if (context != null && FilteredNumbersUtil.hasRecentEmergencyCall(context)) {
+                    FilteredNumbersUtil.maybeNotifyCallBlockingDisabled(context);
+                }
             }
         };
 
         mHandler.blockNumber(
                 onBlockNumberListener,
-                getArguments().getString(ARG_NORMALIZED_NUMBER),
-                getArguments().getString(ARG_NUMBER),
-                getArguments().getString(ARG_COUNTRY_ISO));
+                mNormalizedNumber,
+                mNumber,
+                mCountryIso);
     }
 
     private void unblockNumber() {
diff --git a/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java b/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
index 45fa6b7..4492c51 100644
--- a/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
+++ b/src/com/android/dialer/filterednumber/FilteredNumbersUtil.java
@@ -15,8 +15,12 @@
  */
 package com.android.dialer.filterednumber;
 
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.Intent;
 import android.database.Cursor;
 import android.os.AsyncTask;
 import android.preference.PreferenceManager;
@@ -33,8 +37,10 @@
 import java.util.List;
 
 import com.android.contacts.common.testing.NeededForTesting;
+import com.android.contacts.common.util.PhoneNumberHelper;
 import com.android.dialer.R;
 import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler.OnHasBlockedNumbersListener;
 import com.android.dialer.database.FilteredNumberContract.FilteredNumber;
 import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns;
 
@@ -43,13 +49,21 @@
  */
 public class FilteredNumbersUtil {
 
-    private static final String HIDE_BLOCKED_CALLS_PREF_KEY = "hide_blocked_calls";
-    // Pref key for storing the time, in milliseconds after epoch, of end of the last emergency call.
-    private static final String LAST_EMERGENCY_CALL_PREF_KEY = "last_emergency_call";
-
     // Disable incoming call blocking if there was a call within the past 2 days.
     private static final long RECENT_EMERGENCY_CALL_THRESHOLD_MS = 1000 * 60 * 60 * 24 * 2;
 
+    private static final String HIDE_BLOCKED_CALLS_PREF_KEY = "hide_blocked_calls";
+    // Pref key for storing the time of end of the last emergency call in milliseconds after epoch.
+    private static final String LAST_EMERGENCY_CALL_MS_PREF_KEY = "last_emergency_call_ms";
+
+    // Pref key for storing whether a notification has been dispatched to notify the user that call
+    // blocking has been disabled because of a recent emergency call.
+    private static final String NOTIFIED_CALL_BLOCKING_DISABLED_BY_EMERGENCY_CALL_PREF_KEY =
+            "notified_call_blocking_disabled_by_emergency_call";
+
+    public static final String CALL_BLOCKING_NOTIFICATION_TAG = "call_blocking";
+    public static final int CALL_BLOCKING_DISABLED_BY_EMERGENCY_CALL_NOTIFICATION_ID = 10;
+
     /**
      * Used for testing to specify that a custom threshold should be used instead of the default.
      * This custom threshold will only be used when setting this log tag to VERBOSE:
@@ -256,7 +270,7 @@
             return false;
         }
         return PreferenceManager.getDefaultSharedPreferences(context)
-                .getBoolean(FilteredNumbersUtil.HIDE_BLOCKED_CALLS_PREF_KEY, false);
+                .getBoolean(HIDE_BLOCKED_CALLS_PREF_KEY, false);
     }
 
     public static void setShouldHideBlockedCalls(Context context, boolean shouldHide) {
@@ -275,7 +289,7 @@
         }
 
         Long lastEmergencyCallTime = PreferenceManager.getDefaultSharedPreferences(context)
-                .getLong(LAST_EMERGENCY_CALL_PREF_KEY, 0);
+                .getLong(LAST_EMERGENCY_CALL_MS_PREF_KEY, 0);
         if (lastEmergencyCallTime == 0) {
             return false;
         }
@@ -288,14 +302,64 @@
         if (context == null) {
             return;
         }
+
         PreferenceManager.getDefaultSharedPreferences(context)
                 .edit()
-                .putLong(LAST_EMERGENCY_CALL_PREF_KEY, System.currentTimeMillis())
+                .putLong(LAST_EMERGENCY_CALL_MS_PREF_KEY, System.currentTimeMillis())
+                .putBoolean(NOTIFIED_CALL_BLOCKING_DISABLED_BY_EMERGENCY_CALL_PREF_KEY, false)
                 .apply();
+
+        maybeNotifyCallBlockingDisabled(context);
+    }
+
+    public static void maybeNotifyCallBlockingDisabled(final Context context) {
+        // Skip if the user has already received a notification for the most recent emergency call.
+        if (PreferenceManager.getDefaultSharedPreferences(context)
+                .getBoolean(NOTIFIED_CALL_BLOCKING_DISABLED_BY_EMERGENCY_CALL_PREF_KEY, false)) {
+            return;
+        }
+
+        // If the user has blocked numbers, notify that call blocking is temporarily disabled.
+        FilteredNumberAsyncQueryHandler queryHandler =
+                new FilteredNumberAsyncQueryHandler(context.getContentResolver());
+        queryHandler.hasBlockedNumbersAsync(new OnHasBlockedNumbersListener() {
+            @Override
+            public void onHasBlockedNumbers(boolean hasBlockedNumbers) {
+                if (context == null || !hasBlockedNumbers) {
+                    return;
+                }
+
+                NotificationManager notificationManager = (NotificationManager)
+                        context.getSystemService(Context.NOTIFICATION_SERVICE);
+                Notification.Builder builder = new Notification.Builder(context)
+                        .setSmallIcon(R.drawable.ic_block_24dp)
+                        .setContentTitle(context.getString(
+                                R.string.call_blocking_disabled_notification_title))
+                        .setContentText(context.getString(
+                                R.string.call_blocking_disabled_notification_text));
+
+                final Intent contentIntent =
+                        new Intent(context, ManageBlockedNumbersActivity.class);
+                builder.setContentIntent(PendingIntent.getActivity(
+                        context, 0, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+
+                notificationManager.notify(
+                        CALL_BLOCKING_NOTIFICATION_TAG,
+                        CALL_BLOCKING_DISABLED_BY_EMERGENCY_CALL_NOTIFICATION_ID,
+                        builder.build());
+
+                // Record that the user has been notified for this emergency call.
+                PreferenceManager.getDefaultSharedPreferences(context)
+                    .edit()
+                    .putBoolean(NOTIFIED_CALL_BLOCKING_DISABLED_BY_EMERGENCY_CALL_PREF_KEY, true)
+                    .apply();
+            }
+        });
     }
 
     public static boolean canBlockNumber(Context context, String number) {
-        return !PhoneNumberUtils.isEmergencyNumber(number) && !TextUtils.isEmpty(number);
+        return !TextUtils.isEmpty(number) && !PhoneNumberUtils.isEmergencyNumber(number)
+                && !PhoneNumberHelper.isUriNumber(number);
     }
 
     private static long getRecentEmergencyCallThresholdMs(Context context) {
diff --git a/src/com/android/dialer/list/BlockedListSearchFragment.java b/src/com/android/dialer/list/BlockedListSearchFragment.java
index d1490f5..852e7c9 100644
--- a/src/com/android/dialer/list/BlockedListSearchFragment.java
+++ b/src/com/android/dialer/list/BlockedListSearchFragment.java
@@ -133,7 +133,8 @@
     protected ContactEntryListAdapter createListAdapter() {
         BlockedListSearchAdapter adapter = new BlockedListSearchAdapter(getActivity());
         adapter.setDisplayPhotos(true);
-        adapter.setUseCallableUri(usesCallableUri());
+        // Don't show SIP addresses.
+        adapter.setUseCallableUri(false);
         adapter.setQueryString(mSearchQuery);
         return adapter;
     }