summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrandon Maxwell <maxwelb@google.com>2016-04-15 13:32:03 -0700
committerUsman Abdullah <uabdullah@google.com>2016-04-20 18:33:19 +0000
commit03dffbf949a9758da1b296369d29ef8b3aecae38 (patch)
tree1390e5475f5d818aabf4b6d8418beff0434f18cc
parentd0db4f8941e13766b78c90432b92b4eaccf71e2c (diff)
Performing auto-migration when there are no blocked nums
The previous behavior was such that users that had no numbers in the Dialer block list still had to go through steps to migrate to the framework blocking solution, even though there was nothing to migrate. This changes add logic to check if the blocked list is empty, if that's the cause the user is automatically switched to the framework blocking solution. This check is performed only once on app startup. Fixes: 27704106 Change-Id: I32482003279ef2070c1ebd8b801acf637c48ba8c (cherry picked from commit ee4e15b40f0d20b5f04f3569efa12c0d26a38645)
-rw-r--r--src/com/android/dialer/DialerApplication.java6
-rw-r--r--src/com/android/dialer/compat/FilteredNumberCompat.java11
-rw-r--r--src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java2
-rw-r--r--src/com/android/dialer/filterednumber/BlockedNumbersAutoMigrator.java101
-rw-r--r--tests/src/com/android/dialer/filterednumber/BlockedNumbersAutoMigratorTest.java201
5 files changed, 318 insertions, 3 deletions
diff --git a/src/com/android/dialer/DialerApplication.java b/src/com/android/dialer/DialerApplication.java
index 189c68221..1a0497bb9 100644
--- a/src/com/android/dialer/DialerApplication.java
+++ b/src/com/android/dialer/DialerApplication.java
@@ -19,11 +19,13 @@ package com.android.dialer;
import android.app.Application;
import android.content.Context;
import android.os.Trace;
+import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import com.android.contacts.common.extensions.ExtensionsFactory;
import com.android.contacts.common.testing.NeededForTesting;
-import com.android.dialer.compat.FilteredNumberCompat;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
+import com.android.dialer.filterednumber.BlockedNumbersAutoMigrator;
public class DialerApplication extends Application {
@@ -39,6 +41,8 @@ public class DialerApplication extends Application {
Trace.beginSection(TAG + " ExtensionsFactory initialization");
ExtensionsFactory.init(getApplicationContext());
Trace.endSection();
+ new BlockedNumbersAutoMigrator(PreferenceManager.getDefaultSharedPreferences(this),
+ new FilteredNumberAsyncQueryHandler(getContentResolver())).autoMigrate();
Trace.endSection();
}
diff --git a/src/com/android/dialer/compat/FilteredNumberCompat.java b/src/com/android/dialer/compat/FilteredNumberCompat.java
index 91563dc0d..008782d86 100644
--- a/src/com/android/dialer/compat/FilteredNumberCompat.java
+++ b/src/com/android/dialer/compat/FilteredNumberCompat.java
@@ -16,6 +16,7 @@
package com.android.dialer.compat;
+import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import android.app.FragmentManager;
@@ -67,6 +68,8 @@ public class FilteredNumberCompat {
private static Boolean isEnabledForTest;
+ private static Context contextForTest;
+
/**
* @return The column name for ID in the filtered number database.
*/
@@ -154,7 +157,8 @@ public class FilteredNumberCompat {
*/
@NeededForTesting
public static void setHasMigratedToNewBlocking(boolean hasMigrated) {
- PreferenceManager.getDefaultSharedPreferences(DialerApplication.getContext()).edit()
+ PreferenceManager.getDefaultSharedPreferences(
+ MoreObjects.firstNonNull(contextForTest, DialerApplication.getContext())).edit()
.putBoolean(HAS_MIGRATED_TO_NEW_BLOCKING_KEY, hasMigrated).apply();
}
@@ -163,6 +167,11 @@ public class FilteredNumberCompat {
isEnabledForTest = isEnabled;
}
+ @NeededForTesting
+ public static void setContextForTest(Context context) {
+ contextForTest = context;
+ }
+
/**
* Gets the content {@link Uri} for number filtering.
*
diff --git a/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
index 52ef49ac0..68a2e85d5 100644
--- a/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
+++ b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java
@@ -125,7 +125,7 @@ public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler {
null, null, null);
}
- public final void hasBlockedNumbers(final OnHasBlockedNumbersListener listener) {
+ public void hasBlockedNumbers(final OnHasBlockedNumbersListener listener) {
startQuery(NO_TOKEN,
new Listener() {
@Override
diff --git a/src/com/android/dialer/filterednumber/BlockedNumbersAutoMigrator.java b/src/com/android/dialer/filterednumber/BlockedNumbersAutoMigrator.java
new file mode 100644
index 000000000..ed0faabbe
--- /dev/null
+++ b/src/com/android/dialer/filterednumber/BlockedNumbersAutoMigrator.java
@@ -0,0 +1,101 @@
+/*
+ * 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.content.SharedPreferences;
+import android.util.Log;
+
+import com.android.dialer.compat.FilteredNumberCompat;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler.OnHasBlockedNumbersListener;
+
+/**
+ * Class responsible for checking if the user can be auto-migrated to {@link
+ * android.provider.BlockedNumberContract} blocking. In order for this to happen, the user cannot
+ * have any numbers that are blocked in the Dialer solution.
+ */
+public class BlockedNumbersAutoMigrator {
+
+ private static final String TAG = "BlockedNumbersAuto";
+
+ private static final String HAS_CHECKED_AUTO_MIGRATE_KEY = "checkedAutoMigrate";
+
+ private final SharedPreferences sharedPreferences;
+ private final FilteredNumberAsyncQueryHandler queryHandler;
+
+ /**
+ * Constructs the BlockedNumbersAutoMigrator with the given {@link SharedPreferences} and {@link
+ * FilteredNumberAsyncQueryHandler}.
+ *
+ * @param sharedPreferences The SharedPreferences used to persist information.
+ * @param queryHandler The FilteredNumberAsyncQueryHandler used to determine if there are
+ * blocked numbers.
+ * @throws NullPointerException if sharedPreferences or queryHandler are null.
+ */
+ public BlockedNumbersAutoMigrator(SharedPreferences sharedPreferences,
+ FilteredNumberAsyncQueryHandler queryHandler) {
+ this.sharedPreferences = Preconditions.checkNotNull(sharedPreferences);
+ this.queryHandler = Preconditions.checkNotNull(queryHandler);
+ }
+
+ /**
+ * Attempts to perform the auto-migration. Auto-migration will only be attempted once and can be
+ * performed only when the user has no blocked numbers. As a result of this method, the user
+ * will be migrated to the framework blocking solution, as determined by {@link
+ * FilteredNumberCompat#hasMigratedToNewBlocking()}.
+ */
+ public void autoMigrate() {
+ if (!shouldAttemptAutoMigrate()) {
+ return;
+ }
+
+ Log.i(TAG, "Attempting to auto-migrate.");
+ queryHandler.hasBlockedNumbers(new OnHasBlockedNumbersListener() {
+ @Override
+ public void onHasBlockedNumbers(boolean hasBlockedNumbers) {
+ if (hasBlockedNumbers) {
+ Log.i(TAG, "Not auto-migrating: blocked numbers exist.");
+ return;
+ }
+ Log.i(TAG, "Auto-migrating: no blocked numbers.");
+ FilteredNumberCompat.setHasMigratedToNewBlocking(true);
+ }
+ });
+ }
+
+ private boolean shouldAttemptAutoMigrate() {
+ if (sharedPreferences.contains(HAS_CHECKED_AUTO_MIGRATE_KEY)) {
+ Log.d(TAG, "Not attempting auto-migrate: already checked once.");
+ return false;
+ }
+ Log.i(TAG, "Updating state as already checked for auto-migrate.");
+ sharedPreferences.edit().putBoolean(HAS_CHECKED_AUTO_MIGRATE_KEY, true).apply();
+
+ if (!FilteredNumberCompat.canUseNewFiltering()) {
+ Log.i(TAG, "Not attempting auto-migrate: not available.");
+ return false;
+ }
+
+ if (FilteredNumberCompat.hasMigratedToNewBlocking()) {
+ Log.i(TAG, "Not attempting auto-migrate: already migrated.");
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/tests/src/com/android/dialer/filterednumber/BlockedNumbersAutoMigratorTest.java b/tests/src/com/android/dialer/filterednumber/BlockedNumbersAutoMigratorTest.java
new file mode 100644
index 000000000..505855528
--- /dev/null
+++ b/tests/src/com/android/dialer/filterednumber/BlockedNumbersAutoMigratorTest.java
@@ -0,0 +1,201 @@
+/*
+ * 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.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.test.AndroidTestCase;
+
+import com.android.contacts.common.compat.CompatUtils;
+import com.android.dialer.compat.FilteredNumberCompat;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler.OnHasBlockedNumbersListener;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class BlockedNumbersAutoMigratorTest extends AndroidTestCase {
+
+ private static final String HAS_CHECKED_AUTO_MIGRATE_KEY_FOR_TEST = "checkedAutoMigrateForTest";
+
+ @Mock
+ private FilteredNumberAsyncQueryHandler mockQueryHandler;
+
+ private SharedPreferences sharedPreferences;
+
+ private BlockedNumbersAutoMigrator blockedNumbersAutoMigrator;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+ FilteredNumberCompat.setContextForTest(getContext());
+ FilteredNumberCompat.setHasMigratedToNewBlocking(false);
+
+ sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
+ // SharedPreference state isn't cleaned up between each test automatically, clear it now
+ sharedPreferences.edit().clear().apply();
+
+ blockedNumbersAutoMigrator = new BlockedNumbersAutoMigrator(sharedPreferences,
+ mockQueryHandler);
+ }
+
+ public void testConstructor_NullSharedPreferences() {
+ try {
+ new BlockedNumbersAutoMigrator(null, mockQueryHandler);
+ fail();
+ } catch (NullPointerException e) {
+ }
+ }
+
+ public void testConstructor_NullQueryHandler() {
+ try {
+ new BlockedNumbersAutoMigrator(sharedPreferences, null);
+ fail();
+ } catch (NullPointerException e) {
+ }
+ }
+
+ public void testAutoMigrate_M() {
+ if (CompatUtils.isNCompatible()) {
+ return;
+ }
+ blockedNumbersAutoMigrator.autoMigrate();
+
+ verify(mockQueryHandler, never()).hasBlockedNumbers(any(OnHasBlockedNumbersListener.class));
+ }
+
+ public void testAutoMigrate_AlreadyMigrated() {
+ if (!CompatUtils.isNCompatible()) {
+ return;
+ }
+ FilteredNumberCompat.setHasMigratedToNewBlocking(true);
+
+ blockedNumbersAutoMigrator.autoMigrate();
+
+ verify(mockQueryHandler, never()).hasBlockedNumbers(any(OnHasBlockedNumbersListener.class));
+ }
+
+ public void testAutoMigrate_AlreadyChecked() {
+ if (!CompatUtils.isNCompatible()) {
+ return;
+ }
+ sharedPreferences.edit()
+ .putBoolean(HAS_CHECKED_AUTO_MIGRATE_KEY_FOR_TEST, true)
+ .apply();
+
+ blockedNumbersAutoMigrator.autoMigrate();
+
+ verify(mockQueryHandler, never()).hasBlockedNumbers(any(OnHasBlockedNumbersListener.class));
+ }
+
+ public void testAutoMigrate_HasNumbers() {
+ if (!CompatUtils.isNCompatible()) {
+ return;
+ }
+ setupFilteredNumberHasBlockedNumbersExpectation(true);
+
+ blockedNumbersAutoMigrator.autoMigrate();
+
+ verify(mockQueryHandler).hasBlockedNumbers(any(OnHasBlockedNumbersListener.class));
+ assertFalse(FilteredNumberCompat.hasMigratedToNewBlocking());
+ }
+
+ public void testAutoMigrate_HasNumbers_MultipleCalls() {
+ if (!CompatUtils.isNCompatible()) {
+ return;
+ }
+ setupFilteredNumberHasBlockedNumbersExpectation(true);
+
+ blockedNumbersAutoMigrator.autoMigrate();
+ blockedNumbersAutoMigrator.autoMigrate();
+
+ verify(mockQueryHandler, times(1))
+ .hasBlockedNumbers(any(OnHasBlockedNumbersListener.class));
+ assertFalse(FilteredNumberCompat.hasMigratedToNewBlocking());
+ }
+
+ public void testAutoMigrate_NoNumbers() {
+ if (!CompatUtils.isNCompatible()) {
+ return;
+ }
+ setupFilteredNumberHasBlockedNumbersExpectation(false);
+
+ blockedNumbersAutoMigrator.autoMigrate();
+
+ verify(mockQueryHandler).hasBlockedNumbers(any(OnHasBlockedNumbersListener.class));
+ assertTrue(FilteredNumberCompat.hasMigratedToNewBlocking());
+ }
+
+ public void testAutoMigrate_NoNumbers_MultipleCalls() {
+ if (!CompatUtils.isNCompatible()) {
+ return;
+ }
+ setupFilteredNumberHasBlockedNumbersExpectation(false);
+
+ blockedNumbersAutoMigrator.autoMigrate();
+ blockedNumbersAutoMigrator.autoMigrate();
+
+ verify(mockQueryHandler, times(1))
+ .hasBlockedNumbers(any(OnHasBlockedNumbersListener.class));
+ assertTrue(FilteredNumberCompat.hasMigratedToNewBlocking());
+ }
+
+
+ public void testAutoMigrate_SimulateClearingAppData() {
+ if (!CompatUtils.isNCompatible()) {
+ return;
+ }
+ setupFilteredNumberHasBlockedNumbersExpectation(true);
+
+ blockedNumbersAutoMigrator.autoMigrate();
+
+ // Clearing app data removes the sharedPreferences and all of the blocked numbers
+ sharedPreferences.edit().clear().apply();
+ setupFilteredNumberHasBlockedNumbersExpectation(false);
+
+ blockedNumbersAutoMigrator.autoMigrate();
+
+ verify(mockQueryHandler, times(2))
+ .hasBlockedNumbers(any(OnHasBlockedNumbersListener.class));
+ assertTrue(FilteredNumberCompat.hasMigratedToNewBlocking());
+ }
+
+ /*
+ * Sets up the {@link #mockQueryHandler} to call the {@link OnHasBlockedNumbersListener} with
+ * the given hasBlockedNumbers value as the parameter, when
+ * {@link FilteredNumberAsyncQueryHandler#hasBlockedNumbers} is called.
+ */
+ private void setupFilteredNumberHasBlockedNumbersExpectation(final boolean hasBlockedNumbers) {
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ ((OnHasBlockedNumbersListener) invocation.getArguments()[0])
+ .onHasBlockedNumbers(hasBlockedNumbers);
+ return null;
+ }
+ }).when(mockQueryHandler).hasBlockedNumbers(any(OnHasBlockedNumbersListener.class));
+ }
+}