diff options
7 files changed, 291 insertions, 17 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml index b8f8679bc..5302b0df0 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -570,6 +570,18 @@ [CHAR LIMIT=30] --> <string name="call_log_voicemail_title">Voicemail</string> + <!-- Title for dialog which opens when the user needs to migrate to the framework blocking implementation [CHAR LIMIT=30]--> + <string name="migrate_blocked_numbers_dialog_title">New, simplified blocking</string> + + <!-- Body text for dialog which opens when the user needs to migrate to the framework blocking implementation [CHAR LIMIT=NONE]--> + <string name="migrate_blocked_numbers_dialog_message">To better protect you, Phone needs to change how blocking works. Your blocked numbers will now stop both calls and texts and may be shared with other apps.</string> + + <!-- Positive confirmation button for the dialog which opens when the user needs to migrate to the framework blocking implementation [CHAR LIMIT=NONE]--> + <string name="migrate_blocked_numbers_dialog_allow_button">Allow</string> + + <!-- Do not translate --> + <string name="migrate_blocked_numbers_dialog_cancel_button">@android:string/cancel</string> + <!-- Confirmation dialog title for blocking a number. [CHAR LIMIT=NONE] --> <string name="block_number_confirmation_title">Block <xliff:g id="number" example="(555) 555-5555">%1$s</xliff:g>?</string> diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java index e6a29fbe2..d2cda92b1 100644 --- a/src/com/android/dialer/CallDetailActivity.java +++ b/src/com/android/dialer/CallDetailActivity.java @@ -54,10 +54,12 @@ import com.android.dialer.calllog.CallLogAsyncTaskUtil.CallLogAsyncTaskListener; import com.android.dialer.calllog.CallTypeHelper; import com.android.dialer.calllog.ContactInfoHelper; import com.android.dialer.calllog.PhoneAccountUtils; +import com.android.dialer.compat.FilteredNumberCompat; import com.android.dialer.database.FilteredNumberAsyncQueryHandler; import com.android.dialer.database.FilteredNumberAsyncQueryHandler.OnCheckBlockedListener; import com.android.dialer.filterednumber.BlockNumberDialogFragment; import com.android.dialer.filterednumber.FilteredNumbersUtil; +import com.android.dialer.filterednumber.MigrateBlockedNumbersDialogFragment; import com.android.dialer.logging.InteractionEvent; import com.android.dialer.logging.Logger; import com.android.dialer.util.DialerUtils; @@ -372,14 +374,9 @@ public class CallDetailActivity extends AppCompatActivity public void onClick(View view) { int resId = view.getId(); if (resId == R.id.call_detail_action_block) { - BlockNumberDialogFragment.show( - mBlockedNumberId, - mNumber, - mDetails.countryIso, - mDisplayNumber, - R.id.call_detail, - getFragmentManager(), - this); + FilteredNumberCompat + .showBlockNumberDialogFlow(mBlockedNumberId, mNumber, mDetails.countryIso, + mDisplayNumber, R.id.call_detail, getFragmentManager(), this); } else if (resId == R.id.call_detail_action_copy) { ClipboardUtils.copyText(mContext, null, mNumber, true); } else if (resId == R.id.call_detail_action_edit_before_call) { diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java index 392672fec..de9bf7739 100644 --- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java +++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java @@ -51,9 +51,11 @@ import com.android.contacts.common.util.UriUtils; import com.android.dialer.DialtactsActivity; import com.android.dialer.R; import com.android.dialer.calllog.calllogcache.CallLogCache; +import com.android.dialer.compat.FilteredNumberCompat; import com.android.dialer.database.FilteredNumberAsyncQueryHandler; import com.android.dialer.filterednumber.BlockNumberDialogFragment; import com.android.dialer.filterednumber.FilteredNumbersUtil; +import com.android.dialer.filterednumber.MigrateBlockedNumbersDialogFragment; import com.android.dialer.logging.Logger; import com.android.dialer.logging.ScreenEvent; import com.android.dialer.service.ExtendedBlockingButtonRenderer; @@ -370,14 +372,11 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder public boolean onMenuItemClick(MenuItem item) { int resId = item.getItemId(); if (resId == R.id.context_menu_block_number) { - BlockNumberDialogFragment.show( - blockId, - number, - countryIso, - displayNumber, - R.id.floating_action_button_container, - ((Activity) mContext).getFragmentManager(), - mFilteredNumberDialogCallback); + FilteredNumberCompat + .showBlockNumberDialogFlow(blockId, number, countryIso, displayNumber, + R.id.floating_action_button_container, + ((Activity) mContext).getFragmentManager(), + mFilteredNumberDialogCallback); return true; } else if (resId == R.id.context_menu_copy_to_clipboard) { ClipboardUtils.copyText(mContext, null, number, true); diff --git a/src/com/android/dialer/compat/FilteredNumberCompat.java b/src/com/android/dialer/compat/FilteredNumberCompat.java index 3ad45e87d..743bf28b9 100644 --- a/src/com/android/dialer/compat/FilteredNumberCompat.java +++ b/src/com/android/dialer/compat/FilteredNumberCompat.java @@ -18,9 +18,9 @@ import com.google.common.base.Preconditions; +import android.app.FragmentManager; import android.content.ContentUris; import android.content.ContentValues; -import android.content.Context; import android.net.Uri; import android.preference.PreferenceManager; import android.support.annotation.Nullable; @@ -33,6 +33,10 @@ import com.android.dialer.database.FilteredNumberContract.FilteredNumber; import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns; import com.android.dialer.database.FilteredNumberContract.FilteredNumberSources; import com.android.dialer.database.FilteredNumberContract.FilteredNumberTypes; +import com.android.dialer.filterednumber.BlockNumberDialogFragment; +import com.android.dialer.filterednumber.BlockNumberDialogFragment.Callback; +import com.android.dialer.filterednumber.MigrateBlockedNumbersDialogFragment; +import com.android.dialer.filterednumber.MigrateBlockedNumbersDialogFragment.Listener; import java.util.ArrayList; import java.util.List; @@ -222,4 +226,41 @@ public class FilteredNumberCompat { } return contentValues; } + + /** + * Shows the flow of {@link android.app.DialogFragment}s for blocking or unblocking numbers. + * + * @param blockId The id into the blocked numbers database. + * @param number The number to block or unblock. + * @param countryIso The countryIso used to format the given number. + * @param displayNumber The form of the number to block, suitable for displaying. + * @param parentViewId The id for the containing view of the Dialog. + * @param fragmentManager The {@link FragmentManager} used to show fragments. + * @param callback (optional) The {@link Callback} to call when the block or unblock operation + * is complete. + */ + public static void showBlockNumberDialogFlow(final Integer blockId, final String number, + final String countryIso, final String displayNumber, final Integer parentViewId, + final FragmentManager fragmentManager, @Nullable final Callback callback) { + // If the user is blocking a number and isn't using the framework solution when they + // should be, show the migration dialog + if (shouldShowMigrationDialog(blockId == null)) { + MigrateBlockedNumbersDialogFragment.newInstance(new Listener() { + @Override + public void onComplete() { + BlockNumberDialogFragment + .show(null, number, countryIso, displayNumber, parentViewId, + fragmentManager, callback); + } + }).show(fragmentManager, "MigrateBlockedNumbers"); + return; + } + BlockNumberDialogFragment + .show(blockId, number, countryIso, displayNumber, parentViewId, fragmentManager, + callback); + } + + private static boolean shouldShowMigrationDialog(boolean isBlocking) { + return isBlocking && canUseNewFiltering() && !hasMigratedToNewBlocking(); + } } diff --git a/src/com/android/dialer/filterednumber/MigrateBlockedNumbersDialogFragment.java b/src/com/android/dialer/filterednumber/MigrateBlockedNumbersDialogFragment.java new file mode 100644 index 000000000..3783519e5 --- /dev/null +++ b/src/com/android/dialer/filterednumber/MigrateBlockedNumbersDialogFragment.java @@ -0,0 +1,97 @@ +/* + * 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 com.google.common.base.Preconditions; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.android.dialer.R; + +/** + * Dialog fragment shown to users when they need to migrate to use + * {@link android.provider.BlockedNumberContract} for blocking. + */ +public class MigrateBlockedNumbersDialogFragment extends DialogFragment { + + /** + * Listener for the operation to migrate from + * {@link com.android.dialer.database.FilteredNumberContract} blocking to + * {@link android.provider.BlockedNumberContract} blocking. + */ + public interface Listener { + + /** + * Callback called when the migration operation is finished. + */ + void onComplete(); + } + + private Listener mMigrationListener; + + /** + * Creates a new MigrateBlockedNumbersDialogFragment. + * + * @param migrationListener The {@link Listener} to call when the + * migration is complete. + * @return the new MigrateBlockedNumbersDialogFragment. + * @throws NullPointerException if migrationListener is {@code null}. + */ + public static DialogFragment newInstance(Listener migrationListener) { + MigrateBlockedNumbersDialogFragment fragment = new MigrateBlockedNumbersDialogFragment(); + fragment.mMigrationListener = Preconditions.checkNotNull(migrationListener); + return fragment; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + super.onCreateDialog(savedInstanceState); + return new AlertDialog.Builder(getActivity()) + .setTitle(R.string.migrate_blocked_numbers_dialog_title) + .setMessage(R.string.migrate_blocked_numbers_dialog_message) + .setPositiveButton(R.string.migrate_blocked_numbers_dialog_allow_button, + newPositiveButtonOnClickListener()) + .setNegativeButton(R.string.migrate_blocked_numbers_dialog_cancel_button, null) + .create(); + } + + private DialogInterface.OnClickListener newPositiveButtonOnClickListener() { + return new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // TODO(maxwelb): Perform actual migration, call + // FilteredNumberCompat#hasMigratedToNewBlocking + + mMigrationListener.onComplete(); + } + }; + } + + @Override + public void onPause() { + // The dialog is dismissed and state is cleaned up onPause, i.e. rotation. + dismiss(); + mMigrationListener = null; + super.onPause(); + } +} diff --git a/tests/src/com/android/dialer/filterednumber/MigrateBlockedNumbersDialogFragmentInstrumentationTest.java b/tests/src/com/android/dialer/filterednumber/MigrateBlockedNumbersDialogFragmentInstrumentationTest.java new file mode 100644 index 000000000..4cf648a62 --- /dev/null +++ b/tests/src/com/android/dialer/filterednumber/MigrateBlockedNumbersDialogFragmentInstrumentationTest.java @@ -0,0 +1,83 @@ +/* + * 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.Mockito.doNothing; +import static org.mockito.Mockito.verify; + +import android.app.AlertDialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.test.ActivityInstrumentationTestCase2; + +import com.android.dialer.DialtactsActivity; +import com.android.dialer.filterednumber.MigrateBlockedNumbersDialogFragment.Listener; + +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Instrumentation tests for {@link MigrateBlockedNumbersDialogFragment}. Note for these tests to + * work properly, the device's screen must be on. + */ +public class MigrateBlockedNumbersDialogFragmentInstrumentationTest extends + ActivityInstrumentationTestCase2<DialtactsActivity> { + + private static final String SHOW_TAG = "ShowTag"; + + @Mock private Listener mListener; + private DialtactsActivity mActivity; + private DialogFragment mMigrateDialogFragment; + + public MigrateBlockedNumbersDialogFragmentInstrumentationTest() { + super(DialtactsActivity.class); + } + + @Override + public void setUp() throws Exception { + super.setUp(); + MockitoAnnotations.initMocks(this); + mActivity = getActivity(); + mMigrateDialogFragment = MigrateBlockedNumbersDialogFragment.newInstance(mListener); + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + mMigrateDialogFragment.show(mActivity.getFragmentManager(), SHOW_TAG); + } + }); + getInstrumentation().waitForIdleSync(); + } + + public void testDialogAppears() { + assertTrue(mMigrateDialogFragment.getDialog().isShowing()); + } + + public void testDialogPositiveButtonPress() { + doNothing().when(mListener).onComplete(); + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + ((AlertDialog) mMigrateDialogFragment.getDialog()) + .getButton(DialogInterface.BUTTON_POSITIVE).performClick(); + } + }); + getInstrumentation().waitForIdleSync(); + // Dialog was dismissed + assertNull(mMigrateDialogFragment.getDialog()); + verify(mListener).onComplete(); + } +} diff --git a/tests/src/com/android/dialer/filterednumber/MigrateBlockedNumbersDialogFragmentTest.java b/tests/src/com/android/dialer/filterednumber/MigrateBlockedNumbersDialogFragmentTest.java new file mode 100644 index 000000000..c8c782055 --- /dev/null +++ b/tests/src/com/android/dialer/filterednumber/MigrateBlockedNumbersDialogFragmentTest.java @@ -0,0 +1,45 @@ +/* + * 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 android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.dialer.filterednumber.MigrateBlockedNumbersDialogFragment.Listener; + + +/** + * Unit tests for {@link MigrateBlockedNumbersDialogFragment} + */ +@SmallTest +public class MigrateBlockedNumbersDialogFragmentTest extends AndroidTestCase { + + public void testNewInstance_NullMigrationListener() { + try { + MigrateBlockedNumbersDialogFragment.newInstance(null); + fail(); + } catch (NullPointerException e) {} + } + + public void testNewInstance_WithListener() { + assertNotNull(MigrateBlockedNumbersDialogFragment.newInstance( + new Listener() { + @Override + public void onComplete() {} + })); + } +} |