Merge "Centralize EnterprisePolicyGuard checking code in CP2." into nyc-dev
am: 6a4e192300
* commit '6a4e1923005b12e8375c24775f8089a94a08a2e6':
Centralize EnterprisePolicyGuard checking code in CP2.
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index f05aef2..aa58bae 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -5434,6 +5434,14 @@
}
waitForAccess(mReadAccessLatch);
+ if (!isDirectoryParamValid(uri)) {
+ return null;
+ }
+
+ // Check enterprise policy if caller does not come from same profile
+ if (!(isCallerFromSameUser() || mEnterprisePolicyGuard.isCrossProfileAllowed(uri))) {
+ return createEmptyCursor(uri, projection);
+ }
// Query the profile DB if appropriate.
if (mapsToProfileDb(uri)) {
switchToProfileMode();
@@ -5449,31 +5457,19 @@
cancellationSignal);
}
+ private boolean isCallerFromSameUser() {
+ return Binder.getCallingUserHandle().getIdentifier() == UserUtils
+ .getCurrentUserHandle(getContext());
+ }
+
private Cursor queryDirectoryIfNecessary(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) {
String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY);
-
final long directoryId =
(directory == null ? -1 :
(directory.equals("0") ? Directory.DEFAULT :
(directory.equals("1") ? Directory.LOCAL_INVISIBLE : Long.MIN_VALUE)));
- final boolean isEnterpriseUri = isEnterpriseUriWithDirectorySupport(uri);
-
- /*
- * *** Enterprise Uri ONLY ***
- * Handler for enterprise uri should handle the case that directory is null themselves.
- * The below code ONLY guards the case that directory is enterprise directory.
- * (personal directory should not be guarded by dpm policy.)
- */
- if (directoryId == Long.MIN_VALUE && isEnterpriseUri) {
- final boolean isCorpDirectory =
- Directory.isEnterpriseDirectoryId(Long.parseLong(directory));
-
- if (isCorpDirectory && !mEnterprisePolicyGuard.isCrossProfileAllowed(uri)) {
- return createEmptyCursor(uri, projection);
- }
- }
-
+ final boolean isEnterpriseUri = mEnterprisePolicyGuard.isValidEnterpriseUri(uri);
if (isEnterpriseUri || directoryId > Long.MIN_VALUE) {
final Cursor cursor = queryLocal(uri, projection, selection, selectionArgs, sortOrder,
directoryId, cancellationSignal);
@@ -5484,6 +5480,22 @@
directory, cancellationSignal);
}
+ @VisibleForTesting
+ protected static boolean isDirectoryParamValid(Uri uri) {
+ final String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY);
+ if (directory == null) {
+ return true;
+ }
+ try {
+ Long.parseLong(directory);
+ return true;
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Invalid directory ID: " + directory);
+ // Return null cursor when invalid directory id is provided
+ return false;
+ }
+ }
+
private static Cursor createEmptyCursor(final Uri uri, String[] projection) {
projection = projection == null ? getDefaultProjection(uri) : projection;
if (projection == null) {
@@ -5546,6 +5558,27 @@
}
}
+ /**
+ * A helper function to query work CP2. It returns null when work profile is not availabe.
+ */
+ @VisibleForTesting
+ protected Cursor queryCorpContactsProvider(Uri localUri, String[] projection,
+ String selection, String[] selectionArgs, String sortOrder,
+ CancellationSignal cancellationSignal) {
+ final int corpUserId = UserUtils.getCorpUserId(getContext());
+ if (corpUserId < 0) {
+ return null;
+ }
+ // Make sure authority is CP2 not other providers
+ if (!ContactsContract.AUTHORITY.equals(localUri.getAuthority())) {
+ Log.w(TAG, "Invalid authority: " + localUri.getAuthority());
+ return null;
+ }
+ final Uri remoteUri = maybeAddUserId(localUri, corpUserId);
+ return getContext().getContentResolver().query(remoteUri, projection, selection,
+ selectionArgs, sortOrder, cancellationSignal);
+ }
+
private Cursor addSnippetExtrasToCursor(Uri uri, Cursor cursor) {
// If the cursor doesn't contain a snippet column, don't bother wrapping it.
@@ -5841,7 +5874,7 @@
return new MatrixCursor(outputProjection);
}
final Cursor cursor = queryCorpContacts(localUri, projection, selection,
- selectionArgs, sortOrder, Contacts._ID, dirId);
+ selectionArgs, sortOrder, Contacts._ID, dirId, cancellationSignal);
return (cursor != null) ? cursor : new MatrixCursor(outputProjection);
} else {
return queryDirectoryIfNecessary(localUri, projection, selection, selectionArgs,
@@ -6159,7 +6192,8 @@
case PHONES_ENTERPRISE: {
ContactsPermissions.enforceCallingOrSelfPermission(getContext(),
INTERACT_ACROSS_USERS);
- return queryMergedDataPhones(uri, projection, selection, selectionArgs, sortOrder);
+ return queryMergedDataPhones(uri, projection, selection, selectionArgs, sortOrder,
+ cancellationSignal);
}
case PHONES:
case CALLABLES: {
@@ -6903,19 +6937,15 @@
case RAW_CONTACT_ENTITIES_CORP: {
ContactsPermissions.enforceCallingOrSelfPermission(getContext(),
INTERACT_ACROSS_USERS);
- final int corpUserId = UserUtils.getCorpUserId(getContext());
- if (corpUserId < 0) {
- // No Corp user or policy not allowed, return empty cursor
+ final Cursor cursor = queryCorpContactsProvider(
+ RawContactsEntity.CONTENT_URI, projection, selection, selectionArgs,
+ sortOrder, cancellationSignal);
+ if (cursor == null) {
final String[] outputProjection = (projection != null) ? projection
: sRawEntityProjectionMap.getColumnNames();
return new MatrixCursor(outputProjection);
}
- final Uri remoteUri = maybeAddUserId(RawContactsEntity.CONTENT_URI, corpUserId);
- // This method is used by Bluetooth Contacts Sharing only, it uses enterprise
- // contact id to get work contacts info, so work profile should be available at this
- // moment.
- return getContext().getContentResolver().query(remoteUri, projection, selection,
- selectionArgs, sortOrder);
+ return cursor;
}
case RAW_CONTACT_ID_ENTITY: {
@@ -6958,28 +6988,17 @@
case DIRECTORIES_ENTERPRISE: {
return queryMergedDirectories(uri, projection, selection, selectionArgs,
- sortOrder);
+ sortOrder, cancellationSignal);
}
case DIRECTORIES_ID_ENTERPRISE: {
// This method will return either primary directory or enterprise directory
final long inputDirectoryId = ContentUris.parseId(uri);
if (Directory.isEnterpriseDirectoryId(inputDirectoryId)) {
- final int corpUserId = UserUtils.getCorpUserId(getContext());
- final boolean isCrossProfileAllowed =
- mEnterprisePolicyGuard.isCrossProfileAllowed(uri);
- if (corpUserId < 0 || !isCrossProfileAllowed) {
- // No Corp user or policy not allowed, return empty cursor
- final String[] outputProjection = (projection != null) ? projection
- : sDirectoryProjectionMap.getColumnNames();
- return new MatrixCursor(outputProjection);
- }
- final Uri remoteUri = maybeAddUserId(
+ final Cursor cursor = queryCorpContactsProvider(
ContentUris.withAppendedId(Directory.CONTENT_URI,
- inputDirectoryId - Directory.ENTERPRISE_DIRECTORY_ID_BASE),
- corpUserId);
- final Cursor cursor = getContext().getContentResolver().query(remoteUri,
- projection, selection, selectionArgs, sortOrder);
+ inputDirectoryId - Directory.ENTERPRISE_DIRECTORY_ID_BASE),
+ projection, selection, selectionArgs, sortOrder, cancellationSignal);
if (cursor == null) {
// Work profile is not available yet
final String[] outputProjection = (projection != null) ? projection
@@ -7122,21 +7141,14 @@
* Handles {@link Directory#ENTERPRISE_CONTENT_URI}.
*/
private Cursor queryMergedDirectories(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
+ String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) {
final Uri localUri = Directory.CONTENT_URI;
final Cursor primaryCursor = queryLocal(localUri, projection, selection, selectionArgs,
- sortOrder, Directory.DEFAULT, null);
+ sortOrder, Directory.DEFAULT, cancellationSignal);
Cursor corpCursor = null;
try {
- final int corpUserId = UserUtils.getCorpUserId(getContext());
- final boolean isCrossProfileAllowed = mEnterprisePolicyGuard.isCrossProfileAllowed(uri);
- if (corpUserId < 0 || !isCrossProfileAllowed) {
- // No Corp user or policy not allowed
- return primaryCursor;
- }
- final Uri remoteUri = maybeAddUserId(localUri, corpUserId);
- corpCursor = getContext().getContentResolver().query(remoteUri,
- projection, selection, selectionArgs, sortOrder, null);
+ corpCursor = queryCorpContactsProvider(localUri, projection, selection,
+ selectionArgs, sortOrder, cancellationSignal);
if (corpCursor == null) {
// No corp results. Just return the local result.
return primaryCursor;
@@ -7162,7 +7174,7 @@
* Handles {@link Phone#ENTERPRISE_CONTENT_URI}.
*/
private Cursor queryMergedDataPhones(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
+ String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) {
final List<String> pathSegments = uri.getPathSegments();
final int pathSegmentsSize = pathSegments.size();
// Ignore the first 2 path segments: "/data_enterprise/phones"
@@ -7190,7 +7202,7 @@
}
final Cursor managedCursor = queryCorpContacts(localUri, projection, selection,
- selectionArgs, sortOrder, RawContacts.CONTACT_ID, null);
+ selectionArgs, sortOrder, RawContacts.CONTACT_ID, null, cancellationSignal);
if (managedCursor == null) {
// No corp results. Just return the local result.
return primaryCursor;
@@ -7231,26 +7243,11 @@
}
/**
- * Check if uri is an enterprise uri with directory param supported.
- *
- * @param uri Uri that we want to check.
- * @return True if it is an enterprise uri.
- */
- private boolean isEnterpriseUriWithDirectorySupport(final Uri uri) {
- return mEnterprisePolicyGuard.isEnterpriseUriWithDirectorySupport(uri);
- }
-
- /**
* Query corp CP2 directly.
*/
private Cursor queryCorpContacts(Uri localUri, String[] projection, String selection,
String[] selectionArgs, String sortOrder, String contactIdColumnName,
- @Nullable Long directoryId) {
- final int corpUserId = UserUtils.getCorpUserId(getContext());
- if (corpUserId < 0) {
- return null;
- }
- final Uri remoteUri = maybeAddUserId(localUri, corpUserId);
+ @Nullable Long directoryId, CancellationSignal cancellationSignal) {
// We need contactId in projection, if it doesn't have, we add it in projection as
// workProjection, and we restore the actual projection in
// EnterpriseContactsCursorWrapper
@@ -7259,8 +7256,8 @@
final boolean isContactIdAdded = (projection == null) ? false
: (workProjection.length != projection.length);
int columnIdIndex = getContactIdColumnIndex(workProjection, contactIdColumnName);
- final Cursor managedCursor = getContext().getContentResolver().query(remoteUri,
- workProjection, selection, selectionArgs, sortOrder);
+ final Cursor managedCursor = queryCorpContactsProvider(localUri, workProjection,
+ selection, selectionArgs, sortOrder, cancellationSignal);
if (managedCursor == null) {
return null;
}
@@ -7292,7 +7289,7 @@
*/
private Cursor queryCorpLookupIfNecessary(Uri localUri, String[] projection, String selection,
String[] selectionArgs, String sortOrder, String contactIdColumnName,
- boolean isCrossProfileAllowedByPolicy) {
+ CancellationSignal cancellationSignal) {
final String directory = getQueryParameter(localUri, ContactsContract.DIRECTORY_PARAM_KEY);
final long directoryId = (directory != null) ? Long.parseLong(directory)
@@ -7317,7 +7314,7 @@
MoreDatabaseUtils.dumpCursor(TAG, "local", local);
}
// If we found a result / no corp profile / policy disallowed, just return it as-is.
- if (local.getCount() > 0 || corpUserId < 0 || !isCrossProfileAllowedByPolicy) {
+ if (local.getCount() > 0 || corpUserId < 0) {
return local;
}
} catch (Throwable th) { // If something throws, close the cursor.
@@ -7330,7 +7327,7 @@
// DB.
try {
final Cursor rewrittenCorpCursor = queryCorpContacts(localUri, projection, selection,
- selectionArgs, sortOrder, contactIdColumnName, null);
+ selectionArgs, sortOrder, contactIdColumnName, null, cancellationSignal);
if (rewrittenCorpCursor != null) {
local.close();
return rewrittenCorpCursor;
@@ -7367,7 +7364,8 @@
ContactsContract.DIRECTORY_PARAM_KEY,
String.valueOf(directoryId - Directory.ENTERPRISE_DIRECTORY_ID_BASE));
final Cursor cursor = queryCorpContacts(builder.build(), projection, null, null,
- null, isSipAddress ? Data.CONTACT_ID : PhoneLookup._ID, directoryId);
+ null, isSipAddress ? Data.CONTACT_ID : PhoneLookup._ID, directoryId,
+ cancellationSignal);
if (cursor == null) {
final String[] outputProjection = (projection != null) ? projection
: sPhoneLookupProjectionMap.getColumnNames();
@@ -7384,8 +7382,7 @@
}
// No directory
return queryCorpLookupIfNecessary(builder.build(), projection, null, null, null,
- isSipAddress ? Data.CONTACT_ID : PhoneLookup._ID,
- mEnterprisePolicyGuard.isCrossProfileAllowed(uri));
+ isSipAddress ? Data.CONTACT_ID : PhoneLookup._ID, cancellationSignal);
}
private static final Set<String> MODIFIED_KEY_SET_FOR_ENTERPRISE_FILTER =
@@ -7417,7 +7414,7 @@
builder.appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
String.valueOf(directoryId - Directory.ENTERPRISE_DIRECTORY_ID_BASE));
final Cursor corpCursor = queryCorpContacts(builder.build(), projection, selection,
- selectionArgs, sortOrder, contactIdString, directoryId);
+ selectionArgs, sortOrder, contactIdString, directoryId, cancellationSignal);
if (corpCursor == null) {
// No Corp user or policy not allowed, return empty cursor
final String[] outputProjection = (projection != null) ? projection
@@ -7434,7 +7431,8 @@
}
}
- private static final Uri.Builder addQueryParametersFromUri(Uri.Builder builder, Uri uri,
+ @VisibleForTesting
+ protected static final Uri.Builder addQueryParametersFromUri(Uri.Builder builder, Uri uri,
Set<String> ignoredKeys) {
Set<String> keys = uri.getQueryParameterNames();
@@ -7467,7 +7465,7 @@
String.valueOf(directoryId - Directory.ENTERPRISE_DIRECTORY_ID_BASE));
final Cursor corpCursor =
queryCorpContacts(builder.build(), projection, selection, selectionArgs,
- sortOrder, Email.CONTACT_ID, directoryId);
+ sortOrder, Email.CONTACT_ID, directoryId, cancellationSignal);
if (corpCursor == null) {
final String[] outputProjection = (projection != null) ? projection
: sDataProjectionMap.getColumnNames();
@@ -7485,7 +7483,7 @@
}
// No directory
return queryCorpLookupIfNecessary(builder.build(), projection, selection, selectionArgs,
- sortOrder, Email.CONTACT_ID, mEnterprisePolicyGuard.isCrossProfileAllowed(uri));
+ sortOrder, Email.CONTACT_ID, cancellationSignal);
}
// TODO: Add test case for this
@@ -8633,6 +8631,14 @@
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
boolean success = false;
try {
+ if (!isDirectoryParamValid(uri)){
+ return null;
+ }
+ if (!isCallerFromSameUser() /* From differnt user */
+ && !mEnterprisePolicyGuard.isCrossProfileAllowed(uri)
+ /* Policy not allowed */){
+ return null;
+ }
waitForAccess(mode.equals("r") ? mReadAccessLatch : mWriteAccessLatch);
final AssetFileDescriptor ret;
if (mapsToProfileDb(uri)) {
@@ -8644,7 +8650,6 @@
}
success = true;
return ret;
-
} finally {
if (VERBOSE_LOGGING) {
Log.v(TAG, "openAssetFile uri=" + uri + " mode=" + mode + " success=" + success +
@@ -8927,8 +8932,7 @@
final Uri remoteUri;
if (Directory.isEnterpriseDirectoryId(directoryId)) {
final int corpUserId = UserUtils.getCorpUserId(getContext());
- final boolean isCrossProfileAllowed = mEnterprisePolicyGuard.isCrossProfileAllowed(uri);
- if (corpUserId < 0 || !isCrossProfileAllowed) {
+ if (corpUserId < 0) {
// No corp profile or the currrent profile is not the personal.
throw new FileNotFoundException(uri.toString());
}
@@ -8986,8 +8990,7 @@
"Photos retrieved by contact ID can only be read.");
}
final int corpUserId = UserUtils.getCorpUserId(getContext());
- final boolean isCrossProfileAllowed = mEnterprisePolicyGuard.isCrossProfileAllowed(uri);
- if (corpUserId < 0 || !isCrossProfileAllowed) {
+ if (corpUserId < 0) {
// No corp profile or the current profile is not the personal.
throw new FileNotFoundException(uri.toString());
}
diff --git a/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuard.java b/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuard.java
index 86e50cc..0e7907b 100644
--- a/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuard.java
+++ b/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuard.java
@@ -21,14 +21,19 @@
import android.content.Context;
import android.content.UriMatcher;
import android.net.Uri;
+import android.os.Binder;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.ContactsContract;
+import android.provider.ContactsContract.Directory;
import android.util.Log;
import com.android.providers.contacts.ContactsProvider2;
import com.android.providers.contacts.ProfileAwareUriMatcher;
import com.android.providers.contacts.util.UserUtils;
+import com.google.common.annotations.VisibleForTesting;
+
/**
* Digest contacts policy from DevcicePolicyManager and guard enterprise uri
*/
@@ -54,19 +59,28 @@
*/
public boolean isCrossProfileAllowed(@NonNull Uri uri) {
final int uriCode = sUriMatcher.match(uri);
- final UserHandle workUserHandle = UserUtils.getCorpUserHandle(mContext);
- if (uriCode == -1 || workUserHandle == null) {
+ final UserHandle currentHandle = new UserHandle(UserUtils.getCurrentUserHandle(mContext));
+ if (uriCode == -1 || currentHandle == null) {
return false;
}
- final boolean isCallerIdEnabled = !mDpm.getCrossProfileCallerIdDisabled(workUserHandle);
+ final boolean isCallerIdEnabled = !mDpm.getCrossProfileCallerIdDisabled(currentHandle);
final boolean isContactsSearchEnabled =
- !mDpm.getCrossProfileContactsSearchDisabled(workUserHandle);
+ !mDpm.getCrossProfileContactsSearchDisabled(currentHandle);
+ final boolean isCrossProfileDirectorySupported = isCrossProfileDirectorySupported(uri);
+ final String directory = uri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY);
if (VERBOSE_LOGGING) {
Log.v(TAG, "isCallerIdEnabled: " + isCallerIdEnabled);
Log.v(TAG, "isContactsSearchEnabled: " + isContactsSearchEnabled);
}
+ if (directory != null) {
+ final long directoryId = Long.parseLong(directory);
+ if (Directory.isRemoteDirectory(directoryId)
+ && !isCrossProfileDirectorySupported(uri)) {
+ return false;
+ }
+ }
// If either guard policy allows access, return true.
return (isCallerIdGuarded(uriCode) && isCallerIdEnabled)
@@ -74,26 +88,47 @@
}
/**
- * Check if uri is an enterprise uri with directory param supported.
+ * Check if uri is a cross profile query with directory param supported.
*
* @param uri Uri that we want to check.
* @return True if it is an enterprise uri.
*/
- public boolean isEnterpriseUriWithDirectorySupport(@NonNull Uri uri) {
+ @VisibleForTesting
+ protected boolean isCrossProfileDirectorySupported(@NonNull Uri uri) {
final int uriCode = sUriMatcher.match(uri);
return isDirectorySupported(uriCode);
}
+ public boolean isValidEnterpriseUri(@NonNull Uri uri) {
+ final int uriCode = sUriMatcher.match(uri);
+ return isValidEnterpriseUri(uriCode);
+ }
- /** Private methods **/
private static boolean isDirectorySupported(int uriCode) {
switch(uriCode) {
+ case ContactsProvider2.PHONE_LOOKUP:
+ case ContactsProvider2.EMAILS_LOOKUP:
+ case ContactsProvider2.CONTACTS_FILTER:
+ case ContactsProvider2.PHONES_FILTER:
+ case ContactsProvider2.CALLABLES_FILTER:
+ case ContactsProvider2.EMAILS_FILTER:
+ case ContactsProvider2.DIRECTORY_FILE_ENTERPRISE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static boolean isValidEnterpriseUri(int uriCode) {
+ switch (uriCode) {
case ContactsProvider2.PHONE_LOOKUP_ENTERPRISE:
case ContactsProvider2.EMAILS_LOOKUP_ENTERPRISE:
case ContactsProvider2.CONTACTS_FILTER_ENTERPRISE:
case ContactsProvider2.PHONES_FILTER_ENTERPRISE:
case ContactsProvider2.CALLABLES_FILTER_ENTERPRISE:
case ContactsProvider2.EMAILS_FILTER_ENTERPRISE:
+ case ContactsProvider2.DIRECTORIES_ENTERPRISE:
+ case ContactsProvider2.DIRECTORIES_ID_ENTERPRISE:
case ContactsProvider2.DIRECTORY_FILE_ENTERPRISE:
return true;
default:
@@ -103,12 +138,12 @@
private static boolean isCallerIdGuarded(int uriCode) {
switch(uriCode) {
- case ContactsProvider2.DIRECTORIES_ENTERPRISE:
- case ContactsProvider2.DIRECTORIES_ID_ENTERPRISE:
- case ContactsProvider2.PHONE_LOOKUP_ENTERPRISE:
- case ContactsProvider2.EMAILS_LOOKUP_ENTERPRISE:
- case ContactsProvider2.CONTACTS_ID_PHOTO_CORP:
- case ContactsProvider2.CONTACTS_ID_DISPLAY_PHOTO_CORP:
+ case ContactsProvider2.DIRECTORIES:
+ case ContactsProvider2.DIRECTORIES_ID:
+ case ContactsProvider2.PHONE_LOOKUP:
+ case ContactsProvider2.EMAILS_LOOKUP:
+ case ContactsProvider2.CONTACTS_ID_PHOTO:
+ case ContactsProvider2.CONTACTS_ID_DISPLAY_PHOTO:
case ContactsProvider2.DIRECTORY_FILE_ENTERPRISE:
return true;
default:
@@ -118,14 +153,14 @@
private static boolean isContactsSearchGuarded(int uriCode) {
switch(uriCode) {
- case ContactsProvider2.DIRECTORIES_ENTERPRISE:
- case ContactsProvider2.DIRECTORIES_ID_ENTERPRISE:
- case ContactsProvider2.CONTACTS_FILTER_ENTERPRISE:
- case ContactsProvider2.CALLABLES_FILTER_ENTERPRISE:
- case ContactsProvider2.PHONES_FILTER_ENTERPRISE:
- case ContactsProvider2.EMAILS_FILTER_ENTERPRISE:
- case ContactsProvider2.CONTACTS_ID_PHOTO_CORP:
- case ContactsProvider2.CONTACTS_ID_DISPLAY_PHOTO_CORP:
+ case ContactsProvider2.DIRECTORIES:
+ case ContactsProvider2.DIRECTORIES_ID:
+ case ContactsProvider2.CONTACTS_FILTER:
+ case ContactsProvider2.CALLABLES_FILTER:
+ case ContactsProvider2.PHONES_FILTER:
+ case ContactsProvider2.EMAILS_FILTER:
+ case ContactsProvider2.CONTACTS_ID_PHOTO:
+ case ContactsProvider2.CONTACTS_ID_DISPLAY_PHOTO:
case ContactsProvider2.DIRECTORY_FILE_ENTERPRISE:
return true;
default:
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
index 6ff5ddd..d4418c4 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -72,6 +72,7 @@
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
+import android.util.ArraySet;
import com.android.internal.util.ArrayUtils;
import com.android.providers.contacts.ContactsActor.AlteringUserContext;
@@ -97,6 +98,7 @@
import com.android.providers.contacts.testutil.TestUtil;
import com.android.providers.contacts.tests.R;
import com.android.providers.contacts.util.NullContentProvider;
+import com.android.providers.contacts.util.UserUtils;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
@@ -2619,6 +2621,58 @@
assertStoredValuesOrderly(filterUri3, new ContentValues[] { v3, v1, v2 });
}
+ public void testAddQueryParametersFromUri() {
+ final ContactsProvider2 provider = (ContactsProvider2) getProvider();
+ final Uri originalUri = Phone.CONTENT_FILTER_URI.buildUpon()
+ .appendQueryParameter("a", "a")
+ .appendQueryParameter("b", "b")
+ .appendQueryParameter("c", "c").build();
+ final Uri.Builder targetBuilder = Phone.CONTENT_FILTER_URI.buildUpon();
+ provider.addQueryParametersFromUri(targetBuilder, originalUri,
+ new ArraySet<String>(Arrays.asList(new String[] {
+ "b"
+ })));
+ final Uri targetUri = targetBuilder.build();
+ assertEquals(1, targetUri.getQueryParameters("a").size());
+ assertEquals(0, targetUri.getQueryParameters("b").size());
+ assertEquals(1, targetUri.getQueryParameters("c").size());
+ }
+
+ private Uri buildContactsFilterUriWithDirectory(String directory) {
+ return Contacts.CONTENT_FILTER_URI.buildUpon()
+ .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY, directory).build();
+ }
+
+ public void testTestInvalidDirectory() throws Exception {
+ final ContactsProvider2 provider = (ContactsProvider2) getProvider();
+ assertTrue(provider.isDirectoryParamValid(Contacts.CONTENT_FILTER_URI));
+ assertFalse(provider.isDirectoryParamValid(buildContactsFilterUriWithDirectory("")));
+ assertTrue(provider.isDirectoryParamValid(buildContactsFilterUriWithDirectory("0")));
+ assertTrue(provider.isDirectoryParamValid(buildContactsFilterUriWithDirectory("123")));
+ assertFalse(provider.isDirectoryParamValid(buildContactsFilterUriWithDirectory("abc")));
+ }
+
+ public void testQueryCorpContactsProvider() throws Exception {
+ final ContactsProvider2 provider = (ContactsProvider2) getProvider();
+ final MockUserManager um = mActor.mockUserManager;
+ final Uri enterpriseUri =
+ Uri.withAppendedPath(PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI, "408-222-2222");
+ final Uri invalidAuthorityUri = android.provider.Settings.Secure.CONTENT_URI;
+
+ // No corp user. Primary only.
+ assertEquals(-1, UserUtils.getCorpUserId(mActor.getProviderContext()));
+ assertNull(provider.queryCorpContactsProvider(enterpriseUri, null, null, null,
+ null, null));
+
+ final SynchronousContactsProvider2 corpCp2 = setUpCorpProvider();
+ // Primary + corp
+ um.setUsers(MockUserManager.PRIMARY_USER, MockUserManager.CORP_USER);
+ assertNotNull(provider.queryCorpContactsProvider(enterpriseUri, null, null, null,
+ null, null));
+ assertNull(provider.queryCorpContactsProvider(invalidAuthorityUri, null, null,
+ null, null, null));
+ }
+
/**
* Tests {@link DataUsageFeedback} correctly bucketize contacts using each
* {@link DataUsageStatColumns#LAST_TIME_USED}
diff --git a/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java b/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java
index af8c966..505ce21 100644
--- a/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java
+++ b/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java
@@ -26,6 +26,7 @@
import android.test.mock.MockContext;
import android.test.suitebuilder.annotation.SmallTest;
+import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
@@ -55,28 +56,28 @@
private static final String CONTACT_PHONE = "+1234567890";
private static final long DIRECTORY_ID = Directory.ENTERPRISE_DEFAULT;
- private static final Uri URI_CONTACTS_ID_PHOTO_CORP =
- Uri.parse("content://com.android.contacts/contacts_corp/" + CONTACT_ID + "/photo");
- private static final Uri URI_CONTACTS_ID_DISPLAY_PHOTO_CORP = Uri
- .parse("content://com.android.contacts/contacts_corp/" + CONTACT_ID + "/display_photo");
- private static final Uri URI_CONTACTS_FILTER_ENTERPRISE =
- Uri.parse("content://com.android.contacts/contacts/filter_enterprise/" + CONTACT_NAME);
- private static final Uri URI_PHONES_FILTER_ENTERPRISE = Uri
- .parse("content://com.android.contacts/data/phones/filter_enterprise/" + CONTACT_NAME);
- private static final Uri URI_CALLABLES_FILTER_ENTERPRISE = Uri.parse(
- "content://com.android.contacts/data/callables/filter_enterprise/" + CONTACT_NAME);
- private static final Uri URI_EMAILS_FILTER_ENTERPRISE = Uri
- .parse("content://com.android.contacts/data/emails/filter_enterprise/" + CONTACT_NAME);
- private static final Uri URI_EMAILS_LOOKUP_ENTERPRISE =
- Uri.parse("content://com.android.contacts/data/emails/lookup_enterprise/"
+ private static final Uri URI_CONTACTS_ID_PHOTO =
+ Uri.parse("content://com.android.contacts/contacts/" + CONTACT_ID + "/photo");
+ private static final Uri URI_CONTACTS_ID_DISPLAY_PHOTO = Uri
+ .parse("content://com.android.contacts/contacts/" + CONTACT_ID + "/display_photo");
+ private static final Uri URI_CONTACTS_FILTER =
+ Uri.parse("content://com.android.contacts/contacts/filter/" + CONTACT_NAME);
+ private static final Uri URI_PHONES_FILTER = Uri
+ .parse("content://com.android.contacts/data/phones/filter/" + CONTACT_NAME);
+ private static final Uri URI_CALLABLES_FILTER = Uri.parse(
+ "content://com.android.contacts/data/callables/filter/" + CONTACT_NAME);
+ private static final Uri URI_EMAILS_FILTER = Uri
+ .parse("content://com.android.contacts/data/emails/filter/" + CONTACT_NAME);
+ private static final Uri URI_EMAILS_LOOKUP =
+ Uri.parse("content://com.android.contacts/data/emails/lookup/"
+ Uri.encode(CONTACT_EMAIL));
- private static final Uri URI_PHONE_LOOKUP_ENTERPRISE = Uri.parse(
- "content://com.android.contacts/phone_lookup_enterprise/" + Uri.encode(CONTACT_PHONE));
- private static final Uri URI_DIRECTORIES_ENTERPRISE =
- Uri.parse("content://com.android.contacts/directories_enterprise");
- private static final Uri URI_DIRECTORIES_ID_ENTERPRISE =
- Uri.parse("content://com.android.contacts/directories_enterprise/" + DIRECTORY_ID);
- private static final Uri URI_DIRECTORY_FILE_ENTERPRISE =
+ private static final Uri URI_PHONE_LOOKUP = Uri.parse(
+ "content://com.android.contacts/phone_lookup/" + Uri.encode(CONTACT_PHONE));
+ private static final Uri URI_DIRECTORIES =
+ Uri.parse("content://com.android.contacts/directories");
+ private static final Uri URI_DIRECTORIES_ID =
+ Uri.parse("content://com.android.contacts/directories/" + DIRECTORY_ID);
+ private static final Uri URI_DIRECTORY_FILE =
Uri.parse("content://com.android.contacts/directory_file_enterprise/content%3A%2F%2F"
+ "com.google.contacts.gal.provider%2Fphoto%2F?directory=1000000002");
@@ -98,17 +99,17 @@
public void testDirectorySupport() {
EnterprisePolicyGuard guard = new EnterprisePolicyGuard(getContext());
- checkDirectorySupport(guard, URI_PHONE_LOOKUP_ENTERPRISE, true);
- checkDirectorySupport(guard, URI_EMAILS_LOOKUP_ENTERPRISE, true);
- checkDirectorySupport(guard, URI_CONTACTS_FILTER_ENTERPRISE, true);
- checkDirectorySupport(guard, URI_PHONES_FILTER_ENTERPRISE, true);
- checkDirectorySupport(guard, URI_CALLABLES_FILTER_ENTERPRISE, true);
- checkDirectorySupport(guard, URI_EMAILS_FILTER_ENTERPRISE, true);
- checkDirectorySupport(guard, URI_DIRECTORY_FILE_ENTERPRISE, true);
- checkDirectorySupport(guard, URI_DIRECTORIES_ENTERPRISE, false);
- checkDirectorySupport(guard, URI_DIRECTORIES_ID_ENTERPRISE, false);
- checkDirectorySupport(guard, URI_CONTACTS_ID_PHOTO_CORP, false);
- checkDirectorySupport(guard, URI_CONTACTS_ID_DISPLAY_PHOTO_CORP, false);
+ checkDirectorySupport(guard, URI_PHONE_LOOKUP, true);
+ checkDirectorySupport(guard, URI_EMAILS_LOOKUP, true);
+ checkDirectorySupport(guard, URI_CONTACTS_FILTER, true);
+ checkDirectorySupport(guard, URI_PHONES_FILTER, true);
+ checkDirectorySupport(guard, URI_CALLABLES_FILTER, true);
+ checkDirectorySupport(guard, URI_EMAILS_FILTER, true);
+ checkDirectorySupport(guard, URI_DIRECTORY_FILE, true);
+ checkDirectorySupport(guard, URI_DIRECTORIES, false);
+ checkDirectorySupport(guard, URI_DIRECTORIES_ID, false);
+ checkDirectorySupport(guard, URI_CONTACTS_ID_PHOTO, false);
+ checkDirectorySupport(guard, URI_CONTACTS_ID_DISPLAY_PHOTO, false);
checkDirectorySupport(guard, URI_OTHER, false);
}
@@ -117,85 +118,69 @@
Context context;
EnterprisePolicyGuard guard;
- // No corp user
- context = getMockContext(/* managedProfileExists= */ false, true, true);
+ // All enabled.
+ context = getMockContext(true, true);
guard = new EnterprisePolicyGuard(context);
- checkCrossProfile(guard, URI_PHONE_LOOKUP_ENTERPRISE, false);
- checkCrossProfile(guard, URI_EMAILS_LOOKUP_ENTERPRISE, false);
- checkCrossProfile(guard, URI_CONTACTS_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_PHONES_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_CALLABLES_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_EMAILS_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_DIRECTORY_FILE_ENTERPRISE, false);
- checkCrossProfile(guard, URI_DIRECTORIES_ENTERPRISE, false);
- checkCrossProfile(guard, URI_DIRECTORIES_ID_ENTERPRISE, false);
- checkCrossProfile(guard, URI_CONTACTS_ID_PHOTO_CORP, false);
- checkCrossProfile(guard, URI_CONTACTS_ID_DISPLAY_PHOTO_CORP, false);
- checkCrossProfile(guard, URI_OTHER, false);
-
- // All enabled. Corp user enabled
- context = getMockContext(/* managedProfileExists= */ true, true, true);
- guard = new EnterprisePolicyGuard(context);
- checkCrossProfile(guard, URI_PHONE_LOOKUP_ENTERPRISE, true);
- checkCrossProfile(guard, URI_EMAILS_LOOKUP_ENTERPRISE, true);
- checkCrossProfile(guard, URI_CONTACTS_FILTER_ENTERPRISE, true);
- checkCrossProfile(guard, URI_PHONES_FILTER_ENTERPRISE, true);
- checkCrossProfile(guard, URI_CALLABLES_FILTER_ENTERPRISE, true);
- checkCrossProfile(guard, URI_EMAILS_FILTER_ENTERPRISE, true);
- checkCrossProfile(guard, URI_DIRECTORY_FILE_ENTERPRISE, true);
- checkCrossProfile(guard, URI_DIRECTORIES_ENTERPRISE, true);
- checkCrossProfile(guard, URI_DIRECTORIES_ID_ENTERPRISE, true);
- checkCrossProfile(guard, URI_CONTACTS_ID_PHOTO_CORP, true);
- checkCrossProfile(guard, URI_CONTACTS_ID_DISPLAY_PHOTO_CORP, true);
+ checkCrossProfile(guard, URI_PHONE_LOOKUP, true);
+ checkCrossProfile(guard, URI_EMAILS_LOOKUP, true);
+ checkCrossProfile(guard, URI_CONTACTS_FILTER, true);
+ checkCrossProfile(guard, URI_PHONES_FILTER, true);
+ checkCrossProfile(guard, URI_CALLABLES_FILTER, true);
+ checkCrossProfile(guard, URI_EMAILS_FILTER, true);
+ checkCrossProfile(guard, URI_DIRECTORY_FILE, true);
+ checkCrossProfile(guard, URI_DIRECTORIES, true);
+ checkCrossProfile(guard, URI_DIRECTORIES_ID, true);
+ checkCrossProfile(guard, URI_CONTACTS_ID_PHOTO, true);
+ checkCrossProfile(guard, URI_CONTACTS_ID_DISPLAY_PHOTO, true);
checkCrossProfile(guard, URI_OTHER, false);
// Only ContactsSearch is disabled
- context = getMockContext(true, true, /* isContactsSearchEnabled= */ false);
+ context = getMockContext(true, /* isContactsSearchEnabled= */ false);
guard = new EnterprisePolicyGuard(context);
- checkCrossProfile(guard, URI_PHONE_LOOKUP_ENTERPRISE, true);
- checkCrossProfile(guard, URI_EMAILS_LOOKUP_ENTERPRISE, true);
- checkCrossProfile(guard, URI_CONTACTS_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_PHONES_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_CALLABLES_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_EMAILS_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_DIRECTORY_FILE_ENTERPRISE, true);
- checkCrossProfile(guard, URI_DIRECTORIES_ENTERPRISE, true);
- checkCrossProfile(guard, URI_DIRECTORIES_ID_ENTERPRISE, true);
- checkCrossProfile(guard, URI_CONTACTS_ID_PHOTO_CORP, true);
- checkCrossProfile(guard, URI_CONTACTS_ID_DISPLAY_PHOTO_CORP, true);
+ checkCrossProfile(guard, URI_PHONE_LOOKUP, true);
+ checkCrossProfile(guard, URI_EMAILS_LOOKUP, true);
+ checkCrossProfile(guard, URI_CONTACTS_FILTER, false);
+ checkCrossProfile(guard, URI_PHONES_FILTER, false);
+ checkCrossProfile(guard, URI_CALLABLES_FILTER, false);
+ checkCrossProfile(guard, URI_EMAILS_FILTER, false);
+ checkCrossProfile(guard, URI_DIRECTORY_FILE, true);
+ checkCrossProfile(guard, URI_DIRECTORIES, true);
+ checkCrossProfile(guard, URI_DIRECTORIES_ID, true);
+ checkCrossProfile(guard, URI_CONTACTS_ID_PHOTO, true);
+ checkCrossProfile(guard, URI_CONTACTS_ID_DISPLAY_PHOTO, true);
checkCrossProfile(guard, URI_OTHER, false);
// Only CallerId is disabled
- context = getMockContext(true, /* isCallerIdEnabled= */ false, true);
+ context = getMockContext(/* isCallerIdEnabled= */ false, true);
guard = new EnterprisePolicyGuard(context);
- checkCrossProfile(guard, URI_PHONE_LOOKUP_ENTERPRISE, false);
- checkCrossProfile(guard, URI_EMAILS_LOOKUP_ENTERPRISE, false);
- checkCrossProfile(guard, URI_CONTACTS_FILTER_ENTERPRISE, true);
- checkCrossProfile(guard, URI_PHONES_FILTER_ENTERPRISE, true);
- checkCrossProfile(guard, URI_CALLABLES_FILTER_ENTERPRISE, true);
- checkCrossProfile(guard, URI_EMAILS_FILTER_ENTERPRISE, true);
- checkCrossProfile(guard, URI_DIRECTORY_FILE_ENTERPRISE, true);
- checkCrossProfile(guard, URI_DIRECTORIES_ENTERPRISE, true);
- checkCrossProfile(guard, URI_DIRECTORIES_ID_ENTERPRISE, true);
- checkCrossProfile(guard, URI_CONTACTS_ID_PHOTO_CORP, true);
- checkCrossProfile(guard, URI_CONTACTS_ID_DISPLAY_PHOTO_CORP, true);
+ checkCrossProfile(guard, URI_PHONE_LOOKUP, false);
+ checkCrossProfile(guard, URI_EMAILS_LOOKUP, false);
+ checkCrossProfile(guard, URI_CONTACTS_FILTER, true);
+ checkCrossProfile(guard, URI_PHONES_FILTER, true);
+ checkCrossProfile(guard, URI_CALLABLES_FILTER, true);
+ checkCrossProfile(guard, URI_EMAILS_FILTER, true);
+ checkCrossProfile(guard, URI_DIRECTORY_FILE, true);
+ checkCrossProfile(guard, URI_DIRECTORIES, true);
+ checkCrossProfile(guard, URI_DIRECTORIES_ID, true);
+ checkCrossProfile(guard, URI_CONTACTS_ID_PHOTO, true);
+ checkCrossProfile(guard, URI_CONTACTS_ID_DISPLAY_PHOTO, true);
checkCrossProfile(guard, URI_OTHER, false);
// CallerId and ContactsSearch are disabled
- context = getMockContext(true, /* isCallerIdEnabled= */ false,
+ context = getMockContext(/* isCallerIdEnabled= */ false,
/* isContactsSearchEnabled= */ false);
guard = new EnterprisePolicyGuard(context);
- checkCrossProfile(guard, URI_PHONE_LOOKUP_ENTERPRISE, false);
- checkCrossProfile(guard, URI_EMAILS_LOOKUP_ENTERPRISE, false);
- checkCrossProfile(guard, URI_CONTACTS_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_PHONES_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_CALLABLES_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_EMAILS_FILTER_ENTERPRISE, false);
- checkCrossProfile(guard, URI_DIRECTORY_FILE_ENTERPRISE, false);
- checkCrossProfile(guard, URI_DIRECTORIES_ENTERPRISE, false);
- checkCrossProfile(guard, URI_DIRECTORIES_ID_ENTERPRISE, false);
- checkCrossProfile(guard, URI_CONTACTS_ID_PHOTO_CORP, false);
- checkCrossProfile(guard, URI_CONTACTS_ID_DISPLAY_PHOTO_CORP, false);
+ checkCrossProfile(guard, URI_PHONE_LOOKUP, false);
+ checkCrossProfile(guard, URI_EMAILS_LOOKUP, false);
+ checkCrossProfile(guard, URI_CONTACTS_FILTER, false);
+ checkCrossProfile(guard, URI_PHONES_FILTER, false);
+ checkCrossProfile(guard, URI_CALLABLES_FILTER, false);
+ checkCrossProfile(guard, URI_EMAILS_FILTER, false);
+ checkCrossProfile(guard, URI_DIRECTORY_FILE, false);
+ checkCrossProfile(guard, URI_DIRECTORIES, false);
+ checkCrossProfile(guard, URI_DIRECTORIES_ID, false);
+ checkCrossProfile(guard, URI_CONTACTS_ID_PHOTO, false);
+ checkCrossProfile(guard, URI_CONTACTS_ID_DISPLAY_PHOTO, false);
checkCrossProfile(guard, URI_OTHER, false);
}
@@ -203,15 +188,13 @@
boolean expected) {
if (expected) {
assertTrue("Expected true but got false for uri: " + uri,
- guard.isEnterpriseUriWithDirectorySupport(uri));
+ guard.isCrossProfileDirectorySupported(uri));
} else {
assertFalse("Expected false but got true for uri: " + uri,
- guard.isEnterpriseUriWithDirectorySupport(uri));
-
+ guard.isCrossProfileDirectorySupported(uri));
}
}
-
private static void checkCrossProfile(EnterprisePolicyGuard guard, Uri uri, boolean expected) {
if (expected) {
assertTrue("Expected true but got false for uri: " + uri,
@@ -236,16 +219,14 @@
Arrays.asList(new UserInfo[] {CURRENT_USER_INFO, WORK_USER_INFO});
- private Context getMockContext(boolean managedProfileExists, boolean isCallerIdEnabled,
- boolean isContactsSearchEnabled) {
+ private Context getMockContext(boolean isCallerIdEnabled, boolean isContactsSearchEnabled) {
DevicePolicyManager mockDpm = mock(DevicePolicyManager.class);
when(mockDpm.getCrossProfileCallerIdDisabled(Matchers.<UserHandle>any()))
.thenReturn(!isCallerIdEnabled);
when(mockDpm.getCrossProfileContactsSearchDisabled(Matchers.<UserHandle>any()))
.thenReturn(!isContactsSearchEnabled);
- List<UserInfo> userInfos =
- managedProfileExists ? MANAGED_USERINFO_LIST : NORMAL_USERINFO_LIST;
+ List<UserInfo> userInfos = MANAGED_USERINFO_LIST;
UserManager mockUm = mock(UserManager.class);
when(mockUm.getUserHandle()).thenReturn(CURRENT_USER_ID);
when(mockUm.getUsers()).thenReturn(userInfos);