summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/providers/contacts/CallLogProvider.java22
-rw-r--r--src/com/android/providers/contacts/DatabaseModifier.java51
-rw-r--r--src/com/android/providers/contacts/DbModifierWithVmNotification.java231
-rw-r--r--src/com/android/providers/contacts/VoicemailContentProvider.java56
-rw-r--r--src/com/android/providers/contacts/VoicemailContentTable.java45
-rw-r--r--src/com/android/providers/contacts/VoicemailStatusTable.java27
-rw-r--r--src/com/android/providers/contacts/VoicemailTable.java11
-rw-r--r--tests/src/com/android/providers/contacts/CallLogProviderTest.java18
-rw-r--r--tests/src/com/android/providers/contacts/MockPackageManager.java54
-rw-r--r--tests/src/com/android/providers/contacts/VoicemailProviderTest.java14
10 files changed, 396 insertions, 133 deletions
diff --git a/src/com/android/providers/contacts/CallLogProvider.java b/src/com/android/providers/contacts/CallLogProvider.java
index c42c810..e45c1c2 100644
--- a/src/com/android/providers/contacts/CallLogProvider.java
+++ b/src/com/android/providers/contacts/CallLogProvider.java
@@ -177,7 +177,7 @@ public class CallLogProvider extends ContentProvider {
SQLiteDatabase db = mDbHelper.getWritableDatabase();
mCallsInserter = new DatabaseUtils.InsertHelper(db, Tables.CALLS);
}
- long rowId = mCallsInserter.insert(values);
+ long rowId = getDatabaseModifier(mCallsInserter).insert(values);
if (rowId > 0) {
notifyChange();
return ContentUris.withAppendedId(uri, rowId);
@@ -211,7 +211,8 @@ public class CallLogProvider extends ContentProvider {
throw new UnsupportedOperationException("Cannot update URL: " + uri);
}
- int count = db.update(Tables.CALLS, values, selectionBuilder.build(), selectionArgs);
+ int count = getDatabaseModifier(db).update(Tables.CALLS, values,
+ selectionBuilder.build(), selectionArgs);
if (count > 0) {
notifyChange();
}
@@ -227,7 +228,8 @@ public class CallLogProvider extends ContentProvider {
final int matchedUriId = sURIMatcher.match(uri);
switch (matchedUriId) {
case CALLS:
- int count = db.delete(Tables.CALLS, selectionBuilder.build(), selectionArgs);
+ int count = getDatabaseModifier(db).delete(Tables.CALLS,
+ selectionBuilder.build(), selectionArgs);
if (count > 0) {
notifyChange();
}
@@ -247,6 +249,20 @@ public class CallLogProvider extends ContentProvider {
return mCountryMonitor.getCountryIso();
}
+ // Work around to let the test code override the context. getContext() is final so cannot be
+ // overridden.
+ protected Context context() {
+ return getContext();
+ }
+
+ private DatabaseModifier getDatabaseModifier(SQLiteDatabase db) {
+ return new DbModifierWithVmNotification(Tables.CALLS, db, context());
+ }
+
+ private DatabaseModifier getDatabaseModifier(DatabaseUtils.InsertHelper insertHelper) {
+ return new DbModifierWithVmNotification(Tables.CALLS, insertHelper, context());
+ }
+
private boolean hasVoicemailValue(ContentValues values) {
return values.containsKey(Calls.TYPE) &&
values.getAsInteger(Calls.TYPE).equals(Calls.VOICEMAIL_TYPE);
diff --git a/src/com/android/providers/contacts/DatabaseModifier.java b/src/com/android/providers/contacts/DatabaseModifier.java
new file mode 100644
index 0000000..3f5a402
--- /dev/null
+++ b/src/com/android/providers/contacts/DatabaseModifier.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 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.providers.contacts;
+
+import android.content.ContentValues;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+
+/**
+ * An interface which wraps key database modify operations (insert, update, delete) to perform
+ * additional tasks before or after the database modification operation. A typical use case is to
+ * generate notification when a database is modified.
+ */
+public interface DatabaseModifier {
+ /**
+ * Use this method to insert a value which you would otherwise do using the
+ * {@link SQLiteDatabase#insert(String, String, ContentValues)} method.
+ */
+ public abstract long insert(String table, String nullColumnHack, ContentValues values);
+ /**
+ * Use this method to insert a value which you would otherwise do using the
+ * {@link DatabaseUtils.InsertHelper#insert(ContentValues)} method.
+ */
+ public abstract long insert(ContentValues values);
+ /**
+ * Use this method to update a table which you would otherwise do using the
+ * {@link SQLiteDatabase#update(String, ContentValues, String, String[])} method.
+ */
+ public abstract int update(String table, ContentValues values,
+ String whereClause, String[] whereArgs);
+ /**
+ * Use this method to delete entries from a table which you would otherwise do using the
+ * {@link SQLiteDatabase#delete(String, String, String[])} method.
+ */
+ public abstract int delete(String table, String whereClause, String[] whereArgs);
+}
diff --git a/src/com/android/providers/contacts/DbModifierWithVmNotification.java b/src/com/android/providers/contacts/DbModifierWithVmNotification.java
new file mode 100644
index 0000000..b71819e
--- /dev/null
+++ b/src/com/android/providers/contacts/DbModifierWithVmNotification.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2011 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.providers.contacts;
+
+import static android.Manifest.permission.READ_WRITE_OWN_VOICEMAIL;
+import static com.android.providers.contacts.Manifest.permission.READ_WRITE_ALL_VOICEMAIL;
+
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.util.DbQueryUtils;
+import com.google.android.collect.Lists;
+
+import android.content.ComponentName;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ResolveInfo;
+import android.database.Cursor;
+import android.database.DatabaseUtils.InsertHelper;
+import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.os.Binder;
+import android.provider.VoicemailContract;
+import android.provider.VoicemailContract.Status;
+import android.provider.VoicemailContract.Voicemails;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * An implementation of {@link DatabaseModifier} for voicemail related tables which additionally
+ * generates necessary notifications after the modification operation is performed.
+ */
+public class DbModifierWithVmNotification implements DatabaseModifier {
+ private static final String TAG = "DbModifierWithVmNotification";
+
+ private static final String[] PROJECTION = new String[] {
+ VoicemailContract.SOURCE_PACKAGE_FIELD
+ };
+ private static final int SOURCE_PACKAGE_COLUMN_INDEX = 0;
+ private static final String NON_NULL_SOURCE_PACKAGE_SELECTION =
+ VoicemailContract.SOURCE_PACKAGE_FIELD + " IS NOT NULL";
+
+ private final String mTableName;
+ private final SQLiteDatabase mDb;
+ private final InsertHelper mInsertHelper;
+ private final Context mContext;
+ private final Uri mBaseUri;
+ private final boolean mIsVoicemailContentTable;
+ private final VoicemailPermissions mVoicemailPermissions;
+
+ public DbModifierWithVmNotification(String tableName, SQLiteDatabase db, Context context) {
+ this(tableName, db, null, context);
+ }
+
+ public DbModifierWithVmNotification(String tableName, InsertHelper insertHelper,
+ Context context) {
+ this(tableName, null, insertHelper, context);
+ }
+
+ private DbModifierWithVmNotification(String tableName, SQLiteDatabase db,
+ InsertHelper insertHelper, Context context) {
+ mTableName = tableName;
+ mDb = db;
+ mInsertHelper = insertHelper;
+ mContext = context;
+ mBaseUri = mTableName.equals(Tables.VOICEMAIL_STATUS) ?
+ Status.CONTENT_URI : Voicemails.CONTENT_URI;
+ mIsVoicemailContentTable = !mTableName.equals(Tables.VOICEMAIL_STATUS);
+ mVoicemailPermissions = new VoicemailPermissions(mContext);
+ }
+
+ @Override
+ public long insert(String table, String nullColumnHack, ContentValues values) {
+ Set<String> packagesModified = getModifiedPackages(values);
+ long rowId = mDb.insert(table, nullColumnHack, values);
+ if (rowId > 0 && packagesModified.size() != 0) {
+ notifyOnInsert(ContentUris.withAppendedId(mBaseUri, rowId), packagesModified);
+ }
+ return rowId;
+ }
+
+ @Override
+ public long insert(ContentValues values) {
+ Set<String> packagesModified = getModifiedPackages(values);
+ long rowId = mInsertHelper.insert(values);
+ if (rowId > 0 && packagesModified.size() != 0) {
+ notifyOnInsert(ContentUris.withAppendedId(mBaseUri, rowId), packagesModified);
+ }
+ return rowId;
+ }
+
+ private void notifyOnInsert(Uri notificationUri, Set<String> packagesModified) {
+ if (mIsVoicemailContentTable) {
+ notifyChange(notificationUri, packagesModified, VoicemailContract.ACTION_NEW_VOICEMAIL,
+ Intent.ACTION_PROVIDER_CHANGED);
+ } else {
+ notifyChange(notificationUri, packagesModified, Intent.ACTION_PROVIDER_CHANGED);
+ }
+ }
+
+ @Override
+ public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
+ Set<String> packagesModified = getModifiedPackages(whereClause, whereArgs);
+ packagesModified.addAll(getModifiedPackages(values));
+ int count = mDb.update(table, values, whereClause, whereArgs);
+ if (count > 0 && packagesModified.size() != 0) {
+ notifyChange(mBaseUri, packagesModified, Intent.ACTION_PROVIDER_CHANGED);
+ }
+ return count;
+ }
+
+ @Override
+ public int delete(String table, String whereClause, String[] whereArgs) {
+ Set<String> packagesModified = getModifiedPackages(whereClause, whereArgs);
+ int count = mDb.delete(table, whereClause, whereArgs);
+ if (count > 0 && packagesModified.size() != 0) {
+ notifyChange(mBaseUri, packagesModified, Intent.ACTION_PROVIDER_CHANGED);
+ }
+ return count;
+ }
+
+ /**
+ * Returns the set of packages affected when a modify operation is run for the specified
+ * where clause. When called from an insert operation an empty set returned by this method
+ * implies (indirectly) that this does not affect any voicemail entry, as a voicemail entry is
+ * always expected to have the source package field set.
+ */
+ private Set<String> getModifiedPackages(String whereClause, String[] whereArgs) {
+ Set<String> modifiedPackages = new HashSet<String>();
+ Cursor cursor = mDb.query(mTableName, PROJECTION,
+ DbQueryUtils.concatenateClauses(NON_NULL_SOURCE_PACKAGE_SELECTION, whereClause),
+ whereArgs, null, null, null);
+ while(cursor.moveToNext()) {
+ modifiedPackages.add(cursor.getString(SOURCE_PACKAGE_COLUMN_INDEX));
+ }
+ return modifiedPackages;
+ }
+
+ /**
+ * Returns the source package that gets affected (in an insert/update operation) by the supplied
+ * content values. An empty set returned by this method also implies (indirectly) that this does
+ * not affect any voicemail entry, as a voicemail entry is always expected to have the source
+ * package field set.
+ */
+ private Set<String> getModifiedPackages(ContentValues values) {
+ Set<String> impactedPackages = new HashSet<String>();
+ if(values.containsKey(VoicemailContract.SOURCE_PACKAGE_FIELD)) {
+ impactedPackages.add(values.getAsString(VoicemailContract.SOURCE_PACKAGE_FIELD));
+ }
+ return impactedPackages;
+ }
+
+ private void notifyChange(Uri notificationUri, Set<String> modifiedPackages,
+ String... intentActions) {
+ // Notify the observers.
+ // Must be done only once, even if there are multiple broadcast intents.
+ mContext.getContentResolver().notifyChange(notificationUri, null, true);
+ Collection<String> callingPackages = getCallingPackages();
+ // Now fire individual intents.
+ for (String intentAction : intentActions) {
+ // self_change extra should be included only for provider_changed events.
+ boolean includeSelfChangeExtra = intentAction.equals(Intent.ACTION_PROVIDER_CHANGED);
+ for (ComponentName component :
+ getBroadcastReceiverComponents(intentAction, notificationUri)) {
+ Intent intent = new Intent(intentAction, notificationUri);
+ intent.setComponent(component);
+ if (includeSelfChangeExtra && callingPackages != null) {
+ intent.putExtra(VoicemailContract.EXTRA_SELF_CHANGE,
+ callingPackages.contains(component.getPackageName()));
+ }
+ // If this package is not affected by the change then it shall receive the intent
+ // only if it has READ_WRITE_ALL_VOICEMAIL permissions.
+ String permissionNeeded = modifiedPackages.contains(component.getPackageName()) ?
+ READ_WRITE_OWN_VOICEMAIL : READ_WRITE_ALL_VOICEMAIL;
+ mContext.sendBroadcast(intent, permissionNeeded);
+ Log.v(TAG, String.format("Sent intent. act:%s, url:%s, comp:%s, perm:%s," +
+ " self_change:%s", intent.getAction(), intent.getData(),
+ component.getClassName(), permissionNeeded,
+ intent.hasExtra(VoicemailContract.EXTRA_SELF_CHANGE) ?
+ intent.getBooleanExtra(VoicemailContract.EXTRA_SELF_CHANGE, false) :
+ null));
+ }
+ }
+ }
+
+ /** Determines the components that can possibly receive the specified intent. */
+ private List<ComponentName> getBroadcastReceiverComponents(String intentAction, Uri uri) {
+ Intent intent = new Intent(intentAction, uri);
+ List<ComponentName> receiverComponents = new ArrayList<ComponentName>();
+ // For broadcast receivers ResolveInfo.activityInfo is the one that is populated.
+ for (ResolveInfo resolveInfo :
+ mContext.getPackageManager().queryBroadcastReceivers(intent, 0)) {
+ ActivityInfo activityInfo = resolveInfo.activityInfo;
+ receiverComponents.add(new ComponentName(activityInfo.packageName, activityInfo.name));
+ }
+ return receiverComponents;
+ }
+
+ /**
+ * Returns the package names of the calling process. If the calling process has more than
+ * one packages, this returns them all
+ */
+ private Collection<String> getCallingPackages() {
+ int caller = Binder.getCallingUid();
+ if (caller == 0) {
+ return null;
+ }
+ return Lists.newArrayList(mContext.getPackageManager().getPackagesForUid(caller));
+ }
+}
diff --git a/src/com/android/providers/contacts/VoicemailContentProvider.java b/src/com/android/providers/contacts/VoicemailContentProvider.java
index cbebb9c..e1f44ca 100644
--- a/src/com/android/providers/contacts/VoicemailContentProvider.java
+++ b/src/com/android/providers/contacts/VoicemailContentProvider.java
@@ -23,14 +23,9 @@ import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
import com.android.providers.contacts.util.SelectionBuilder;
import com.android.providers.contacts.util.TypedUriMatcherImpl;
-import android.content.ComponentName;
import android.content.ContentProvider;
-import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
@@ -40,7 +35,6 @@ import android.provider.VoicemailContract;
import android.provider.VoicemailContract.Voicemails;
import java.io.FileNotFoundException;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -53,7 +47,6 @@ public class VoicemailContentProvider extends ContentProvider
implements VoicemailTable.DelegateHelper {
private static final String TAG = "VoicemailContentProvider";
- private ContentResolver mContentResolver;
private VoicemailPermissions mVoicemailPermissions;
private VoicemailTable.Delegate mVoicemailContentTable;
private VoicemailTable.Delegate mVoicemailStatusTable;
@@ -61,7 +54,6 @@ public class VoicemailContentProvider extends ContentProvider
@Override
public boolean onCreate() {
Context context = context();
- mContentResolver = context.getContentResolver();
mVoicemailPermissions = new VoicemailPermissions(context);
mVoicemailContentTable = new VoicemailContentTable(Tables.CALLS, context,
getDatabaseHelper(context), this);
@@ -91,12 +83,6 @@ public class VoicemailContentProvider extends ContentProvider
}
@Override
- public int bulkInsert(Uri uri, ContentValues[] valuesArray) {
- UriData uriData = checkPermissionsAndCreateUriData(uri, valuesArray);
- return getTableDelegate(uriData).bulkInsert(uriData, valuesArray);
- }
-
- @Override
public Uri insert(Uri uri, ContentValues values) {
UriData uriData = checkPermissionsAndCreateUriData(uri, values);
return getTableDelegate(uriData).insert(uriData, values);
@@ -234,35 +220,6 @@ public class VoicemailContentProvider extends ContentProvider
@Override
// VoicemailTable.DelegateHelper interface.
- public void notifyChange(Uri notificationUri, String... intentActions) {
- // Notify the observers.
- mContentResolver.notifyChange(notificationUri, null, true);
- String callingPackage = getCallingPackage();
- // Fire notification intents.
- for (String intentAction : intentActions) {
- // TODO: We can possibly be more intelligent here and send targeted intents based on
- // what voicemail permission the package has. If possible, here is what we would like to
- // do for a given broadcast intent -
- // 1) Send it to all packages that have READ_WRITE_ALL_VOICEMAIL permission.
- // 2) Send it to only the owner package that has just READ_WRITE_OWN_VOICEMAIL, if not
- // already sent in (1).
- for (ComponentName component :
- getBroadcastReceiverComponents(intentAction, notificationUri)) {
- Intent intent = new Intent(intentAction, notificationUri);
- intent.setComponent(component);
- // self_change extra should be included only for provider_changed events.
- if (intentAction.equals(Intent.ACTION_PROVIDER_CHANGED)) {
- intent.putExtra(VoicemailContract.EXTRA_SELF_CHANGE,
- callingPackage.equals(component.getPackageName()));
- }
- context().sendBroadcast(intent,
- android.Manifest.permission.READ_WRITE_OWN_VOICEMAIL);
- }
- }
- }
-
- @Override
- // VoicemailTable.DelegateHelper interface.
public void checkAndAddSourcePackageIntoValues(UriData uriData, ContentValues values) {
// If content values don't contain the provider, calculate the right provider to use.
if (!values.containsKey(SOURCE_PACKAGE_FIELD)) {
@@ -406,17 +363,4 @@ public class VoicemailContentProvider extends ContentProvider
}
return getEqualityClause(Voicemails.SOURCE_PACKAGE, getCallingPackage());
}
-
- /** Determines the components that can possibly receive the specified intent. */
- protected List<ComponentName> getBroadcastReceiverComponents(String intentAction, Uri uri) {
- Intent intent = new Intent(intentAction, uri);
- List<ComponentName> receiverComponents = new ArrayList<ComponentName>();
- // For broadcast receivers ResolveInfo.activityInfo is the one that is populated.
- for (ResolveInfo resolveInfo :
- context().getPackageManager().queryBroadcastReceivers(intent, 0)) {
- ActivityInfo activityInfo = resolveInfo.activityInfo;
- receiverComponents.add(new ComponentName(activityInfo.packageName, activityInfo.name));
- }
- return receiverComponents;
- }
}
diff --git a/src/com/android/providers/contacts/VoicemailContentTable.java b/src/com/android/providers/contacts/VoicemailContentTable.java
index 19961c4..b9afbd7 100644
--- a/src/com/android/providers/contacts/VoicemailContentTable.java
+++ b/src/com/android/providers/contacts/VoicemailContentTable.java
@@ -25,7 +25,6 @@ import com.android.providers.contacts.util.CloseUtils;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
-import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
@@ -33,7 +32,6 @@ import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.provider.CallLog.Calls;
-import android.provider.VoicemailContract;
import android.provider.VoicemailContract.Voicemails;
import android.util.Log;
@@ -81,26 +79,7 @@ public class VoicemailContentTable implements VoicemailTable.Delegate {
}
@Override
- public int bulkInsert(UriData uriData, ContentValues[] valuesArray) {
- int numInserted = 0;
- for (ContentValues values : valuesArray) {
- if (insertInternal(uriData, values, false) != null) {
- numInserted++;
- }
- }
- if (numInserted > 0) {
- mDelegateHelper.notifyChange(uriData.getUri(), Intent.ACTION_PROVIDER_CHANGED);
- }
- return numInserted;
- }
-
- @Override
public Uri insert(UriData uriData, ContentValues values) {
- return insertInternal(uriData, values, true);
- }
-
- private Uri insertInternal(UriData uriData, ContentValues values,
- boolean sendProviderChangedNotification) {
checkForSupportedColumns(sVoicemailProjectionMap, values);
ContentValues copiedValues = new ContentValues(values);
checkInsertSupported(uriData);
@@ -114,13 +93,9 @@ public class VoicemailContentTable implements VoicemailTable.Delegate {
copiedValues.put(Calls.TYPE, Calls.VOICEMAIL_TYPE);
SQLiteDatabase db = mDbHelper.getWritableDatabase();
- long rowId = db.insert(mTableName, null, copiedValues);
+ long rowId = getDatabaseModifier(db).insert(mTableName, null, copiedValues);
if (rowId > 0) {
Uri newUri = ContentUris.withAppendedId(uriData.getUri(), rowId);
- mDelegateHelper.notifyChange(newUri, VoicemailContract.ACTION_NEW_VOICEMAIL);
- if (sendProviderChangedNotification) {
- mDelegateHelper.notifyChange(newUri, Intent.ACTION_PROVIDER_CHANGED);
- }
// Populate the 'voicemail_uri' field to be used by the call_log provider.
updateVoicemailUri(db, newUri);
return newUri;
@@ -181,11 +156,8 @@ public class VoicemailContentTable implements VoicemailTable.Delegate {
}
// Now delete the rows themselves.
- int count = db.delete(mTableName, combinedClause, selectionArgs);
- if (count > 0) {
- mDelegateHelper.notifyChange(uriData.getUri(), Intent.ACTION_PROVIDER_CHANGED);
- }
- return count;
+ return getDatabaseModifier(db).delete(mTableName, combinedClause,
+ selectionArgs);
}
@Override
@@ -216,11 +188,8 @@ public class VoicemailContentTable implements VoicemailTable.Delegate {
// URI that include message Id. I think we do want to support bulk update.
String combinedClause = concatenateClauses(selection, uriData.getWhereClause(),
getCallTypeClause());
- int count = db.update(mTableName, values, combinedClause, selectionArgs);
- if (count > 0) {
- mDelegateHelper.notifyChange(uriData.getUri(), Intent.ACTION_PROVIDER_CHANGED);
- }
- return count;
+ return getDatabaseModifier(db).update(mTableName, values, combinedClause,
+ selectionArgs);
}
private void checkUpdateSupported(UriData uriData) {
@@ -277,4 +246,8 @@ public class VoicemailContentTable implements VoicemailTable.Delegate {
private String getCallTypeClause() {
return getEqualityClause(Calls.TYPE, String.valueOf(Calls.VOICEMAIL_TYPE));
}
+
+ private DatabaseModifier getDatabaseModifier(SQLiteDatabase db) {
+ return new DbModifierWithVmNotification(mTableName, db, mContext);
+ }
}
diff --git a/src/com/android/providers/contacts/VoicemailStatusTable.java b/src/com/android/providers/contacts/VoicemailStatusTable.java
index 1f1fa8b..504af46 100644
--- a/src/com/android/providers/contacts/VoicemailStatusTable.java
+++ b/src/com/android/providers/contacts/VoicemailStatusTable.java
@@ -23,7 +23,6 @@ import com.android.providers.contacts.VoicemailContentProvider.UriData;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
-import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
@@ -64,10 +63,9 @@ public class VoicemailStatusTable implements VoicemailTable.Delegate {
SQLiteDatabase db = mDbHelper.getWritableDatabase();
ContentValues copiedValues = new ContentValues(values);
mDelegateHelper.checkAndAddSourcePackageIntoValues(uriData, copiedValues);
- long rowId = db.insert(mTableName, null, copiedValues);
+ long rowId = getDatabaseModifier(db).insert(mTableName, null, copiedValues);
if (rowId > 0) {
Uri newUri = ContentUris.withAppendedId(uriData.getUri(), rowId);
- mDelegateHelper.notifyChange(newUri, Intent.ACTION_PROVIDER_CHANGED);
return newUri;
} else {
return null;
@@ -75,19 +73,11 @@ public class VoicemailStatusTable implements VoicemailTable.Delegate {
}
@Override
- public int bulkInsert(UriData uriData, ContentValues[] valuesArray) {
- throw new UnsupportedOperationException("bulkInsert is not supported for status table");
- }
-
- @Override
public int delete(UriData uriData, String selection, String[] selectionArgs) {
SQLiteDatabase db = mDbHelper.getWritableDatabase();
String combinedClause = concatenateClauses(selection, uriData.getWhereClause());
- int count = db.delete(mTableName, combinedClause, selectionArgs);
- if (count > 0) {
- mDelegateHelper.notifyChange(uriData.getUri(), Intent.ACTION_PROVIDER_CHANGED);
- }
- return count;
+ return getDatabaseModifier(db).delete(mTableName, combinedClause,
+ selectionArgs);
}
@Override
@@ -112,11 +102,8 @@ public class VoicemailStatusTable implements VoicemailTable.Delegate {
String[] selectionArgs) {
SQLiteDatabase db = mDbHelper.getWritableDatabase();
String combinedClause = concatenateClauses(selection, uriData.getWhereClause());
- int count = db.update(mTableName, values, combinedClause, selectionArgs);
- if (count > 0) {
- mDelegateHelper.notifyChange(uriData.getUri(), Intent.ACTION_PROVIDER_CHANGED);
- }
- return count;
+ return getDatabaseModifier(db).update(mTableName, values, combinedClause,
+ selectionArgs);
}
@Override
@@ -132,4 +119,8 @@ public class VoicemailStatusTable implements VoicemailTable.Delegate {
public ParcelFileDescriptor openFile(UriData uriData, String mode) {
throw new UnsupportedOperationException("File operation is not supported for status table");
}
+
+ private DatabaseModifier getDatabaseModifier(SQLiteDatabase db) {
+ return new DbModifierWithVmNotification(mTableName, db, mContext);
+ }
}
diff --git a/src/com/android/providers/contacts/VoicemailTable.java b/src/com/android/providers/contacts/VoicemailTable.java
index cab48fd..5af0cd0 100644
--- a/src/com/android/providers/contacts/VoicemailTable.java
+++ b/src/com/android/providers/contacts/VoicemailTable.java
@@ -35,7 +35,6 @@ public interface VoicemailTable {
*/
public interface Delegate {
public Uri insert(UriData uriData, ContentValues values);
- public int bulkInsert(UriData uriData, ContentValues[] valuesArray);
public int delete(UriData uriData, String selection, String[] selectionArgs);
public Cursor query(UriData uriData, String[] projection, String selection,
String[] selectionArgs, String sortOrder);
@@ -52,16 +51,6 @@ public interface VoicemailTable {
*/
public interface DelegateHelper {
/**
- * Notifies the content resolver and fires required broadcast intent(s) to notify about the
- * change.
- *
- * @param notificationUri The URI that got impacted due to the change. This is the URI that
- * is included in content resolver and broadcast intent notification.
- * @param intentActions List of intent actions that needs to be fired. A separate intent is
- * fired for each intent action.
- */
- public void notifyChange(Uri notificationUri, String... intentActions);
- /**
* Inserts source_package field into ContentValues. Used in insert operations.
*/
public void checkAndAddSourcePackageIntoValues(UriData uriData, ContentValues values);
diff --git a/tests/src/com/android/providers/contacts/CallLogProviderTest.java b/tests/src/com/android/providers/contacts/CallLogProviderTest.java
index 12ca128..29a42dc 100644
--- a/tests/src/com/android/providers/contacts/CallLogProviderTest.java
+++ b/tests/src/com/android/providers/contacts/CallLogProviderTest.java
@@ -23,6 +23,9 @@ import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.provider.CallLog;
@@ -342,6 +345,21 @@ public class CallLogProviderTest extends BaseContactsProvider2Test {
protected String getCurrentCountryIso() {
return "us";
}
+
+ @Override
+ protected Context context() {
+ return new ContextWrapper(super.context()) {
+ @Override
+ public PackageManager getPackageManager() {
+ return new MockPackageManager("com.test.package1", "com.test.package2");
+ }
+
+ @Override
+ public void sendBroadcast(Intent intent, String receiverPermission) {
+ // Do nothing for now.
+ }
+ };
+ }
}
}
diff --git a/tests/src/com/android/providers/contacts/MockPackageManager.java b/tests/src/com/android/providers/contacts/MockPackageManager.java
new file mode 100644
index 0000000..db1e79e
--- /dev/null
+++ b/tests/src/com/android/providers/contacts/MockPackageManager.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 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.providers.contacts;
+
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ResolveInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MockPackageManager extends android.test.mock.MockPackageManager {
+ private final String[] mPackages;
+ public MockPackageManager(String... packages) {
+ mPackages = packages;
+ }
+
+ @Override
+ public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
+ List<ResolveInfo> resolveInfos = new ArrayList<ResolveInfo>();
+ for (String pkg : mPackages) {
+ resolveInfos.add(createResolveInfo(pkg));
+ }
+ return resolveInfos;
+ }
+
+ private ResolveInfo createResolveInfo(String packageName) {
+ ActivityInfo activityInfo = new ActivityInfo();
+ activityInfo.packageName = packageName;
+ activityInfo.name = "FooClass";
+ ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.activityInfo = activityInfo;
+ return resolveInfo;
+ }
+
+ @Override
+ public String[] getPackagesForUid(int uid) {
+ return new String[] {mPackages[0]};
+ }
+}
diff --git a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
index baee751..e214f60 100644
--- a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
+++ b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
@@ -16,13 +16,13 @@
package com.android.providers.contacts;
-import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.provider.CallLog.Calls;
@@ -539,6 +539,10 @@ public class VoicemailProviderTest extends BaseContactsProvider2Test {
public void sendBroadcast(Intent intent, String receiverPermission) {
mDelgate.sendOrderedBroadcast(intent, receiverPermission);
}
+ @Override
+ public PackageManager getPackageManager() {
+ return new MockPackageManager("com.test.package1", "com.test.package2");
+ }
};
}
@@ -546,14 +550,6 @@ public class VoicemailProviderTest extends BaseContactsProvider2Test {
protected String getCallingPackage() {
return getContext().getPackageName();
}
-
- @Override
- protected List<ComponentName> getBroadcastReceiverComponents(String intentAction, Uri uri) {
- List<ComponentName> broadcastReceiverComponents = new ArrayList<ComponentName>();
- broadcastReceiverComponents.add(new ComponentName(
- getContext().getPackageName(), "TestReceiverClass"));
- return broadcastReceiverComponents;
- }
}
/** Lazily construct the test directory when required. */