Merge "Add the enterprise caller-id API"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e335e40..58eab25 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3,14 +3,6 @@
android:sharedUserId="android.uid.shared"
android:sharedUserLabel="@string/sharedUserLabel">
- <permission
- android:name="com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL"
- android:label="@string/read_write_all_voicemail_label"
- android:description="@string/read_write_all_voicemail_description"
- android:permissionGroup="android.permission-group.PERSONAL_INFO"
- android:protectionLevel="system|signature"
- />
-
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
@@ -22,7 +14,8 @@
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.MANAGE_USERS" />
<uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
- <uses-permission android:name="com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL" />
+ <uses-permission android:name="com.android.voicemail.permission.READ_ALL_VOICEMAIL" />
+ <uses-permission android:name="com.android.voicemail.permission.MANAGE_VOICEMAIL" />
<application android:process="android.process.acore"
android:label="@string/app_label"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5291017..c326eee 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -44,14 +44,6 @@
<!-- The name of the invisible local contact directory -->
<string name="local_invisible_directory">Other</string>
- <!-- Title of an application permission, listed so the user can choose whether they want to
- allow the application to do this. [CHAR LIMIT=NONE] -->
- <string name="read_write_all_voicemail_label">Access all voicemails</string>
- <!-- Description of an application permission, listed so the user can choose whether
- they want to allow the application to do this. [CHAR LIMIT=NONE] -->
- <string name="read_write_all_voicemail_description">Allows the app to store and retrieve
- all voicemails that this device can access.</string>
-
<!-- The prefix string before the number used for the display name for the voicemail table.
Because of the way this is combined in SQL we can't allow a generic format string.
The resulting string will be this string with the number appended to the end.
diff --git a/src/com/android/providers/contacts/CallLogProvider.java b/src/com/android/providers/contacts/CallLogProvider.java
index 7295dc4..a4e642c 100644
--- a/src/com/android/providers/contacts/CallLogProvider.java
+++ b/src/com/android/providers/contacts/CallLogProvider.java
@@ -230,7 +230,7 @@
// permission and also requires the additional voicemail param set.
if (hasVoicemailValue(values)) {
checkIsAllowVoicemailRequest(uri);
- mVoicemailPermissions.checkCallerHasFullAccess();
+ mVoicemailPermissions.checkCallerHasManageAccess();
}
if (mCallsInserter == null) {
SQLiteDatabase db = mDbHelper.getWritableDatabase();
@@ -331,8 +331,10 @@
private void checkVoicemailPermissionAndAddRestriction(Uri uri,
SelectionBuilder selectionBuilder, boolean isQuery) {
if (isAllowVoicemailRequest(uri)) {
- if (!(isQuery && mVoicemailPermissions.callerHasFullReadAccess())) {
- mVoicemailPermissions.checkCallerHasFullAccess();
+ if (isQuery) {
+ mVoicemailPermissions.checkCallerHasFullReadAccess();
+ } else {
+ mVoicemailPermissions.checkCallerHasManageAccess();
}
} else {
selectionBuilder.addClause(EXCLUDE_VOICEMAIL_SELECTION);
diff --git a/src/com/android/providers/contacts/DbModifierWithNotification.java b/src/com/android/providers/contacts/DbModifierWithNotification.java
index fda8321..c25e171 100644
--- a/src/com/android/providers/contacts/DbModifierWithNotification.java
+++ b/src/com/android/providers/contacts/DbModifierWithNotification.java
@@ -18,7 +18,7 @@
package com.android.providers.contacts;
import static android.Manifest.permission.ADD_VOICEMAIL;
-import static com.android.providers.contacts.Manifest.permission.READ_WRITE_ALL_VOICEMAIL;
+import static android.Manifest.permission.READ_ALL_VOICEMAIL;
import android.content.ComponentName;
import android.content.ContentUris;
@@ -210,7 +210,8 @@
// Ignore any package that is not affected by the change and don't have full access
// either.
if (!modifiedPackages.contains(component.getPackageName()) &&
- !mVoicemailPermissions.packageHasFullAccess(component.getPackageName())) {
+ !mVoicemailPermissions.packageHasFullReadAccess(
+ component.getPackageName())) {
continue;
}
@@ -221,7 +222,7 @@
callingPackages.contains(component.getPackageName()));
}
String permissionNeeded = modifiedPackages.contains(component.getPackageName()) ?
- ADD_VOICEMAIL : READ_WRITE_ALL_VOICEMAIL;
+ ADD_VOICEMAIL : READ_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(),
diff --git a/src/com/android/providers/contacts/VoicemailContentProvider.java b/src/com/android/providers/contacts/VoicemailContentProvider.java
index 79e549b..ec5c6ad 100644
--- a/src/com/android/providers/contacts/VoicemailContentProvider.java
+++ b/src/com/android/providers/contacts/VoicemailContentProvider.java
@@ -99,14 +99,14 @@
@Override
public Uri insert(Uri uri, ContentValues values) {
- UriData uriData = checkPermissionsAndCreateUriData(uri, values);
+ UriData uriData = checkPermissionsAndCreateUriDataForWrite(uri, values);
return getTableDelegate(uriData).insert(uriData, values);
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
- UriData uriData = checkPermissionsAndCreateUriDataForReadOperation(uri);
+ UriData uriData = checkPermissionsAndCreateUriDataForRead(uri);
SelectionBuilder selectionBuilder = new SelectionBuilder(selection);
selectionBuilder.addClause(getPackageRestrictionClause(true/*isQuery*/));
return getTableDelegate(uriData).query(uriData, projection, selectionBuilder.build(),
@@ -115,7 +115,7 @@
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- UriData uriData = checkPermissionsAndCreateUriData(uri, values);
+ UriData uriData = checkPermissionsAndCreateUriDataForWrite(uri, values);
SelectionBuilder selectionBuilder = new SelectionBuilder(selection);
selectionBuilder.addClause(getPackageRestrictionClause(false/*isQuery*/));
return getTableDelegate(uriData).update(uriData, values, selectionBuilder.build(),
@@ -124,7 +124,7 @@
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
- UriData uriData = checkPermissionsAndCreateUriData(uri);
+ UriData uriData = checkPermissionsAndCreateUriDataForWrite(uri);
SelectionBuilder selectionBuilder = new SelectionBuilder(selection);
selectionBuilder.addClause(getPackageRestrictionClause(false/*isQuery*/));
return getTableDelegate(uriData).delete(uriData, selectionBuilder.build(), selectionArgs);
@@ -134,9 +134,9 @@
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
UriData uriData = null;
if (mode.equals("r")) {
- uriData = checkPermissionsAndCreateUriDataForReadOperation(uri);
+ uriData = checkPermissionsAndCreateUriDataForRead(uri);
} else {
- uriData = checkPermissionsAndCreateUriData(uri);
+ uriData = checkPermissionsAndCreateUriDataForWrite(uri);
}
// openFileHelper() relies on "_data" column to be populated with the file path.
return getTableDelegate(uriData).openFile(uriData, mode);
@@ -247,8 +247,9 @@
uriData.getSourcePackage() : getCallingPackage_();
values.put(SOURCE_PACKAGE_FIELD, provider);
}
+
// You must have access to the provider given in values.
- if (!mVoicemailPermissions.callerHasFullAccess()) {
+ if (!mVoicemailPermissions.callerHasManageAccess()) {
checkPackagesMatch(getCallingPackage_(),
values.getAsString(VoicemailContract.SOURCE_PACKAGE_FIELD),
uriData.getUri());
@@ -278,10 +279,10 @@
}
/**
- * Performs necessary voicemail permission checks common to all operations and returns
- * the structured representation, {@link UriData}, of the supplied uri.
+ * Ensures that the caller has the permissions to perform a query/read operation, and
+ * then returns the structured representation {@link UriData} of the supplied uri.
*/
- private UriData checkPermissionsAndCreateUriDataForReadOperation(Uri uri) {
+ private UriData checkPermissionsAndCreateUriDataForRead(Uri uri) {
// If the caller has been explicitly granted read permission to this URI then no need to
// check further.
if (context().checkCallingUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
@@ -293,26 +294,29 @@
return UriData.createUriData(uri);
}
- return checkPermissionsAndCreateUriData(uri);
+ return checkPermissionsAndCreateUriData(uri, true);
}
/**
* Performs necessary voicemail permission checks common to all operations and returns
* the structured representation, {@link UriData}, of the supplied uri.
*/
- private UriData checkPermissionsAndCreateUriData(Uri uri) {
- mVoicemailPermissions.checkCallerHasOwnVoicemailAccess();
+ private UriData checkPermissionsAndCreateUriData(Uri uri, boolean read) {
UriData uriData = UriData.createUriData(uri);
- checkPackagePermission(uriData);
+ if (!hasReadWritePermission(read)) {
+ mVoicemailPermissions.checkCallerHasOwnVoicemailAccess();
+ checkPackagePermission(uriData);
+ }
return uriData;
}
/**
- * Same as {@link #checkPackagePermission(UriData)}. In addition does permission check
- * on the ContentValues.
+ * Ensures that the caller has the permissions to perform an update/delete operation, and
+ * then returns the structured representation {@link UriData} of the supplied uri.
+ * Also does a permission check on the ContentValues.
*/
- private UriData checkPermissionsAndCreateUriData(Uri uri, ContentValues... valuesArray) {
- UriData uriData = checkPermissionsAndCreateUriData(uri);
+ private UriData checkPermissionsAndCreateUriDataForWrite(Uri uri, ContentValues... valuesArray) {
+ UriData uriData = checkPermissionsAndCreateUriData(uri, false);
for (ContentValues values : valuesArray) {
checkSourcePackageSameIfSet(uriData, values);
}
@@ -329,13 +333,13 @@
String errorMsg = String.format("Permission denied for URI: %s\n. " +
"Package %s cannot perform this operation for %s. Requires %s permission.",
uri, callingPackage, voicemailSourcePackage,
- Manifest.permission.READ_WRITE_ALL_VOICEMAIL);
+ android.Manifest.permission.MANAGE_VOICEMAIL);
throw new SecurityException(errorMsg);
}
}
/**
- * Checks that either the caller has READ_WRITE_ALL_VOICEMAIL permission,
+ * Checks that either the caller has the MANAGE_VOICEMAIL permission,
* or has the ADD_VOICEMAIL permission and is using a URI that matches
* /voicemail/?source_package=[source-package] where [source-package] is the same as the calling
* package.
@@ -343,13 +347,13 @@
* @throws SecurityException if the check fails.
*/
private void checkPackagePermission(UriData uriData) {
- if (!mVoicemailPermissions.callerHasFullAccess()) {
+ if (!mVoicemailPermissions.callerHasManageAccess()) {
if (!uriData.hasSourcePackage()) {
// 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",
- getCallingPackage_(), Manifest.permission.READ_WRITE_ALL_VOICEMAIL,
+ getCallingPackage_(), android.Manifest.permission.MANAGE_VOICEMAIL,
VoicemailContract.PARAM_KEY_SOURCE_PACKAGE, uriData.getUri()));
}
checkPackagesMatch(getCallingPackage_(), uriData.getSourcePackage(), uriData.getUri());
@@ -381,7 +385,7 @@
// which one we return.
String bestSoFar = callerPackages[0];
for (String callerPackage : callerPackages) {
- if (mVoicemailPermissions.packageHasFullAccess(callerPackage)) {
+ if (mVoicemailPermissions.packageHasManageAccess(callerPackage)) {
// Full always wins, we can return early.
return callerPackage;
}
@@ -397,12 +401,21 @@
* access to all data.
*/
private String getPackageRestrictionClause(boolean isQuery) {
- if (isQuery && mVoicemailPermissions.callerHasFullReadAccess()) {
- return null;
- }
- if (mVoicemailPermissions.callerHasFullAccess()) {
+ if (hasReadWritePermission(isQuery)) {
return null;
}
return getEqualityClause(Voicemails.SOURCE_PACKAGE, getCallingPackage_());
}
+
+ /**
+ * Whether or not the calling package has the appropriate read/write permission
+ *
+ * @param read Whether or not this operation is a read
+ *
+ * @return True if the package has the permission required to perform the read/write operation
+ */
+ private boolean hasReadWritePermission(boolean read) {
+ return read ? mVoicemailPermissions.callerHasFullReadAccess() :
+ mVoicemailPermissions.callerHasManageAccess();
+ }
}
diff --git a/src/com/android/providers/contacts/VoicemailPermissions.java b/src/com/android/providers/contacts/VoicemailPermissions.java
index 570399c..5a26443 100644
--- a/src/com/android/providers/contacts/VoicemailPermissions.java
+++ b/src/com/android/providers/contacts/VoicemailPermissions.java
@@ -36,16 +36,15 @@
return callerHasPermission(android.Manifest.permission.ADD_VOICEMAIL);
}
-
/** Determine if the calling process has full read access to all voicemails. */
public boolean callerHasFullReadAccess() {
return callerHasPermission(android.Manifest.permission.READ_ALL_VOICEMAIL);
}
- /** Determines if the calling process has access to all voicemails. */
- public boolean callerHasFullAccess() {
- return callerHasOwnVoicemailAccess() &&
- callerHasPermission(Manifest.permission.READ_WRITE_ALL_VOICEMAIL);
+ /** Determine if the calling process has the permission required to update and remove all
+ * voicemails */
+ public boolean callerHasManageAccess() {
+ return callerHasPermission(android.Manifest.permission.MANAGE_VOICEMAIL);
}
/**
@@ -72,16 +71,10 @@
}
}
- /**
- * Checks that the caller has permissions to access ALL voicemails.
- *
- * @throws SecurityException if the caller does not have the voicemail source permission.
- */
- public void checkCallerHasFullAccess() {
- if (!callerHasFullAccess()) {
- throw new SecurityException(String.format("The caller must have permissions %s AND %s",
- android.Manifest.permission.ADD_VOICEMAIL,
- Manifest.permission.READ_WRITE_ALL_VOICEMAIL));
+ public void checkCallerHasManageAccess() {
+ if (!callerHasManageAccess()) {
+ throw new SecurityException(String.format("The caller must have %s permission: ",
+ android.Manifest.permission.MANAGE_VOICEMAIL));
}
}
@@ -96,25 +89,19 @@
return packageHasPermission(packageName, android.Manifest.permission.READ_ALL_VOICEMAIL);
}
- /** Determines if the given package has full access. */
- public boolean packageHasFullAccess(String packageName) {
- return packageHasOwnVoicemailAccess(packageName) &&
- packageHasPermission(packageName, Manifest.permission.READ_WRITE_ALL_VOICEMAIL);
+ /** Determines if the given package has manage access. */
+ public boolean packageHasManageAccess(String packageName) {
+ return packageHasPermission(packageName, android.Manifest.permission.MANAGE_VOICEMAIL);
}
/** Determines if the given package has the given permission. */
private boolean packageHasPermission(String packageName, String permission) {
return mContext.getPackageManager().checkPermission(permission, packageName)
- == PackageManager.PERMISSION_GRANTED;
+ == PackageManager.PERMISSION_GRANTED;
}
/** Determines if the calling process has the given permission. */
private boolean callerHasPermission(String permission) {
- // We need to check against both the calling or self permission in order for the Contacts
- // app to be allowed access.
- // The reason is that the Contacts app shares its process with the ContactsProvider and
- // therefore its requests are not considered to be IPCs, since they are coming from the same
- // process, even if, technically, from a different package.
return mContext.checkCallingOrSelfPermission(permission)
== PackageManager.PERMISSION_GRANTED;
}
diff --git a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
index 512455b..45af26c 100644
--- a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
@@ -79,6 +79,19 @@
*/
public abstract class BaseContactsProvider2Test extends PhotoLoadingTestCase {
+ static final String ADD_VOICEMAIL_PERMISSION =
+ "com.android.voicemail.permission.ADD_VOICEMAIL";
+ /*
+ * Permission to allow querying voicemails
+ */
+ static final String READ_ALL_VOICEMAIL_PERMISSION =
+ "com.android.voicemail.permission.READ_ALL_VOICEMAIL";
+ /*
+ * Permission to allow deleting and updating voicemails
+ */
+ static final String MANAGE_VOICEMAIL_PERMISSION =
+ "com.android.voicemail.permission.MANAGE_VOICEMAIL";
+
protected static final String PACKAGE = "ContactsProvider2Test";
public static final String READ_ONLY_ACCOUNT_TYPE =
SynchronousContactsProvider2.READ_ONLY_ACCOUNT_TYPE;
diff --git a/tests/src/com/android/providers/contacts/BaseVoicemailProviderTest.java b/tests/src/com/android/providers/contacts/BaseVoicemailProviderTest.java
index 5f02e3f..9373dc0 100644
--- a/tests/src/com/android/providers/contacts/BaseVoicemailProviderTest.java
+++ b/tests/src/com/android/providers/contacts/BaseVoicemailProviderTest.java
@@ -34,10 +34,6 @@
* Base class for all tests that require interacting with the voicemail content provider.
*/
public class BaseVoicemailProviderTest extends BaseContactsProvider2Test {
- private static final String READ_WRITE_ALL_PERMISSION =
- "com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL";
- private static final String ADD_VOICEMAIL_PERMISSION =
- "com.android.voicemail.permission.ADD_VOICEMAIL";
protected boolean mUseSourceUri = false;
private File mTestDirectory;
@@ -66,21 +62,23 @@
}
protected void setUpForOwnPermission() {
- // Give away full permission, in case it was granted previously.
- mActor.removePermissions(READ_WRITE_ALL_PERMISSION);
+ mActor.removePermissions(READ_ALL_VOICEMAIL_PERMISSION);
+ mActor.removePermissions(MANAGE_VOICEMAIL_PERMISSION);
mActor.addPermissions(ADD_VOICEMAIL_PERMISSION);
mUseSourceUri = true;
}
protected void setUpForFullPermission() {
mActor.addPermissions(ADD_VOICEMAIL_PERMISSION);
- mActor.addPermissions(READ_WRITE_ALL_PERMISSION);
+ mActor.addPermissions(READ_ALL_VOICEMAIL_PERMISSION);
+ mActor.addPermissions(MANAGE_VOICEMAIL_PERMISSION);
mUseSourceUri = false;
}
protected void setUpForNoPermission() {
mActor.removePermissions(ADD_VOICEMAIL_PERMISSION);
- mActor.removePermissions(READ_WRITE_ALL_PERMISSION);
+ mActor.removePermissions(READ_ALL_VOICEMAIL_PERMISSION);
+ mActor.removePermissions(MANAGE_VOICEMAIL_PERMISSION);
mUseSourceUri = true;
}
diff --git a/tests/src/com/android/providers/contacts/CallLogProviderTest.java b/tests/src/com/android/providers/contacts/CallLogProviderTest.java
index f0540ee..6a9410f 100644
--- a/tests/src/com/android/providers/contacts/CallLogProviderTest.java
+++ b/tests/src/com/android/providers/contacts/CallLogProviderTest.java
@@ -51,11 +51,6 @@
*/
@MediumTest
public class CallLogProviderTest extends BaseContactsProvider2Test {
- private static final String READ_WRITE_ALL_PERMISSION =
- "com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL";
- private static final String ADD_VOICEMAIL_PERMISSION =
- "com.android.voicemail.permission.ADD_VOICEMAIL";
-
/** Fields specific to voicemail provider that should not be exposed by call_log*/
private static final String[] VOICEMAIL_PROVIDER_SPECIFIC_COLUMNS = new String[] {
Voicemails._DATA,
@@ -100,12 +95,8 @@
private void setUpWithVoicemailPermissions() {
mActor.addPermissions(ADD_VOICEMAIL_PERMISSION);
- mActor.addPermissions(READ_WRITE_ALL_PERMISSION);
- }
-
- private void setUpWithNoVoicemailPermissions() {
- mActor.removePermissions(ADD_VOICEMAIL_PERMISSION);
- mActor.removePermissions(READ_WRITE_ALL_PERMISSION);
+ mActor.addPermissions(READ_ALL_VOICEMAIL_PERMISSION);
+ mActor.addPermissions(MANAGE_VOICEMAIL_PERMISSION);
}
public void testInsert_VoicemailCallRecord() {
@@ -348,7 +339,13 @@
null, null);
}
});
- // Should now succeed with permissions granted.
+
+ // Should succeed with manage permission granted
+ mActor.addPermissions(MANAGE_VOICEMAIL_PERMISSION);
+ mResolver.update(Calls.CONTENT_URI_WITH_VOICEMAIL, getDefaultCallValues(), null, null);
+ mActor.removePermissions(MANAGE_VOICEMAIL_PERMISSION);
+
+ // Should also succeed with full permissions granted.
setUpWithVoicemailPermissions();
mResolver.update(Calls.CONTENT_URI_WITH_VOICEMAIL, getDefaultCallValues(), null, null);
}
@@ -360,7 +357,13 @@
mResolver.query(Calls.CONTENT_URI_WITH_VOICEMAIL, null, null, null, null);
}
});
- // Should now succeed with permissions granted.
+
+ // Should succeed with read_all permission granted
+ mActor.addPermissions(READ_ALL_VOICEMAIL_PERMISSION);
+ mResolver.query(Calls.CONTENT_URI_WITH_VOICEMAIL, null, null, null, null);
+ mActor.removePermissions(READ_ALL_VOICEMAIL_PERMISSION);
+
+ // Should also succeed with full permissions granted.
setUpWithVoicemailPermissions();
mResolver.query(Calls.CONTENT_URI_WITH_VOICEMAIL, null, null, null, null);
}
@@ -372,6 +375,12 @@
mResolver.delete(Calls.CONTENT_URI_WITH_VOICEMAIL, null, null);
}
});
+
+ // Should succeed with manage permission granted
+ mActor.addPermissions(MANAGE_VOICEMAIL_PERMISSION);
+ mResolver.delete(Calls.CONTENT_URI_WITH_VOICEMAIL, null, null);
+ mActor.removePermissions(MANAGE_VOICEMAIL_PERMISSION);
+
// Should now succeed with permissions granted.
setUpWithVoicemailPermissions();
mResolver.delete(Calls.CONTENT_URI_WITH_VOICEMAIL, null, null);
diff --git a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
index 8fdbccf..451d1ac 100644
--- a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
+++ b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
@@ -195,6 +195,20 @@
insertVoicemailForSourcePackage("another-package");
}
});
+
+ setUpForNoPermission();
+ mUseSourceUri = false;
+ // With the READ_ALL_VOICEMAIL permission, we should now be able to read all voicemails
+ mActor.addPermissions(READ_ALL_VOICEMAIL_PERMISSION);
+ assertEquals(2, getCount(voicemailUri(), null, null));
+
+ // An insert for another package should still fail
+ EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
+ @Override
+ public void run() {
+ insertVoicemailForSourcePackage("another-package");
+ }
+ });
}
public void testPermissions_UpdateAndDelete() {
@@ -224,6 +238,25 @@
mResolver.delete(anotherVoicemail, null, null);
}
});
+
+ // If we have the manage voicemail permission, we should be able to both update and delete
+ // voicemails from all packages
+ setUpForNoPermission();
+ mActor.addPermissions(MANAGE_VOICEMAIL_PERMISSION);
+ mResolver.update(anotherVoicemail, getTestVoicemailValues(), null, null);
+
+ // Now add the read voicemail permission temporarily to verify that the update actually
+ // worked
+ mActor.addPermissions(READ_ALL_VOICEMAIL_PERMISSION);
+ assertStoredValues(anotherVoicemail, getTestVoicemailValues());
+ mActor.removePermissions(READ_ALL_VOICEMAIL_PERMISSION);
+
+ mResolver.delete(anotherVoicemail, null, null);
+
+ // Now add the read voicemail permission temporarily to verify that the delete actually
+ // worked
+ mActor.addPermissions(READ_ALL_VOICEMAIL_PERMISSION);
+ assertEquals(0, getCount(anotherVoicemail, null, null));
}
private Uri withSourcePackageParam(Uri uri) {
@@ -250,6 +283,35 @@
mActor.removeUriPermissions(uri1);
}
+ /*
+ * Checks that the READ_ALL_VOICEMAIL permission provides read access to a uri.
+ */
+ public void testUriPermissions_ReadAccess() {
+ setUpForFullPermission();
+ final Uri uri1 = insertVoicemail();
+ // Give away all permissions before querying. Access should be denied.
+ setUpForNoPermission();
+ mUseSourceUri = false;
+ checkHasNoAccessToUri(uri1);
+
+ mActor.addPermissions(READ_ALL_VOICEMAIL_PERMISSION);
+ checkHasReadAccessToUri(uri1);
+ }
+
+ /*
+ * Checks that the MANAGE_VOICEMAIL permission provides write access to a uri.
+ */
+ public void testUriPermissions_WriteAccess() {
+ setUpForFullPermission();
+ final Uri uri1 = insertVoicemail();
+ // Give away all permissions before querying. Access should be denied.
+ setUpForNoPermission();
+ checkHasNoAccessToUri(uri1);
+
+ mActor.addPermissions(MANAGE_VOICEMAIL_PERMISSION);
+ checkHasUpdateAndDeleteAccessToUri(uri1);
+ }
+
private void checkHasNoAccessToUri(final Uri uri) {
checkHasNoReadAccessToUri(uri);
checkHasNoWriteAccessToUri(uri);
@@ -298,6 +360,11 @@
});
}
+ private void checkHasUpdateAndDeleteAccessToUri(final Uri uri) {
+ mResolver.update(uri, getTestVoicemailValues(), null, null);
+ mResolver.delete(uri, null, null);
+ }
+
private void checkHasNoWriteAccessToUri(final Uri uri) {
EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
@Override