summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnne Rong <annerong@google.com>2015-08-10 17:45:55 -0700
committerAnne Rong <annerong@google.com>2015-08-19 11:32:53 -0700
commit6fcdcc15f3b8786e0ecab5886324eeb212c58699 (patch)
treeab80eb215de719da1015c05843dbdb2e87a95cff /src
parentab183510ce4ed4538d5bbbbfba512db240b32f27 (diff)
Create local database table + ContentProvider for filtered numbers
Bug: 23350722 Bug: 23350276 Change-Id: I070434cead43aa93026aa6b00ab886aa2947b1e6
Diffstat (limited to 'src')
-rw-r--r--src/com/android/dialer/database/DialerDatabaseHelper.java100
-rw-r--r--src/com/android/dialer/database/FilteredNumberContract.java149
-rw-r--r--src/com/android/dialer/database/FilteredNumberProvider.java199
3 files changed, 417 insertions, 31 deletions
diff --git a/src/com/android/dialer/database/DialerDatabaseHelper.java b/src/com/android/dialer/database/DialerDatabaseHelper.java
index eec24f5bc..8fcbb9208 100644
--- a/src/com/android/dialer/database/DialerDatabaseHelper.java
+++ b/src/com/android/dialer/database/DialerDatabaseHelper.java
@@ -38,6 +38,7 @@ import android.util.Log;
import com.android.contacts.common.util.PermissionsUtil;
import com.android.contacts.common.util.StopWatch;
+import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns;
import com.android.dialer.R;
import com.android.dialer.dialpad.SmartDialNameMatcher;
import com.android.dialer.dialpad.SmartDialPrefix;
@@ -60,6 +61,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class DialerDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "DialerDatabaseHelper";
private static final boolean DEBUG = false;
+ private boolean mIsTestInstance = false;
private static DialerDatabaseHelper sSingleton = null;
@@ -73,7 +75,7 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
* 0-98 KitKat
* </pre>
*/
- public static final int DATABASE_VERSION = 4;
+ public static final int DATABASE_VERSION = 5;
public static final String DATABASE_NAME = "dialer.db";
/**
@@ -86,6 +88,8 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
private static final int MAX_ENTRIES = 20;
public interface Tables {
+ /** Saves a list of numbers to be blocked.*/
+ static final String FILTERED_NUMBER_TABLE = "filtered_numbers_table";
/** Saves the necessary smart dial information of all contacts. */
static final String SMARTDIAL_TABLE = "smartdial_table";
/** Saves all possible prefixes to refer to a contacts.*/
@@ -334,7 +338,12 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
*/
@VisibleForTesting
static DialerDatabaseHelper getNewInstanceForTest(Context context) {
- return new DialerDatabaseHelper(context, null);
+ return new DialerDatabaseHelper(context, null, true);
+ }
+
+ protected DialerDatabaseHelper(Context context, String databaseName, boolean isTestInstance) {
+ this(context, databaseName, DATABASE_VERSION);
+ mIsTestInstance = isTestInstance;
}
protected DialerDatabaseHelper(Context context, String databaseName) {
@@ -358,36 +367,51 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
private void setupTables(SQLiteDatabase db) {
dropTables(db);
- db.execSQL("CREATE TABLE " + Tables.SMARTDIAL_TABLE + " (" +
- SmartDialDbColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
- SmartDialDbColumns.DATA_ID + " INTEGER, " +
- SmartDialDbColumns.NUMBER + " TEXT," +
- SmartDialDbColumns.CONTACT_ID + " INTEGER," +
- SmartDialDbColumns.LOOKUP_KEY + " TEXT," +
- SmartDialDbColumns.DISPLAY_NAME_PRIMARY + " TEXT, " +
- SmartDialDbColumns.PHOTO_ID + " INTEGER, " +
- SmartDialDbColumns.LAST_SMARTDIAL_UPDATE_TIME + " LONG, " +
- SmartDialDbColumns.LAST_TIME_USED + " LONG, " +
- SmartDialDbColumns.TIMES_USED + " INTEGER, " +
- SmartDialDbColumns.STARRED + " INTEGER, " +
- SmartDialDbColumns.IS_SUPER_PRIMARY + " INTEGER, " +
- SmartDialDbColumns.IN_VISIBLE_GROUP + " INTEGER, " +
- SmartDialDbColumns.IS_PRIMARY + " INTEGER" +
- ");");
-
- db.execSQL("CREATE TABLE " + Tables.PREFIX_TABLE + " (" +
- PrefixColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
- PrefixColumns.PREFIX + " TEXT COLLATE NOCASE, " +
- PrefixColumns.CONTACT_ID + " INTEGER" +
- ");");
-
- db.execSQL("CREATE TABLE " + Tables.PROPERTIES + " (" +
- PropertiesColumns.PROPERTY_KEY + " TEXT PRIMARY KEY, " +
- PropertiesColumns.PROPERTY_VALUE + " TEXT " +
- ");");
-
+ db.execSQL("CREATE TABLE " + Tables.SMARTDIAL_TABLE + " ("
+ + SmartDialDbColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ + SmartDialDbColumns.DATA_ID + " INTEGER, "
+ + SmartDialDbColumns.NUMBER + " TEXT,"
+ + SmartDialDbColumns.CONTACT_ID + " INTEGER,"
+ + SmartDialDbColumns.LOOKUP_KEY + " TEXT,"
+ + SmartDialDbColumns.DISPLAY_NAME_PRIMARY + " TEXT, "
+ + SmartDialDbColumns.PHOTO_ID + " INTEGER, "
+ + SmartDialDbColumns.LAST_SMARTDIAL_UPDATE_TIME + " LONG, "
+ + SmartDialDbColumns.LAST_TIME_USED + " LONG, "
+ + SmartDialDbColumns.TIMES_USED + " INTEGER, "
+ + SmartDialDbColumns.STARRED + " INTEGER, "
+ + SmartDialDbColumns.IS_SUPER_PRIMARY + " INTEGER, "
+ + SmartDialDbColumns.IN_VISIBLE_GROUP + " INTEGER, "
+ + SmartDialDbColumns.IS_PRIMARY + " INTEGER"
+ + ");");
+
+ db.execSQL("CREATE TABLE " + Tables.PREFIX_TABLE + " ("
+ + PrefixColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ + PrefixColumns.PREFIX + " TEXT COLLATE NOCASE, "
+ + PrefixColumns.CONTACT_ID + " INTEGER"
+ + ");");
+
+ db.execSQL("CREATE TABLE " + Tables.PROPERTIES + " ("
+ + PropertiesColumns.PROPERTY_KEY + " TEXT PRIMARY KEY, "
+ + PropertiesColumns.PROPERTY_VALUE + " TEXT "
+ + ");");
+
+ // This will need to also be updated in setupTablesForFilteredNumberTest and onUpgrade.
+ // Hardcoded so we know on glance what columns are updated in setupTables,
+ // and to be able to guarantee the state of the DB at each upgrade step.
+ db.execSQL("CREATE TABLE " + Tables.FILTERED_NUMBER_TABLE + " ("
+ + FilteredNumberColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ + FilteredNumberColumns.NORMALIZED_NUMBER + " TEXT,"
+ + FilteredNumberColumns.COUNTRY_ISO + " TEXT,"
+ + FilteredNumberColumns.TIMES_FILTERED + " INTEGER,"
+ + FilteredNumberColumns.LAST_TIME_FILTERED + " LONG,"
+ + FilteredNumberColumns.CREATION_TIME + " LONG,"
+ + FilteredNumberColumns.TYPE + " INTEGER,"
+ + FilteredNumberColumns.SOURCE + " INTEGER"
+ + ");");
setProperty(db, DATABASE_VERSION_PROPERTY, String.valueOf(DATABASE_VERSION));
- resetSmartDialLastUpdatedTime();
+ if (!mIsTestInstance) {
+ resetSmartDialLastUpdatedTime();
+ }
}
public void dropTables(SQLiteDatabase db) {
@@ -414,6 +438,20 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
return;
}
+ if (oldVersion < 5) {
+ db.execSQL("CREATE TABLE " + Tables.FILTERED_NUMBER_TABLE + " ("
+ + FilteredNumberColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ + FilteredNumberColumns.NORMALIZED_NUMBER + " TEXT,"
+ + FilteredNumberColumns.COUNTRY_ISO + " TEXT,"
+ + FilteredNumberColumns.TIMES_FILTERED + " INTEGER,"
+ + FilteredNumberColumns.LAST_TIME_FILTERED + " LONG,"
+ + FilteredNumberColumns.CREATION_TIME + " LONG,"
+ + FilteredNumberColumns.TYPE + " INTEGER,"
+ + FilteredNumberColumns.SOURCE + " INTEGER"
+ + ");");
+ oldVersion = 5;
+ }
+
if (oldVersion != DATABASE_VERSION) {
throw new IllegalStateException(
"error upgrading the database to version " + DATABASE_VERSION);
diff --git a/src/com/android/dialer/database/FilteredNumberContract.java b/src/com/android/dialer/database/FilteredNumberContract.java
new file mode 100644
index 000000000..1fb2363d0
--- /dev/null
+++ b/src/com/android/dialer/database/FilteredNumberContract.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2015 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.database;
+
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+/**
+ * <p>
+ * The contract between the filtered number provider and applications. Contains
+ * definitions for the supported URIs and columns.
+ * Currently only accessible within Dialer.
+ * </p>
+ */
+public final class FilteredNumberContract {
+
+ /** The authority for the filtered numbers provider */
+ public static final String AUTHORITY = "com.android.dialer";
+
+ /** A content:// style uri to the authority for the filtered numbers provider */
+ public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
+
+ /** The type of filtering to be applied, e.g. block the number or whitelist the number. */
+ public interface FilteredNumberTypes {
+ static final int UNDEFINED = 0;
+ /**
+ * Dialer will disconnect the call without sending the caller to voicemail.
+ */
+ static final int BLOCKED_NUMBER = 1;
+ }
+
+ /** The original source of the filtered number, e.g. the user manually added it. */
+ public interface FilteredNumberSources {
+ static final int UNDEFINED = 0;
+ /**
+ * The user manually added this number through Dialer (e.g. from the call log or InCallUI).
+ */
+ static final int USER = 1;
+ }
+
+ public interface FilteredNumberColumns {
+ // TYPE: INTEGER
+ static final String _ID = "id";
+ /**
+ * Represents the number to be filtered, normalized to compare phone numbers for equality.
+ *
+ * TYPE: TEXT
+ */
+ static final String NORMALIZED_NUMBER = "normalized_number";
+ /**
+ * The country code representing the country detected when
+ * the phone number was added to the database.
+ * Most numbers don't have the country code, so a best guess is provided by
+ * the country detector system. The country iso is also needed in order to format
+ * phone numbers correctly.
+ *
+ * TYPE: TEXT
+ */
+ static final String COUNTRY_ISO = "country_iso";
+ /**
+ * The number of times the number has been filtered by Dialer.
+ * When this number is incremented, LAST_TIME_FILTERED should also be updated to
+ * the current time.
+ *
+ * TYPE: INTEGER
+ */
+ static final String TIMES_FILTERED = "times_filtered";
+ /**
+ * Set to the current time when the phone number is filtered.
+ * When this is updated, TIMES_FILTERED should also be incremented.
+ *
+ * TYPE: LONG
+ */
+ static final String LAST_TIME_FILTERED = "last_time_filtered";
+ // TYPE: LONG
+ static final String CREATION_TIME = "creation_time";
+ /**
+ * Indicates the type of filtering to be applied.
+ *
+ * TYPE: INTEGER
+ * See {@link FilteredNumberTypes}
+ */
+ static final String TYPE = "type";
+ /**
+ * Integer representing the original source of the filtered number.
+ *
+ * TYPE: INTEGER
+ * See {@link FilteredNumberSources}
+ */
+ static final String SOURCE = "source";
+ }
+
+ /**
+ * <p>
+ * Constants for the table of filtered numbers.
+ * </p>
+ * <h3>Operations</h3>
+ * <dl>
+ * <dt><b>Insert</b></dt>
+ * <dd>Required fields: NORMALIZED_NUMBER, TYPE, SOURCE.
+ * A default value will be used for the other fields if left null.</dd>
+ * <dt><b>Update</b></dt>
+ * <dt><b>Delete</b></dt>
+ * <dt><b>Query</b></dt>
+ * <dd>{@link #CONTENT_URI} can be used for any query, append an ID to
+ * retrieve a specific filtered number entry.</dd>
+ * </dl>
+ */
+ public static class FilteredNumber implements BaseColumns {
+
+ public static final String FILTERED_NUMBERS_TABLE = "filtered_numbers_table";
+
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(
+ AUTHORITY_URI,
+ FILTERED_NUMBERS_TABLE);
+
+ /**
+ * This utility class cannot be instantiated.
+ */
+ private FilteredNumber () {}
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of
+ * filtered numbers.
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/filtered_numbers_table";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} single filtered number.
+ */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/filtered_numbers_table";
+
+ }
+}
diff --git a/src/com/android/dialer/database/FilteredNumberProvider.java b/src/com/android/dialer/database/FilteredNumberProvider.java
new file mode 100644
index 000000000..2bacd89b2
--- /dev/null
+++ b/src/com/android/dialer/database/FilteredNumberProvider.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2015 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.database;
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.os.Binder;
+import android.text.TextUtils;
+import android.text.format.Time;
+import android.util.Log;
+
+import com.android.contacts.common.GeoUtil;
+import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns;
+import com.android.dialerbind.DatabaseHelperManager;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.Arrays;
+
+/**
+ * Filtered number content provider.
+ */
+public class FilteredNumberProvider extends ContentProvider {
+
+ private static String TAG = FilteredNumberProvider.class.getSimpleName();
+
+ private DialerDatabaseHelper mDialerDatabaseHelper;
+
+ private static final int FILTERED_NUMBERS_TABLE = 1;
+ private static final int FILTERED_NUMBERS_TABLE_ID = 2;
+
+ private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ static {
+ sUriMatcher.addURI(FilteredNumberContract.AUTHORITY,
+ FilteredNumberContract.FilteredNumber.FILTERED_NUMBERS_TABLE,
+ FILTERED_NUMBERS_TABLE);
+ sUriMatcher.addURI(FilteredNumberContract.AUTHORITY,
+ FilteredNumberContract.FilteredNumber.FILTERED_NUMBERS_TABLE + "/#",
+ FILTERED_NUMBERS_TABLE_ID);
+ }
+
+ @Override
+ public boolean onCreate() {
+ mDialerDatabaseHelper = getDatabaseHelper(getContext());
+ if (mDialerDatabaseHelper == null) {
+ return false;
+ }
+ return true;
+ }
+
+ @VisibleForTesting
+ protected DialerDatabaseHelper getDatabaseHelper(Context context) {
+ return DatabaseHelperManager.getDatabaseHelper(context);
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ Log.d(TAG, "query: uri=" + uri + " projection=" + Arrays.toString(projection) +
+ " selection=[" + selection + "] args=" + Arrays.toString(selectionArgs) +
+ " order=[" + sortOrder + "] CPID=" + Binder.getCallingPid());
+
+ final SQLiteDatabase db = mDialerDatabaseHelper.getReadableDatabase();
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+ qb.setTables(DialerDatabaseHelper.Tables.FILTERED_NUMBER_TABLE);
+ final int match = sUriMatcher.match(uri);
+ switch (match) {
+ case FILTERED_NUMBERS_TABLE:
+ break;
+ case FILTERED_NUMBERS_TABLE_ID:
+ qb.appendWhere(FilteredNumberColumns._ID + "=" + ContentUris.parseId(uri));
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown uri: " + uri);
+ }
+ final Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, null);
+ if (c != null) {
+ c.setNotificationUri(getContext().getContentResolver(),
+ FilteredNumberContract.FilteredNumber.CONTENT_URI);
+ } else {
+ Log.d(TAG, "CURSOR WAS NULL");
+ }
+ return c;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return FilteredNumberContract.FilteredNumber.CONTENT_ITEM_TYPE;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ SQLiteDatabase db = mDialerDatabaseHelper.getWritableDatabase();
+ setDefaultValues(values);
+ long id = db.insert(DialerDatabaseHelper.Tables.FILTERED_NUMBER_TABLE, null, values);
+ if (id < 0) {
+ return null;
+ }
+ notifyChange(uri);
+ return ContentUris.withAppendedId(uri, id);
+ }
+
+ @VisibleForTesting
+ protected long getCurrentTimeMs() {
+ Time timeNow = new Time();
+ timeNow.setToNow();
+ return timeNow.toMillis(false);
+ }
+
+ private void setDefaultValues(ContentValues values) {
+ if (values.getAsString(FilteredNumberColumns.COUNTRY_ISO) == null) {
+ values.put(FilteredNumberColumns.COUNTRY_ISO,
+ GeoUtil.getCurrentCountryIso(getContext()));
+ }
+ if (values.getAsInteger(FilteredNumberColumns.TIMES_FILTERED) == null) {
+ values.put(FilteredNumberContract.FilteredNumberColumns.TIMES_FILTERED, 0);
+ }
+ if (values.getAsLong(FilteredNumberColumns.CREATION_TIME) == null) {
+ values.put(FilteredNumberColumns.CREATION_TIME, getCurrentTimeMs());
+ }
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ SQLiteDatabase db = mDialerDatabaseHelper.getWritableDatabase();
+ final int match = sUriMatcher.match(uri);
+ switch (match) {
+ case FILTERED_NUMBERS_TABLE:
+ break;
+ case FILTERED_NUMBERS_TABLE_ID:
+ selection = getSelectionWithId(selection, ContentUris.parseId(uri));
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown uri: " + uri);
+ }
+ int rows = db.delete(DialerDatabaseHelper.Tables.FILTERED_NUMBER_TABLE,
+ selection,
+ selectionArgs);
+ if (rows > 0) {
+ notifyChange(uri);
+ }
+ return rows;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ SQLiteDatabase db = mDialerDatabaseHelper.getWritableDatabase();
+ final int match = sUriMatcher.match(uri);
+ switch (match) {
+ case FILTERED_NUMBERS_TABLE:
+ break;
+ case FILTERED_NUMBERS_TABLE_ID:
+ selection = getSelectionWithId(selection, ContentUris.parseId(uri));
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown uri: " + uri);
+ }
+ int rows = db.update(DialerDatabaseHelper.Tables.FILTERED_NUMBER_TABLE,
+ values,
+ selection,
+ selectionArgs);
+ if (rows > 0 ) {
+ notifyChange(uri);
+ }
+ return rows;
+ }
+
+ private String getSelectionWithId(String selection, long id) {
+ if (TextUtils.isEmpty(selection)) {
+ return FilteredNumberContract.FilteredNumberColumns._ID + "=" + id;
+ } else {
+ return selection + "AND " + FilteredNumberContract.FilteredNumberColumns._ID + "=" + id;
+ }
+ }
+
+ private void notifyChange(Uri uri) {
+ getContext().getContentResolver().notifyChange(uri, null);
+ }
+}