summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers/contacts
diff options
context:
space:
mode:
authorDebashish Chatterjee <debashishc@google.com>2011-07-06 11:41:59 +0100
committerDebashish Chatterjee <debashishc@google.com>2011-07-08 17:09:50 +0100
commit9cf06e7bcb0be759f1c930412fd2e41eba4f5f03 (patch)
tree254b7aee9c79066cf56740ee582bab463ac2ae24 /src/com/android/providers/contacts
parent83a60d38646265694ab9cfa88b9601c201edb303 (diff)
downloadpackages_providers_ContactsProvider-9cf06e7bcb0be759f1c930412fd2e41eba4f5f03.zip
packages_providers_ContactsProvider-9cf06e7bcb0be759f1c930412fd2e41eba4f5f03.tar.gz
packages_providers_ContactsProvider-9cf06e7bcb0be759f1c930412fd2e41eba4f5f03.tar.bz2
VoicemailStatus content provider implementation.
- New Voicemail.Delegate implementation for voicemail_status table. - modified openFile() interface to simplify the interaction. - UridData now has a getWhereClause() method that can be used by both the tables to set selection clause based on the uriData. - Imrpoved permission checks for ContentValues for update/insert/bulkinsert operations. Bug:4968719 Change-Id: I6a6173c58d9929ef952c7d7e95afb8bc5ff4157b
Diffstat (limited to 'src/com/android/providers/contacts')
-rw-r--r--src/com/android/providers/contacts/VoicemailContentProvider.java145
-rw-r--r--src/com/android/providers/contacts/VoicemailContentTable.java27
-rw-r--r--src/com/android/providers/contacts/VoicemailStatusTable.java135
-rw-r--r--src/com/android/providers/contacts/VoicemailTable.java15
-rw-r--r--src/com/android/providers/contacts/VoicemailUriType.java4
5 files changed, 264 insertions, 62 deletions
diff --git a/src/com/android/providers/contacts/VoicemailContentProvider.java b/src/com/android/providers/contacts/VoicemailContentProvider.java
index 3a093c0..6cdde4c 100644
--- a/src/com/android/providers/contacts/VoicemailContentProvider.java
+++ b/src/com/android/providers/contacts/VoicemailContentProvider.java
@@ -15,6 +15,8 @@
*/
package com.android.providers.contacts;
+import static android.provider.VoicemailContract.SOURCE_PACKAGE_FIELD;
+import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
import static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
@@ -33,6 +35,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
+import android.provider.BaseColumns;
import android.provider.VoicemailContract;
import android.provider.VoicemailContract.Voicemails;
@@ -41,23 +44,28 @@ import java.util.ArrayList;
import java.util.List;
/**
- * An implementation of the Voicemail content provider.
+ * An implementation of the Voicemail content provider. This class in the entry point for both
+ * voicemail content ('calls') table and 'voicemail_status' table. This class performs all common
+ * permission checks and then delegates database level operations to respective table delegate
+ * objects.
*/
public class VoicemailContentProvider extends ContentProvider
implements VoicemailTable.DelegateHelper {
private static final String TAG = "VoicemailContentProvider";
- private static final String VOICEMAILS_TABLE_NAME = Tables.CALLS;
private ContentResolver mContentResolver;
private VoicemailPermissions mVoicemailPermissions;
private VoicemailTable.Delegate mVoicemailContentTable;
+ private VoicemailTable.Delegate mVoicemailStatusTable;
@Override
public boolean onCreate() {
Context context = context();
mContentResolver = context.getContentResolver();
mVoicemailPermissions = new VoicemailPermissions(context);
- mVoicemailContentTable = new VoicemailContentTable(VOICEMAILS_TABLE_NAME, context,
+ mVoicemailContentTable = new VoicemailContentTable(Tables.CALLS, context,
+ getDatabaseHelper(context), this);
+ mVoicemailStatusTable = new VoicemailStatusTable(Tables.VOICEMAIL_STATUS, context,
getDatabaseHelper(context), this);
return true;
}
@@ -79,19 +87,19 @@ public class VoicemailContentProvider extends ContentProvider
// Special case: for illegal URIs, we return null rather than thrown an exception.
return null;
}
- return mVoicemailContentTable.getType(uriData);
+ return getTableDelegate(uriData).getType(uriData);
}
@Override
public int bulkInsert(Uri uri, ContentValues[] valuesArray) {
- UriData uriData = checkPermissionsAndCreateUriData(uri);
- return mVoicemailContentTable.bulkInsert(uriData, valuesArray);
+ UriData uriData = checkPermissionsAndCreateUriData(uri, valuesArray);
+ return getTableDelegate(uriData).bulkInsert(uriData, valuesArray);
}
@Override
public Uri insert(Uri uri, ContentValues values) {
- UriData uriData = checkPermissionsAndCreateUriData(uri);
- return mVoicemailContentTable.insert(uriData, values);
+ UriData uriData = checkPermissionsAndCreateUriData(uri, values);
+ return getTableDelegate(uriData).insert(uriData, values);
}
@Override
@@ -100,16 +108,16 @@ public class VoicemailContentProvider extends ContentProvider
UriData uriData = checkPermissionsAndCreateUriData(uri);
SelectionBuilder selectionBuilder = new SelectionBuilder(selection);
selectionBuilder.addClause(getPackageRestrictionClause());
- return mVoicemailContentTable.query(uriData, projection, selectionBuilder.build(),
+ return getTableDelegate(uriData).query(uriData, projection, selectionBuilder.build(),
selectionArgs, sortOrder);
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- UriData uriData = checkPermissionsAndCreateUriData(uri);
+ UriData uriData = checkPermissionsAndCreateUriData(uri, values);
SelectionBuilder selectionBuilder = new SelectionBuilder(selection);
selectionBuilder.addClause(getPackageRestrictionClause());
- return mVoicemailContentTable.update(uriData, values, selectionBuilder.build(),
+ return getTableDelegate(uriData).update(uriData, values, selectionBuilder.build(),
selectionArgs);
}
@@ -118,14 +126,30 @@ public class VoicemailContentProvider extends ContentProvider
UriData uriData = checkPermissionsAndCreateUriData(uri);
SelectionBuilder selectionBuilder = new SelectionBuilder(selection);
selectionBuilder.addClause(getPackageRestrictionClause());
- return mVoicemailContentTable.delete(uriData, selectionBuilder.build(), selectionArgs);
+ return getTableDelegate(uriData).delete(uriData, selectionBuilder.build(), selectionArgs);
}
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
UriData uriData = checkPermissionsAndCreateUriData(uri);
// openFileHelper() relies on "_data" column to be populated with the file path.
- return mVoicemailContentTable.openFile(uriData, mode, openFileHelper(uri, mode));
+ return getTableDelegate(uriData).openFile(uriData, mode);
+ }
+
+ /** Returns the correct table delegate object that can handle this URI. */
+ private VoicemailTable.Delegate getTableDelegate(UriData uriData) {
+ switch (uriData.getUriType()) {
+ case STATUS:
+ case STATUS_ID:
+ return mVoicemailStatusTable;
+ case VOICEMAILS:
+ case VOICEMAILS_ID:
+ return mVoicemailContentTable;
+ case NO_MATCH:
+ throw new IllegalStateException("Invalid uri type for uri: " + uriData.getUri());
+ default:
+ throw new IllegalStateException("Impossible, all cases are covered.");
+ }
}
/**
@@ -135,8 +159,10 @@ public class VoicemailContentProvider extends ContentProvider
private final Uri mUri;
private final String mId;
private final String mSourcePackage;
+ private final VoicemailUriType mUriType;
- public UriData(Uri uri, String id, String sourcePackage) {
+ public UriData(Uri uri, VoicemailUriType uriType, String id, String sourcePackage) {
+ mUriType = uriType;
mUri = uri;
mId = id;
mSourcePackage = sourcePackage;
@@ -167,22 +193,43 @@ public class VoicemailContentProvider extends ContentProvider
return mSourcePackage;
}
+ /** Gets the Voicemail URI type. */
+ public final VoicemailUriType getUriType() {
+ return mUriType;
+ }
+
+ /** Builds a where clause from the URI data. */
+ public final String getWhereClause() {
+ return concatenateClauses(
+ (hasId() ? getEqualityClause(BaseColumns._ID, getId()) : null),
+ (hasSourcePackage() ? getEqualityClause(SOURCE_PACKAGE_FIELD,
+ getSourcePackage()) : null));
+ }
+
/** Create a {@link UriData} corresponding to a given uri. */
public static UriData createUriData(Uri uri) {
String sourcePackage = uri.getQueryParameter(
VoicemailContract.PARAM_KEY_SOURCE_PACKAGE);
List<String> segments = uri.getPathSegments();
- switch (createUriMatcher().match(uri)) {
+ VoicemailUriType uriType = createUriMatcher().match(uri);
+ switch (uriType) {
case VOICEMAILS:
- return new UriData(uri, null, sourcePackage);
+ case STATUS:
+ return new UriData(uri, uriType, null, sourcePackage);
case VOICEMAILS_ID:
- return new UriData(uri, segments.get(1), sourcePackage);
+ case STATUS_ID:
+ return new UriData(uri, uriType, segments.get(1), sourcePackage);
case NO_MATCH:
throw new IllegalArgumentException("Invalid URI: " + uri);
default:
throw new IllegalStateException("Impossible, all cases are covered");
}
}
+
+ private static TypedUriMatcherImpl<VoicemailUriType> createUriMatcher() {
+ return new TypedUriMatcherImpl<VoicemailUriType>(
+ VoicemailContract.AUTHORITY, VoicemailUriType.values());
+ }
}
@Override
@@ -214,21 +261,10 @@ public class VoicemailContentProvider extends ContentProvider
// 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(VoicemailContract.SOURCE_PACKAGE_FIELD)) {
+ if (!values.containsKey(SOURCE_PACKAGE_FIELD)) {
String provider = uriData.hasSourcePackage() ?
uriData.getSourcePackage() : getCallingPackage();
- values.put(VoicemailContract.SOURCE_PACKAGE_FIELD, provider);
- }
- // If you put a provider in the URI and in the values, they must match.
- if (uriData.hasSourcePackage() &&
- values.containsKey(VoicemailContract.SOURCE_PACKAGE_FIELD)) {
- if (!uriData.getSourcePackage().equals(
- values.get(VoicemailContract.SOURCE_PACKAGE_FIELD))) {
- throw new SecurityException(
- "Provider in URI was " + uriData.getSourcePackage() +
- " but doesn't match provider in ContentValues which was "
- + values.get(VoicemailContract.SOURCE_PACKAGE_FIELD));
- }
+ values.put(SOURCE_PACKAGE_FIELD, provider);
}
// You must have access to the provider given in values.
if (!mVoicemailPermissions.callerHasFullAccess()) {
@@ -238,9 +274,26 @@ public class VoicemailContentProvider extends ContentProvider
}
}
- private static TypedUriMatcherImpl<VoicemailUriType> createUriMatcher() {
- return new TypedUriMatcherImpl<VoicemailUriType>(
- VoicemailContract.AUTHORITY, VoicemailUriType.values());
+ /**
+ * Checks that the source_package field is same in uriData and ContentValues, if it happens
+ * to be set in both.
+ */
+ private void checkSourcePackageSameIfSet(UriData uriData, ContentValues values) {
+ if (uriData.hasSourcePackage() && values.containsKey(SOURCE_PACKAGE_FIELD)) {
+ if (!uriData.getSourcePackage().equals(values.get(SOURCE_PACKAGE_FIELD))) {
+ throw new SecurityException(
+ "source_package in URI was " + uriData.getSourcePackage() +
+ " but doesn't match source_package in ContentValues which was "
+ + values.get(SOURCE_PACKAGE_FIELD));
+ }
+ }
+ }
+
+ @Override
+ /** Implementation of {@link VoicemailTable.DelegateHelper#openDataFile(UriData, String)} */
+ public ParcelFileDescriptor openDataFile(UriData uriData, String mode)
+ throws FileNotFoundException {
+ return openFileHelper(uriData.getUri(), mode);
}
/**
@@ -255,15 +308,27 @@ public class VoicemailContentProvider extends ContentProvider
}
/**
- * Checks that the callingProvider is same as voicemailProvider. Throws {@link
+ * Same as {@link #checkPackagePermission(UriData)}. In addition does permission check
+ * on the ContentValues.
+ */
+ private UriData checkPermissionsAndCreateUriData(Uri uri, ContentValues... valuesArray) {
+ UriData uriData = checkPermissionsAndCreateUriData(uri);
+ for (ContentValues values : valuesArray) {
+ checkSourcePackageSameIfSet(uriData, values);
+ }
+ return uriData;
+ }
+
+ /**
+ * Checks that the callingPackage is same as voicemailSourcePackage. Throws {@link
* SecurityException} if they don't match.
*/
- private final void checkPackagesMatch(String callingProvider, String voicemailProvider,
+ private final void checkPackagesMatch(String callingPackage, String voicemailSourcePackage,
Uri uri) {
- if (!voicemailProvider.equals(callingProvider)) {
+ if (!voicemailSourcePackage.equals(callingPackage)) {
String errorMsg = String.format("Permission denied for URI: %s\n. " +
- "Provider %s cannot perform this operation for %s. Requires %s permission.",
- uri, callingProvider, voicemailProvider,
+ "Package %s cannot perform this operation for %s. Requires %s permission.",
+ uri, callingPackage, voicemailSourcePackage,
Manifest.permission.READ_WRITE_ALL_VOICEMAIL);
throw new SecurityException(errorMsg);
}
@@ -272,7 +337,7 @@ public class VoicemailContentProvider extends ContentProvider
/**
* Checks that either the caller has READ_WRITE_ALL_VOICEMAIL permission, or has the
* READ_WRITE_OWN_VOICEMAIL permission and is using a URI that matches
- * /voicemail/source/[source-package] where [source-package] is the same as the calling
+ * /voicemail/?source_package=[source-package] where [source-package] is the same as the calling
* package.
*
* @throws SecurityException if the check fails.
@@ -280,7 +345,7 @@ public class VoicemailContentProvider extends ContentProvider
private void checkPackagePermission(UriData uriData) {
if (!mVoicemailPermissions.callerHasFullAccess()) {
if (!uriData.hasSourcePackage()) {
- // You cannot have a match if this is not a provider uri.
+ // You cannot have a match if this is not a provider URI.
throw new SecurityException(String.format(
"Provider %s does not have %s permission." +
"\nPlease set query parameter '%s' in the URI.\nURI: %s",
diff --git a/src/com/android/providers/contacts/VoicemailContentTable.java b/src/com/android/providers/contacts/VoicemailContentTable.java
index 8f6f3bf..0712a65 100644
--- a/src/com/android/providers/contacts/VoicemailContentTable.java
+++ b/src/com/android/providers/contacts/VoicemailContentTable.java
@@ -38,6 +38,7 @@ import android.provider.VoicemailContract.Voicemails;
import android.util.Log;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
/**
@@ -152,14 +153,13 @@ public class VoicemailContentTable implements VoicemailTable.Delegate {
// Directly update the db because we cannot update voicemail_uri through external
// update() due to projectionMap check. This also avoids unnecessary permission
// checks that are already done as part of insert request.
- db.update(mTableName, values, getWhereClause(
- UriData.createUriData(newUri)), null);
+ db.update(mTableName, values, UriData.createUriData(newUri).getWhereClause(), null);
}
@Override
public int delete(UriData uriData, String selection, String[] selectionArgs) {
final SQLiteDatabase db = mDbHelper.getWritableDatabase();
- String combinedClause = concatenateClauses(selection, getWhereClause(uriData),
+ String combinedClause = concatenateClauses(selection, uriData.getWhereClause(),
getCallTypeClause());
// Delete all the files associated with this query. Once we've deleted the rows, there will
@@ -196,7 +196,7 @@ public class VoicemailContentTable implements VoicemailTable.Delegate {
qb.setProjectionMap(sVoicemailProjectionMap);
qb.setStrict(true);
- String combinedClause = concatenateClauses(selection, getWhereClause(uriData),
+ String combinedClause = concatenateClauses(selection, uriData.getWhereClause(),
getCallTypeClause());
SQLiteDatabase db = mDbHelper.getReadableDatabase();
Cursor c = qb.query(db, projection, combinedClause, selectionArgs, null, null, sortOrder);
@@ -214,7 +214,7 @@ public class VoicemailContentTable implements VoicemailTable.Delegate {
final SQLiteDatabase db = mDbHelper.getWritableDatabase();
// TODO: This implementation does not allow bulk update because it only accepts
// URI that include message Id. I think we do want to support bulk update.
- String combinedClause = concatenateClauses(selection, getWhereClause(uriData),
+ String combinedClause = concatenateClauses(selection, uriData.getWhereClause(),
getCallTypeClause());
int count = db.update(mTableName, values, combinedClause, selectionArgs);
if (count > 0) {
@@ -261,25 +261,16 @@ public class VoicemailContentTable implements VoicemailTable.Delegate {
}
@Override
- public ParcelFileDescriptor openFile(UriData uriData, String mode,
- ParcelFileDescriptor openFileHelper) {
+ public ParcelFileDescriptor openFile(UriData uriData, String mode)
+ throws FileNotFoundException {
+ ParcelFileDescriptor fileDescriptor = mDelegateHelper.openDataFile(uriData, mode);
// If the open succeeded, then update the has_content bit in the table.
if (mode.contains("w")) {
ContentValues contentValues = new ContentValues();
contentValues.put(Voicemails.HAS_CONTENT, 1);
update(uriData, contentValues, null, null);
}
- return openFileHelper;
- }
-
- private String getWhereClause(UriData uriData) {
- return concatenateClauses(
- (uriData.hasId() ?
- getEqualityClause(Voicemails._ID, uriData.getId())
- : null),
- (uriData.hasSourcePackage() ?
- getEqualityClause(Voicemails.SOURCE_PACKAGE, uriData.getSourcePackage())
- : null));
+ return fileDescriptor;
}
/** Creates a clause to restrict the selection to only voicemail call type.*/
diff --git a/src/com/android/providers/contacts/VoicemailStatusTable.java b/src/com/android/providers/contacts/VoicemailStatusTable.java
new file mode 100644
index 0000000..1f1fa8b
--- /dev/null
+++ b/src/com/android/providers/contacts/VoicemailStatusTable.java
@@ -0,0 +1,135 @@
+/*
+ * 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 com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
+
+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;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.provider.VoicemailContract.Status;
+
+/**
+ * Implementation of {@link VoicemailTable.Delegate} for the voicemail status table.
+ */
+public class VoicemailStatusTable implements VoicemailTable.Delegate {
+ private static final ProjectionMap sStatusProjectionMap = new ProjectionMap.Builder()
+ .add(Status._ID)
+ .add(Status.CONFIGURATION_STATE)
+ .add(Status.DATA_CHANNEL_STATE)
+ .add(Status.NOTIFICATION_CHANNEL_STATE)
+ .add(Status.SETTINGS_URI)
+ .add(Status.SOURCE_PACKAGE)
+ .add(Status.VOICEMAIL_ACCESS_URI)
+ .build();
+
+ private final String mTableName;
+ private final Context mContext;
+ private final SQLiteOpenHelper mDbHelper;
+ private final VoicemailTable.DelegateHelper mDelegateHelper;
+
+ public VoicemailStatusTable(String tableName, Context context, SQLiteOpenHelper dbHelper,
+ VoicemailTable.DelegateHelper delegateHelper) {
+ mTableName = tableName;
+ mContext = context;
+ mDbHelper = dbHelper;
+ mDelegateHelper = delegateHelper;
+ }
+
+ @Override
+ public Uri insert(UriData uriData, ContentValues values) {
+ SQLiteDatabase db = mDbHelper.getWritableDatabase();
+ ContentValues copiedValues = new ContentValues(values);
+ mDelegateHelper.checkAndAddSourcePackageIntoValues(uriData, copiedValues);
+ long rowId = 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;
+ }
+ }
+
+ @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;
+ }
+
+ @Override
+ public Cursor query(UriData uriData, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+ qb.setTables(mTableName);
+ qb.setProjectionMap(sStatusProjectionMap);
+ qb.setStrict(true);
+
+ String combinedClause = concatenateClauses(selection, uriData.getWhereClause());
+ SQLiteDatabase db = mDbHelper.getReadableDatabase();
+ Cursor c = qb.query(db, projection, combinedClause, selectionArgs, null, null, sortOrder);
+ if (c != null) {
+ c.setNotificationUri(mContext.getContentResolver(), Status.CONTENT_URI);
+ }
+ return c;
+ }
+
+ @Override
+ public int update(UriData uriData, ContentValues values, String selection,
+ 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;
+ }
+
+ @Override
+ public String getType(UriData uriData) {
+ if (uriData.hasId()) {
+ return Status.ITEM_TYPE;
+ } else {
+ return Status.DIR_TYPE;
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(UriData uriData, String mode) {
+ throw new UnsupportedOperationException("File operation is not supported for status table");
+ }
+}
diff --git a/src/com/android/providers/contacts/VoicemailTable.java b/src/com/android/providers/contacts/VoicemailTable.java
index d068775..cab48fd 100644
--- a/src/com/android/providers/contacts/VoicemailTable.java
+++ b/src/com/android/providers/contacts/VoicemailTable.java
@@ -22,6 +22,8 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
+import java.io.FileNotFoundException;
+
/**
* Defines interfaces for communication between voicemail content provider and voicemail table
* implementations.
@@ -40,8 +42,8 @@ public interface VoicemailTable {
public int update(UriData uriData, ContentValues values, String selection,
String[] selectionArgs);
public String getType(UriData uriData);
- public ParcelFileDescriptor openFile(UriData uriData, String mode,
- ParcelFileDescriptor openFileHelper);
+ public ParcelFileDescriptor openFile(UriData uriData, String mode)
+ throws FileNotFoundException;
}
/**
@@ -63,5 +65,12 @@ public interface VoicemailTable {
* Inserts source_package field into ContentValues. Used in insert operations.
*/
public void checkAndAddSourcePackageIntoValues(UriData uriData, ContentValues values);
+
+ /**
+ * Opens the file pointed to by the column "_data".
+ * @throws FileNotFoundException
+ */
+ public ParcelFileDescriptor openDataFile(UriData uriData, String mode)
+ throws FileNotFoundException;
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/providers/contacts/VoicemailUriType.java b/src/com/android/providers/contacts/VoicemailUriType.java
index c3a33ab..eb1c3bd 100644
--- a/src/com/android/providers/contacts/VoicemailUriType.java
+++ b/src/com/android/providers/contacts/VoicemailUriType.java
@@ -23,7 +23,9 @@ import com.android.providers.contacts.util.UriType;
enum VoicemailUriType implements UriType {
NO_MATCH(null),
VOICEMAILS("voicemail"),
- VOICEMAILS_ID("voicemail/#");
+ VOICEMAILS_ID("voicemail/#"),
+ STATUS("status"),
+ STATUS_ID("status/#");
private final String path;