Adding migrate promo to blocked numbers setting ui

This Migrate promo is shown so users have a way to migrate to the
framework blocking solution, directly from the settings. Previously,
users would have had to block a number to be presented with the
migration dialog.

UI: http://screen/GS8TdfKrnVv
Button Pressed: http://screen/ovd6NgVmOqq

Change-Id: I9c04b8afdf7c5681e09c02c7a4f6013c94b396d9
Fixes:27703938
(cherry picked from commit 3db9bde34452552973acefad5535a2273e9968fe)
diff --git a/res/drawable/selectable_primary_flat_button.xml b/res/drawable/selectable_primary_flat_button.xml
new file mode 100644
index 0000000..c6eb7a2
--- /dev/null
+++ b/res/drawable/selectable_primary_flat_button.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 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.
+ */
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false">
+        <shape><solid android:color="@color/material_grey_300" /></shape>
+    </item>
+  <item>
+    <shape><solid android:color="@color/dialer_theme_color" /></shape>
+  </item>
+</selector>
\ No newline at end of file
diff --git a/res/layout/blocked_number_header.xml b/res/layout/blocked_number_header.xml
index 0af9429..e4b795f 100644
--- a/res/layout/blocked_number_header.xml
+++ b/res/layout/blocked_number_header.xml
@@ -61,7 +61,7 @@
             android:orientation="vertical">
 
             <TextView
-                android:id="@+id/textView"
+                android:id="@+id/blocked_number_text_view"
                 style="@android:style/TextAppearance.Material.Subhead"
                 android:layout_width="wrap_content"
                 android:layout_height="48dp"
@@ -119,6 +119,51 @@
             </RelativeLayout>
 
             <LinearLayout
+                android:id="@+id/migrate_promo"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:visibility="gone">
+
+                <TextView
+                    android:id="@+id/migrate_promo_header"
+                    style="@android:style/TextAppearance.Material.Subhead"
+                    android:layout_width="match_parent"
+                    android:layout_height="48dp"
+                    android:paddingStart="@dimen/blocked_number_container_padding"
+                    android:paddingEnd="@dimen/blocked_number_container_padding"
+                    android:gravity="center_vertical"
+                    android:textStyle="bold"
+                    android:text="@string/migrate_blocked_numbers_dialog_title"
+                    android:textColor="@color/blocked_number_header_color"/>
+
+                <TextView
+                  android:id="@+id/migrate_promo_description"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:layout_marginStart="@dimen/blocked_number_container_padding"
+                  android:layout_marginEnd="@dimen/blocked_number_container_padding"
+                  android:layout_marginBottom="@dimen/blocked_number_container_padding"
+                  android:text="@string/migrate_blocked_numbers_dialog_message"
+                  android:textColor="@color/secondary_text_color"/>
+
+                <Button
+                  android:id="@+id/migrate_promo_allow_button"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:text="@string/migrate_blocked_numbers_dialog_allow_button"
+                  android:layout_marginStart="@dimen/blocked_number_container_padding"
+                  android:layout_marginEnd="@dimen/blocked_number_container_padding"
+                  android:layout_gravity="end"
+                  style="@style/DialerPrimaryFlatButtonStyle"
+                  android:layout_marginBottom="@dimen/blocked_number_container_padding"/>
+
+                <View
+                  style="@style/FullWidthDivider"/>
+
+            </LinearLayout>
+
+            <LinearLayout
                 android:id="@+id/add_number_linear_layout"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 66a45f9..6a40d09 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -322,10 +322,25 @@
         <item name="android:textColor">@color/dialer_flat_button_text_color</item>
     </style>
 
+    <!-- Style for the 'primary' button in a view. Unlike the DialerFlatButtonStyle, this button -->
+    <!-- is not colored white, to draw more attention to it. -->
+    <style name="DialerPrimaryFlatButtonStyle" parent="@android:style/Widget.Material.Button">
+        <item name="android:background">@drawable/selectable_primary_flat_button</item>
+        <item name="android:paddingEnd">@dimen/button_horizontal_padding</item>
+        <item name="android:paddingStart">@dimen/button_horizontal_padding</item>
+        <item name="android:textColor">@android:color/white</item>
+    </style>
+
     <style name="BlockedNumbersDescriptionTextStyle">
         <item name="android:lineSpacingMultiplier">1.43</item>
         <item name="android:paddingTop">8dp</item>
         <item name="android:paddingBottom">8dp</item>
         <item name="android:textSize">@dimen/blocked_number_settings_description_text_size</item>
     </style>
+
+    <style name="FullWidthDivider">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">1dp</item>
+        <item name="android:background">?android:attr/listDivider</item>
+    </style>
 </resources>
diff --git a/src/com/android/dialer/filterednumber/BlockedNumbersFragment.java b/src/com/android/dialer/filterednumber/BlockedNumbersFragment.java
index 87ba8be..b64f186 100644
--- a/src/com/android/dialer/filterednumber/BlockedNumbersFragment.java
+++ b/src/com/android/dialer/filterednumber/BlockedNumbersFragment.java
@@ -15,6 +15,8 @@
  */
 package com.android.dialer.filterednumber;
 
+import com.google.common.base.MoreObjects;
+
 import android.app.ListFragment;
 import android.app.LoaderManager;
 import android.content.Context;
@@ -32,11 +34,12 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import com.android.contacts.common.compat.CompatUtils;
 import com.android.contacts.common.lettertiles.LetterTileDrawable;
+import com.android.contacts.common.testing.NeededForTesting;
 import com.android.dialer.R;
 import com.android.dialer.compat.FilteredNumberCompat;
 import com.android.dialer.database.FilteredNumberContract;
+import com.android.dialer.filterednumber.BlockedNumbersMigrator.Listener;
 import com.android.dialer.filterednumber.FilteredNumbersUtil.CheckForSendToVoicemailContactListener;
 import com.android.dialer.filterednumber.FilteredNumbersUtil.ImportSendToVoicemailContactsListener;
 import com.android.dialer.voicemail.VisualVoicemailEnabledChecker;
@@ -46,9 +49,12 @@
         VisualVoicemailEnabledChecker.Callback {
     private static final char ADD_BLOCKED_NUMBER_ICON_LETTER = '+';
 
+    private BlockedNumbersMigrator blockedNumbersMigratorForTest;
+    protected View migratePromoView;
+    private TextView blockedNumbersText;
+    private TextView footerText;
     private BlockedNumbersAdapter mAdapter;
     private VisualVoicemailEnabledChecker mVoicemailEnabledChecker;
-
     private View mImportSettings;
     private View mBlockedNumbersDisabledForEmergency;
     private View mBlockedNumberListDivider;
@@ -81,6 +87,9 @@
         }
         setListAdapter(mAdapter);
 
+        blockedNumbersText = (TextView) getListView().findViewById(R.id.blocked_number_text_view);
+        migratePromoView = getListView().findViewById(R.id.migrate_promo);
+        getListView().findViewById(R.id.migrate_promo_allow_button).setOnClickListener(this);
         mImportSettings = getListView().findViewById(R.id.import_settings);
         mBlockedNumbersDisabledForEmergency =
                 getListView().findViewById(R.id.blocked_numbers_disabled_for_emergency);
@@ -89,6 +98,8 @@
         getListView().findViewById(R.id.view_numbers_button).setOnClickListener(this);
         getListView().findViewById(R.id.add_number_linear_layout).setOnClickListener(this);
 
+        footerText = (TextView) getActivity().findViewById(
+            R.id.blocked_number_footer_textview);
         mVoicemailEnabledChecker = new VisualVoicemailEnabledChecker(getContext(),this);
         mVoicemailEnabledChecker.asyncUpdate();
         updateActiveVoicemailProvider();
@@ -124,13 +135,16 @@
         // new blocked numbers from the Blocked Management UI. They will be shown a promo card
         // asking them to migrate to new blocking instead.
         if (FilteredNumberCompat.canUseNewFiltering()) {
+            migratePromoView.setVisibility(View.VISIBLE);
+            blockedNumbersText.setVisibility(View.GONE);
             getListView().findViewById(R.id.add_number_linear_layout).setVisibility(View.GONE);
             getListView().findViewById(R.id.add_number_linear_layout).setOnClickListener(null);
-            mBlockedNumberListDivider.setVisibility(View.INVISIBLE);
-
-            mImportSettings.setSystemUiVisibility(View.GONE);
+            mBlockedNumberListDivider.setVisibility(View.GONE);
+            mImportSettings.setVisibility(View.GONE);
             getListView().findViewById(R.id.import_button).setOnClickListener(null);
             getListView().findViewById(R.id.view_numbers_button).setOnClickListener(null);
+            mBlockedNumbersDisabledForEmergency.setVisibility(View.GONE);
+            footerText.setVisibility(View.GONE);
         } else {
             FilteredNumbersUtil.checkForSendToVoicemailContact(
                     getActivity(), new CheckForSendToVoicemailContactListener() {
@@ -143,7 +157,9 @@
                     });
         }
 
-        if (FilteredNumbersUtil.hasRecentEmergencyCall(getContext())) {
+        // All views except migrate and the block list are hidden when new filtering is available
+        if (!FilteredNumberCompat.canUseNewFiltering()
+                && FilteredNumbersUtil.hasRecentEmergencyCall(getContext())) {
             mBlockedNumbersDisabledForEmergency.setVisibility(View.VISIBLE);
         } else {
             mBlockedNumbersDisabledForEmergency.setVisibility(View.GONE);
@@ -190,7 +206,8 @@
 
     @Override
     public void onClick(final View view) {
-        BlockedNumbersSettingsActivity activity = (BlockedNumbersSettingsActivity) getActivity();
+        final BlockedNumbersSettingsActivity activity =
+                (BlockedNumbersSettingsActivity) getActivity();
         if (activity == null) {
             return;
         }
@@ -208,8 +225,22 @@
                             mImportSettings.setVisibility(View.GONE);
                         }
                     });
+        } else if (resId == R.id.migrate_promo_allow_button) {
+            view.setEnabled(false);
+            MoreObjects.firstNonNull(blockedNumbersMigratorForTest,
+                new BlockedNumbersMigrator(getContext().getContentResolver()))
+                .migrate(new Listener() {
+                    @Override
+                    public void onComplete() {
+                        getContext().startActivity(
+                            FilteredNumberCompat.createManageBlockedNumbersIntent(getContext()));
+                        // Remove this activity from the backstack
+                        activity.finish();
+                }
+            });
         }
     }
+
     @Override
     public void onVisualVoicemailEnabledStatusChanged(boolean newStatus){
         updateActiveVoicemailProvider();
@@ -219,12 +250,15 @@
         if (getActivity() == null || getActivity().isFinishing()) {
             return;
         }
-        TextView footerText = (TextView) getActivity().findViewById(
-            R.id.blocked_number_footer_textview);
         if (mVoicemailEnabledChecker.isVisualVoicemailEnabled()) {
             footerText.setText(R.string.block_number_footer_message_vvm);
         } else {
             footerText.setText(R.string.block_number_footer_message_no_vvm);
         }
     }
+
+    @NeededForTesting
+    void setBlockedNumbersMigratorForTest(BlockedNumbersMigrator blockedNumbersMigrator) {
+        blockedNumbersMigratorForTest = blockedNumbersMigrator;
+    }
 }
diff --git a/src/com/android/dialer/settings/DialerSettingsActivity.java b/src/com/android/dialer/settings/DialerSettingsActivity.java
index fc689d0..9db3e05 100644
--- a/src/com/android/dialer/settings/DialerSettingsActivity.java
+++ b/src/com/android/dialer/settings/DialerSettingsActivity.java
@@ -38,6 +38,7 @@
 
 public class DialerSettingsActivity extends AppCompatPreferenceActivity {
     protected SharedPreferences mPreferences;
+    private boolean migrationStatusOnBuildHeaders;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -46,6 +47,18 @@
     }
 
     @Override
+    protected void onResume() {
+        super.onResume();
+        /*
+         * The headers need to be recreated if the migration status changed between when the headers
+         * were created and now.
+         */
+        if (migrationStatusOnBuildHeaders != FilteredNumberCompat.hasMigratedToNewBlocking()) {
+            invalidateHeaders();
+        }
+    }
+
+    @Override
     public void onBuildHeaders(List<Header> target) {
         Header displayOptionsHeader = new Header();
         displayOptionsHeader.titleRes = R.string.display_options_title;
@@ -99,6 +112,7 @@
             blockedCallsHeader.titleRes = R.string.manage_blocked_numbers_label;
             blockedCallsHeader.intent = FilteredNumberCompat.createManageBlockedNumbersIntent(this);
             target.add(blockedCallsHeader);
+            migrationStatusOnBuildHeaders = FilteredNumberCompat.hasMigratedToNewBlocking();
         }
         if (isPrimaryUser
                 && (TelephonyManagerCompat.isTtyModeSupported(telephonyManager)
diff --git a/tests/src/com/android/dialer/filterednumber/BlockedNumbersFragmentInstrumentationTest.java b/tests/src/com/android/dialer/filterednumber/BlockedNumbersFragmentInstrumentationTest.java
new file mode 100644
index 0000000..ea4c51e
--- /dev/null
+++ b/tests/src/com/android/dialer/filterednumber/BlockedNumbersFragmentInstrumentationTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2016 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.dialer.filterednumber;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.View;
+
+import com.android.contacts.common.compat.CompatUtils;
+import com.android.dialer.R;
+import com.android.dialer.compat.FilteredNumberCompat;
+import com.android.dialer.filterednumber.BlockedNumbersMigrator.Listener;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Instrumentation tests for {@link BlockedNumbersFragment}. Note for these tests to work properly,
+ * the device's screen must be on.
+ */
+public class BlockedNumbersFragmentInstrumentationTest extends
+    ActivityInstrumentationTestCase2<BlockedNumbersSettingsActivity> {
+
+  private static final String FRAGMENT_TAG = "blocked_management";
+
+  private BlockedNumbersFragment blockedNumbersFragment;
+  @Mock private BlockedNumbersMigrator blockedNumbersMigrator;
+
+  public BlockedNumbersFragmentInstrumentationTest() {
+    super(BlockedNumbersSettingsActivity.class);
+  }
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    MockitoAnnotations.initMocks(this);
+    FilteredNumberCompat.setIsEnabledForTest(true);
+    blockedNumbersFragment = new BlockedNumbersFragment();
+    blockedNumbersFragment.setBlockedNumbersMigratorForTest(blockedNumbersMigrator);
+    getActivity().getFragmentManager().beginTransaction()
+        .replace(R.id.blocked_numbers_activity_container, blockedNumbersFragment, FRAGMENT_TAG)
+        .commit();
+    getInstrumentation().waitForIdleSync();
+  }
+
+  public void testMigrationPromo_NotShown_M() {
+    if (CompatUtils.isNCompatible()) {
+      return;
+    }
+    assertEquals(View.GONE, blockedNumbersFragment.migratePromoView.getVisibility());
+  }
+
+  public void testMigrationPromo_Shown_N() {
+    if (!CompatUtils.isNCompatible()) {
+      return;
+    }
+    assertEquals(View.VISIBLE, blockedNumbersFragment.migratePromoView.getVisibility());
+  }
+
+  public void testOnClick_Migrate() {
+    if (!CompatUtils.isNCompatible()) {
+      return;
+    }
+
+    getInstrumentation().runOnMainSync(new Runnable() {
+      @Override
+      public void run() {
+        blockedNumbersFragment.getListView().findViewById(R.id.migrate_promo_allow_button)
+            .performClick();
+      }
+    });
+    getInstrumentation().waitForIdleSync();
+    assertFalse(blockedNumbersFragment.getListView().findViewById(R.id.migrate_promo_allow_button)
+        .isEnabled());
+    verify(blockedNumbersMigrator).migrate(any(Listener.class));
+  }
+}