aboutsummaryrefslogtreecommitdiff
path: root/tests/src
diff options
context:
space:
mode:
Diffstat (limited to 'tests/src')
-rw-r--r--tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java86
-rw-r--r--tests/src/com/android/providers/contacts/CallLogMigrationTest.java45
-rw-r--r--tests/src/com/android/providers/contacts/CloneContactsProvider2Test.java504
-rw-r--r--tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java18
-rw-r--r--tests/src/com/android/providers/contacts/ContactsActor.java29
-rw-r--r--tests/src/com/android/providers/contacts/ContactsMockPackageManager.java12
-rw-r--r--tests/src/com/android/providers/contacts/ContactsProvider2Test.java85
-rw-r--r--tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java10
-rw-r--r--tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java69
-rw-r--r--tests/src/com/android/providers/contacts/util/UserUtilsTest.java78
10 files changed, 792 insertions, 144 deletions
diff --git a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
index 54984d29..e8920530 100644
--- a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
@@ -70,6 +70,8 @@ import com.android.providers.contacts.util.Hex;
import com.android.providers.contacts.util.MockClock;
import com.google.android.collect.Sets;
+import java.io.FileInputStream;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
@@ -1381,6 +1383,25 @@ public abstract class BaseContactsProvider2Test extends PhotoLoadingTestCase {
assertEquals(timeStamp, time);
}
+ /**
+ * Asserts the equality of two Uri objects, ignoring the order of the query parameters.
+ */
+ protected static void assertUriEquals(Uri expected, Uri actual) {
+ assertEquals(expected.getScheme(), actual.getScheme());
+ assertEquals(expected.getAuthority(), actual.getAuthority());
+ assertEquals(expected.getPath(), actual.getPath());
+ assertEquals(expected.getFragment(), actual.getFragment());
+ Set<String> expectedParameterNames = expected.getQueryParameterNames();
+ Set<String> actualParameterNames = actual.getQueryParameterNames();
+ assertEquals(expectedParameterNames.size(), actualParameterNames.size());
+ assertTrue(expectedParameterNames.containsAll(actualParameterNames));
+ for (String parameterName : expectedParameterNames) {
+ assertEquals(expected.getQueryParameter(parameterName),
+ actual.getQueryParameter(parameterName));
+ }
+
+ }
+
protected void setTimeForTest(Long time) {
Uri uri = Calls.CONTENT_URI.buildUpon()
.appendQueryParameter(CallLogProvider.PARAM_KEY_QUERY_FOR_TESTING, "1")
@@ -1400,6 +1421,71 @@ public abstract class BaseContactsProvider2Test extends PhotoLoadingTestCase {
getContactsProvider().getProfileProviderForTest().getDatabaseHelper(), values);
}
+ protected class VCardTestUriCreator {
+ private String mLookup1;
+ private String mLookup2;
+
+ public VCardTestUriCreator(String lookup1, String lookup2) {
+ super();
+ mLookup1 = lookup1;
+ mLookup2 = lookup2;
+ }
+
+ public Uri getUri1() {
+ return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup1);
+ }
+
+ public Uri getUri2() {
+ return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup2);
+ }
+
+ public Uri getCombinedUri() {
+ return Uri.withAppendedPath(Contacts.CONTENT_MULTI_VCARD_URI,
+ Uri.encode(mLookup1 + ":" + mLookup2));
+ }
+ }
+
+ protected VCardTestUriCreator createVCardTestContacts() {
+ final long rawContactId1 = RawContactUtil.createRawContact(mResolver, mAccount,
+ RawContacts.SOURCE_ID, "4:12");
+ DataUtil.insertStructuredName(mResolver, rawContactId1, "John", "Doe");
+
+ final long rawContactId2 = RawContactUtil.createRawContact(mResolver, mAccount,
+ RawContacts.SOURCE_ID, "3:4%121");
+ DataUtil.insertStructuredName(mResolver, rawContactId2, "Jane", "Doh");
+
+ final long contactId1 = queryContactId(rawContactId1);
+ final long contactId2 = queryContactId(rawContactId2);
+ final Uri contact1Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId1);
+ final Uri contact2Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId2);
+ final String lookup1 =
+ Uri.encode(Contacts.getLookupUri(mResolver, contact1Uri).getPathSegments().get(2));
+ final String lookup2 =
+ Uri.encode(Contacts.getLookupUri(mResolver, contact2Uri).getPathSegments().get(2));
+ return new VCardTestUriCreator(lookup1, lookup2);
+ }
+
+ protected String readToEnd(FileInputStream inputStream) {
+ try {
+ System.out.println("DECLARED INPUT STREAM LENGTH: " + inputStream.available());
+ int ch;
+ StringBuilder stringBuilder = new StringBuilder();
+ int index = 0;
+ while (true) {
+ ch = inputStream.read();
+ System.out.println("READ CHARACTER: " + index + " " + ch);
+ if (ch == -1) {
+ break;
+ }
+ stringBuilder.append((char)ch);
+ index++;
+ }
+ return stringBuilder.toString();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
/**
* A contact in the database, and the attributes used to create it. Construct using
* {@link GoldenContactBuilder#build()}.
diff --git a/tests/src/com/android/providers/contacts/CallLogMigrationTest.java b/tests/src/com/android/providers/contacts/CallLogMigrationTest.java
index d1e80035..74e5d0a5 100644
--- a/tests/src/com/android/providers/contacts/CallLogMigrationTest.java
+++ b/tests/src/com/android/providers/contacts/CallLogMigrationTest.java
@@ -93,51 +93,6 @@ public class CallLogMigrationTest extends FixedAndroidTestCase {
+ " = 1", null));
}
- public void testMigration() throws IOException {
- final File sourceDbFile = new File(getTestContext().getCacheDir(), "contacts2src.db");
- writeAssetFileToDisk("calllogmigration/contacts2.db", sourceDbFile);
-
- try (final SQLiteDatabase sourceDb = SQLiteDatabase.openDatabase(
- sourceDbFile.getAbsolutePath(), /* cursorFactory=*/ null,
- SQLiteDatabase.OPEN_READWRITE)) {
-
- // Make sure the source tables exist initially.
- assertTrue(CallLogDatabaseHelper.tableExists(sourceDb, "calls"));
- assertTrue(CallLogDatabaseHelper.tableExists(sourceDb, "voicemail_status"));
- // Create the calllog DB to perform the migration.
- final CallLogDatabaseHelperTestable dbh =
- new CallLogDatabaseHelperTestable(getTestContext(), sourceDb);
-
- final SQLiteDatabase db = dbh.getReadableDatabase();
-
- // Check the content:
- // Note what we worry here is basically insertion error due to additional constraints,
- // renames, etc. So here, we just check the number of rows and don't check the content.
- assertEquals(3, DatabaseUtils.longForQuery(db, "select count(*) from " +
- CallLogDatabaseHelper.Tables.CALLS, null));
-
- assertEquals(2, DatabaseUtils.longForQuery(db, "select count(*) from " +
- CallLogDatabaseHelper.Tables.VOICEMAIL_STATUS, null));
-
- assertEquals("123456",
- dbh.getProperty(CallLogDatabaseHelper.DbProperties.CALL_LOG_LAST_SYNCED, ""));
-
- // Test onCreate() step, check each entry with TelephonyComponent in the CALLS has
- // a new coloumn of Calls.IS_PHONE_ACCOUNT_MIGRATION_PENDING.
- assertEquals(3,
- DatabaseUtils.longForQuery(db, "select count(*) from "
- + CallLogDatabaseHelper.Tables.CALLS + " where "
- + Calls.IS_PHONE_ACCOUNT_MIGRATION_PENDING + " = 0", null));
-
- // Also, the source table should have been removed.
- assertFalse(CallLogDatabaseHelper.tableExists(sourceDb, "calls"));
- assertFalse(CallLogDatabaseHelper.tableExists(sourceDb, "voicemail_status"));
-
- assertEquals("1",
- dbh.getProperty(CallLogDatabaseHelper.DbProperties.DATA_MIGRATED, ""));
- }
- }
-
public static final class InMemoryCallLogProviderDbHelperV1 extends SQLiteOpenHelper {
public InMemoryCallLogProviderDbHelperV1(Context context, int databaseVersion) {
super(context,
diff --git a/tests/src/com/android/providers/contacts/CloneContactsProvider2Test.java b/tests/src/com/android/providers/contacts/CloneContactsProvider2Test.java
new file mode 100644
index 00000000..26a78143
--- /dev/null
+++ b/tests/src/com/android/providers/contacts/CloneContactsProvider2Test.java
@@ -0,0 +1,504 @@
+/*
+ * Copyright (C) 2022 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.ContactsActor.MockUserManager.CLONE_PROFILE_USER;
+import static com.android.providers.contacts.ContactsActor.MockUserManager.PRIMARY_USER;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.spy;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.OperationApplicationException;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.provider.CallLog;
+import android.provider.ContactsContract;
+import android.util.SparseArray;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SdkSuppress;
+
+import org.junit.Assert;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Set;
+
+@MediumTest
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+public class CloneContactsProvider2Test extends BaseContactsProvider2Test {
+
+ private ContactsActor mCloneContactsActor;
+ private SynchronousContactsProvider2 mCloneContactsProvider;
+
+ private SynchronousContactsProvider2 getCloneContactsProvider() {
+ return (SynchronousContactsProvider2) mCloneContactsActor.provider;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mCloneContactsActor = new ContactsActor(
+ new ContactsActor.AlteringUserContext(getContext(), CLONE_PROFILE_USER.id),
+ getContextPackageName(), SynchronousContactsProvider2.class, getAuthority());
+ mActor.mockUserManager.setUsers(ContactsActor.MockUserManager.PRIMARY_USER,
+ CLONE_PROFILE_USER);
+ mCloneContactsActor.mockUserManager.setUsers(ContactsActor.MockUserManager.PRIMARY_USER,
+ CLONE_PROFILE_USER);
+ mCloneContactsActor.mockUserManager.myUser = CLONE_PROFILE_USER.id;
+ mCloneContactsProvider = spy(getCloneContactsProvider());
+ mCloneContactsProvider.wipeData();
+ }
+
+ private ContentValues getSampleContentValues() {
+ ContentValues values = new ContentValues();
+ values.put(ContactsContract.RawContacts.ACCOUNT_NAME, "test@test.com");
+ values.put(ContactsContract.RawContacts.ACCOUNT_TYPE, "test.com");
+ values.put(ContactsContract.RawContacts.CUSTOM_RINGTONE, "custom");
+ values.put(ContactsContract.RawContacts.STARRED, "1");
+ return values;
+ }
+
+ private void getCloneContactsProviderWithMockedCallToParent(Uri uri) {
+ Cursor primaryProfileCursor = mActor.provider.query(uri,
+ null /* projection */, null /* queryArgs */, null /* cancellationSignal */);
+ assertNotNull(primaryProfileCursor);
+ doReturn(primaryProfileCursor).when(mCloneContactsProvider)
+ .queryContactsProviderForUser(eq(uri), any(), any(), any(), any(),
+ any(), eq(PRIMARY_USER));
+ }
+
+ private void getCloneContactsProviderWithMockedOpenAssetFileCall(Uri uri)
+ throws FileNotFoundException {
+ AssetFileDescriptor fileDescriptor = mActor.provider.openAssetFile(uri, "r");
+ doReturn(fileDescriptor).when(mCloneContactsProvider)
+ .openAssetFileThroughParentProvider(eq(uri), eq("r"));
+ }
+
+ private String getCursorValue(Cursor c, String columnName) {
+ return c.getString(c.getColumnIndex(columnName));
+ }
+
+ private void assertEqualContentValues(ContentValues contentValues, Cursor cursor) {
+ for (String key: contentValues.getValues().keySet()) {
+ assertEquals(contentValues.get(key), getCursorValue(cursor, key));
+ }
+ }
+
+ private void assertRawContactsCursorEquals(Cursor expectedCursor, Cursor actualCursor,
+ Set<String> columnNames) {
+ assertNotNull(actualCursor);
+ assertEquals(expectedCursor.getCount(), actualCursor.getCount());
+ while (actualCursor.moveToNext()) {
+ expectedCursor.moveToNext();
+ for (String key: columnNames) {
+ assertEquals(getCursorValue(expectedCursor, key),
+ getCursorValue(actualCursor, key));
+ }
+ }
+ }
+
+ private void assertRejectedApplyBatchResults(ContentProviderResult[] res,
+ ArrayList<ContentProviderOperation> ops) {
+ assertEquals(ops.size(), res.length);
+ for (int i = 0;i < ops.size();i++) {
+ Uri expectedUri = ops.get(i).getUri()
+ .buildUpon()
+ .appendPath("0")
+ .build();
+ assertUriEquals(expectedUri, res[i].uri);
+ }
+ }
+
+ /**
+ * Asserts that no contacts are returned when queried by the given contacts provider
+ */
+ private void assertContactsProviderEmpty(ContactsProvider2 contactsProvider2) {
+ Cursor cursor = contactsProvider2.query(ContactsContract.RawContacts.CONTENT_URI,
+ new String[]{ContactsContract.RawContactsEntity._ID},
+ null /* queryArgs */, null /* cancellationSignal */);
+ assertNotNull(cursor);
+ assertEquals(cursor.getCount(), 0);
+ }
+
+ private long insertRawContactsThroughPrimaryProvider(ContentValues values) {
+ Uri resultUri = mActor.resolver.insert(ContactsContract.RawContacts.CONTENT_URI,
+ values);
+ assertNotNull(resultUri);
+ return ContentUris.parseId(resultUri);
+ }
+
+ public void testAreContactWritesEnabled() {
+ // Check that writes are disabled for clone CP2
+ ContactsProvider2 cloneContactsProvider =
+ (ContactsProvider2) mCloneContactsActor.provider;
+ assertFalse(cloneContactsProvider.areContactWritesEnabled());
+
+ // Check that writes are enabled for primary CP2
+ ContactsProvider2 primaryContactsProvider = (ContactsProvider2) getProvider();
+ assertTrue(primaryContactsProvider.areContactWritesEnabled());
+ }
+
+ public void testCloneContactsProviderInsert() {
+ Uri resultUri =
+ mCloneContactsActor.resolver.insert(ContactsContract.RawContacts.CONTENT_URI,
+ getSampleContentValues());
+
+ // Here we expect a fakeUri returned to fail silently
+ Uri expectedUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon()
+ .appendPath("0")
+ .build();
+ assertUriEquals(expectedUri, resultUri);
+ // No contacts should be present in both clone and primary providers
+ assertContactsProviderEmpty(getContactsProvider());
+ doReturn(false)
+ .when(mCloneContactsProvider).isAppAllowedToUseParentUsersContacts(any());
+ assertContactsProviderEmpty(mCloneContactsProvider);
+
+ }
+
+ public void testPrimaryContactsProviderInsert() {
+ ContentValues inputContentValues = getSampleContentValues();
+ long rawContactId = insertRawContactsThroughPrimaryProvider(inputContentValues);
+ Cursor cursor = mActor.resolver.query(ContentUris.withAppendedId(
+ ContactsContract.RawContacts.CONTENT_URI, rawContactId),
+ null /* projection */, null /* queryArgs */, null /* cancellationSignal */);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ assertTrue(cursor.moveToFirst());
+ assertEquals(rawContactId,
+ cursor.getLong(cursor.getColumnIndex(ContactsContract.RawContacts._ID)));
+ assertEqualContentValues(inputContentValues, cursor);
+ }
+
+ public void testCloneContactsProviderUpdate() {
+ // Insert contact through the primary clone provider
+ ContentValues inputContentValues = getSampleContentValues();
+ long rawContactId = insertRawContactsThroughPrimaryProvider(inputContentValues);
+
+ // Update display name in the input content values
+ ContentValues updatedContentValues = getSampleContentValues();
+ updatedContentValues.put(ContactsContract.RawContacts.STARRED,
+ "0");
+ updatedContentValues.put(ContactsContract.RawContacts.CUSTOM_RINGTONE,
+ "beethoven5");
+
+ // Call clone contacts provider update method to update the raw contact inserted earlier
+ int updateResult = mCloneContactsActor.resolver.update(
+ ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId),
+ updatedContentValues, null /* extras */);
+
+ // Check results, no rows should have been affected
+ assertEquals(0, updateResult);
+
+ // Check values associated with rawContactId by querying the database
+ Cursor cursor = mActor.resolver.query(ContentUris.withAppendedId(
+ ContactsContract.RawContacts.CONTENT_URI, rawContactId),
+ null /* projection */, null /* queryArgs */, null /* cancellationSignal */);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ assertTrue(cursor.moveToFirst());
+ assertEqualContentValues(inputContentValues, cursor);
+ }
+
+ public void testCloneContactsProviderDelete() {
+ // Insert contact through the primary clone provider
+ ContentValues inputContentValues = getSampleContentValues();
+ long rawContactId = insertRawContactsThroughPrimaryProvider(inputContentValues);
+
+ // Delete the inserted row through clone provider
+ int deleteResult = mCloneContactsActor.resolver.delete(
+ ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId),
+ null);
+
+ // Check results, no rows should have been affected
+ assertEquals(0, deleteResult);
+
+ // Check that contact is present in the primary CP2 database
+ Cursor cursor = mActor.resolver.query(ContentUris.withAppendedId(
+ ContactsContract.RawContacts.CONTENT_URI, rawContactId),
+ null /* projection */, null /* queryArgs */, null /* cancellationSignal */);
+ assertNotNull(cursor);
+ assertEquals(1, cursor.getCount());
+ assertTrue(cursor.moveToFirst());
+ assertEqualContentValues(inputContentValues, cursor);
+ }
+
+ public void testCloneContactsProviderBulkInsert() {
+ int bulkInsertResult =
+ mCloneContactsActor.resolver.bulkInsert(ContactsContract.RawContacts.CONTENT_URI,
+ new ContentValues[]{ getSampleContentValues() });
+
+ // Check results, no rows should have been affected
+ assertEquals(0, bulkInsertResult);
+ // No contacts should be present in both clone and primary providers
+ assertContactsProviderEmpty(getContactsProvider());
+ doReturn(false)
+ .when(mCloneContactsProvider).isAppAllowedToUseParentUsersContacts(any());
+ assertContactsProviderEmpty(mCloneContactsProvider);
+ }
+
+ public void testCloneContactsApplyBatch()
+ throws RemoteException, OperationApplicationException {
+ ArrayList<ContentProviderOperation> ops = new ArrayList<>();
+
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
+ .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null /* value */)
+ .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null /* value */).build());
+
+ // Phone Number
+ ops.add(ContentProviderOperation
+ .newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+ .withValue(ContactsContract.Data.MIMETYPE,
+ ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "7XXXXXXXXXX")
+ .withValue(ContactsContract.Data.MIMETYPE,
+ ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, "1").build());
+
+ // Display name/Contact name
+ ops.add(ContentProviderOperation
+ .newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+ .withValue(ContactsContract.Data.MIMETYPE,
+ ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, "Name")
+ .build());
+
+ // Check results, fake uris should be returned for each of the insert operation
+ ContentProviderResult[] res = mCloneContactsActor.resolver.applyBatch(
+ ContactsContract.AUTHORITY, ops);
+ assertRejectedApplyBatchResults(res, ops);
+
+ // No contacts should be present in both clone and primary providers
+ assertContactsProviderEmpty(getContactsProvider());
+ doReturn(false)
+ .when(mCloneContactsProvider).isAppAllowedToUseParentUsersContacts(any());
+ assertContactsProviderEmpty(mCloneContactsProvider);
+ }
+
+ public void testCloneContactsCallOperation() {
+ // Query Account Operation
+ Bundle response = mCloneContactsActor.resolver.call(ContactsContract.AUTHORITY_URI,
+ ContactsContract.Settings.QUERY_DEFAULT_ACCOUNT_METHOD, null /* arg */,
+ null /* extras */);
+ assertNotNull(response);
+ assertEquals(Bundle.EMPTY, response);
+
+ // Set account operation
+ Bundle bundle = new Bundle();
+ bundle.putString(ContactsContract.Settings.ACCOUNT_NAME, "test@test.com");
+ bundle.putString(ContactsContract.Settings.ACCOUNT_TYPE, "test.com");
+ Bundle setAccountResponse =
+ mCloneContactsActor.resolver.call(ContactsContract.AUTHORITY_URI,
+ ContactsContract.Settings.SET_DEFAULT_ACCOUNT_METHOD, null /* arg */, bundle);
+ assertNotNull(setAccountResponse);
+ assertEquals(Bundle.EMPTY, response);
+
+ // Authorization URI
+ Uri testUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, 1);
+ final Bundle uriBundle = new Bundle();
+ uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, testUri);
+ final Bundle authResponse = mCloneContactsActor.resolver.call(
+ ContactsContract.AUTHORITY_URI,
+ ContactsContract.Authorization.AUTHORIZATION_METHOD,
+ null /* arg */,
+ uriBundle);
+ assertNotNull(authResponse);
+ assertEquals(Bundle.EMPTY, authResponse);
+ }
+
+ public void testCloneContactsProviderReads_callerNotInAllowlist() {
+ // Insert raw contact through the primary clone provider
+ ContentValues inputContentValues = getSampleContentValues();
+ long rawContactId = insertRawContactsThroughPrimaryProvider(inputContentValues);
+ Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI,
+ rawContactId);
+
+ // Mock call to parent profile contacts provider to return the correct result containing all
+ // contacts in the parent profile.
+ getCloneContactsProviderWithMockedCallToParent(uri);
+
+ // Mock call to ensure the caller package is not in the app-cloning allowlist
+ doReturn(false)
+ .when(mCloneContactsProvider).isAppAllowedToUseParentUsersContacts(any());
+
+ // Test clone contacts provider read with the uri of the contact added above
+ mCloneContactsProvider.query(uri,
+ null /* projection */, null /* queryArgs */, null /* cancellationSignal */);
+
+ // Check that the call passed through to the local query instead of redirecting to the
+ // parent provider
+ verify(mCloneContactsProvider, times(1))
+ .queryDirectoryIfNecessary(any(), any(), any(), any(), any(), any());
+ }
+
+ public void testContactsProviderReads_callerInAllowlist() {
+ // Insert raw contact through the primary clone provider
+ ContentValues inputContentValues = getSampleContentValues();
+ long rawContactId = insertRawContactsThroughPrimaryProvider(inputContentValues);
+ Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI,
+ rawContactId);
+
+ // Mock call to parent profile contacts provider to return the correct result containing all
+ // contacts in the parent profile.
+ getCloneContactsProviderWithMockedCallToParent(uri);
+
+ // Mock call to ensure the caller package is in the app-cloning allowlist
+ doReturn(true)
+ .when(mCloneContactsProvider).isAppAllowedToUseParentUsersContacts(any());
+
+ // Test clone contacts provider read with the uri of the contact added above
+ Cursor cursor = mCloneContactsProvider.query(uri,
+ null /* projection */, null /* queryArgs */, null /* cancellationSignal */);
+
+ // Check that the call did not pass through to the local query and instead redirected to the
+ // parent provider
+ verify(mCloneContactsProvider, times(0))
+ .queryDirectoryIfNecessary(any(), any(), any(), any(), any(), any());
+ assertNotNull(cursor);
+ Cursor primaryProfileCursor = mActor.provider.query(uri,
+ null /* projection */, null /* queryArgs */, null /* cancellationSignal */);
+ assertNotNull(primaryProfileCursor);
+ assertRawContactsCursorEquals(primaryProfileCursor, cursor,
+ inputContentValues.getValues().keySet());
+ }
+
+ public void testQueryPrimaryProfileProvider_callingFromParentUser() {
+ ContentValues inputContentValues = getSampleContentValues();
+ long rawContactId = insertRawContactsThroughPrimaryProvider(inputContentValues);
+ Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI,
+ rawContactId);
+
+ // Fetch primary contacts provider and call method to redirect to parent provider
+ final ContactsProvider2 primaryCP2 = (ContactsProvider2) getProvider();
+ Cursor cursor = primaryCP2.queryParentProfileContactsProvider(uri,
+ null /* projection */, null /* selection */, null /* selectionArgs */,
+ null /* sortOrder */, null /* cancellationSignal */);
+
+ // Assert that empty cursor is returned
+ assertNotNull(cursor);
+ assertEquals(0, cursor.getCount());
+ }
+
+ public void testQueryPrimaryProfileProvider_incorrectAuthority() {
+ ContentValues inputContentValues = getSampleContentValues();
+ insertRawContactsThroughPrimaryProvider(inputContentValues);
+
+ Assert.assertThrows(IllegalArgumentException.class, () ->
+ mCloneContactsProvider.queryParentProfileContactsProvider(CallLog.CONTENT_URI,
+ null /* projection */, null /* selection */, null /* selectionArgs */,
+ null /* sortOrder */, null /* cancellationSignal */));
+ }
+
+ public void testOpenAssetFileMultiVCard() throws IOException {
+ final VCardTestUriCreator contacts = createVCardTestContacts();
+
+ // Mock call to parent profile contacts provider to return the correct asset file
+ getCloneContactsProviderWithMockedOpenAssetFileCall(contacts.getCombinedUri());
+
+ // Mock call to ensure the caller package is in the app-cloning allowlist
+ doReturn(true)
+ .when(mCloneContactsProvider).isAppAllowedToUseParentUsersContacts(any());
+
+ final AssetFileDescriptor descriptor =
+ mCloneContactsProvider.openAssetFile(contacts.getCombinedUri(), "r");
+ final FileInputStream inputStream = descriptor.createInputStream();
+ String data = readToEnd(inputStream);
+ inputStream.close();
+ descriptor.close();
+
+ // Ensure that the resulting VCard has both contacts
+ assertTrue(data.contains("N:Doe;John;;;"));
+ assertTrue(data.contains("N:Doh;Jane;;;"));
+ }
+
+ public void testOpenAssetFileMultiVCard_callerNotInAllowlist() throws IOException {
+ final VCardTestUriCreator contacts = createVCardTestContacts();
+
+ // Mock call to parent profile contacts provider to return the correct asset file
+ getCloneContactsProviderWithMockedOpenAssetFileCall(contacts.getCombinedUri());
+
+ // Mock call to ensure the caller package is not in the app-cloning allowlist
+ doReturn(false)
+ .when(mCloneContactsProvider).isAppAllowedToUseParentUsersContacts(any());
+
+ final AssetFileDescriptor descriptor =
+ mCloneContactsProvider.openAssetFile(contacts.getCombinedUri(), "r");
+
+ // Check that the call passed through to the local call instead of redirecting to the
+ // parent provider
+ verify(mCloneContactsProvider, times(1))
+ .openAssetFile(eq(contacts.getCombinedUri()), any());
+ }
+
+ public void testIsAppAllowedToUseParentUsersContacts_AppInAllowlistCacheEmpty()
+ throws InterruptedException {
+ String testPackageName = mCloneContactsActor.packageName;
+ int processUid = Binder.getCallingUid();
+ doReturn(true)
+ .when(mCloneContactsProvider)
+ .doesPackageHaveALauncherActivity(eq(testPackageName), any());
+
+ SparseArray<ContactsProvider2.LaunchableCloneAppsCacheEntry> launchableCloneAppsCache =
+ mCloneContactsProvider.getLaunchableCloneAppsCacheForTesting();
+ launchableCloneAppsCache.clear();
+ boolean appAllowedToUseParentUsersContacts =
+ mCloneContactsProvider.isAppAllowedToUseParentUsersContacts(testPackageName);
+ assertTrue(appAllowedToUseParentUsersContacts);
+
+ // Check that the cache has been updated with an entry corresponding to current app uid
+ ContactsProvider2.LaunchableCloneAppsCacheEntry cacheEntry =
+ launchableCloneAppsCache.get(processUid);
+ assertNotNull(cacheEntry);
+ assertEquals(1, launchableCloneAppsCache.size());
+ assertTrue(cacheEntry.doesAppHaveLaunchableActivity);
+ }
+
+ public void testIsAppAllowedToUseParentUsersContacts_AppNotInAllowlistCacheEmtpy() {
+ String testPackageName = mCloneContactsActor.packageName;
+ int processUid = Binder.getCallingUid();
+
+ SparseArray<ContactsProvider2.LaunchableCloneAppsCacheEntry> launchableCloneAppsCache =
+ mCloneContactsProvider.getLaunchableCloneAppsCacheForTesting();
+ launchableCloneAppsCache.clear();
+ assertFalse(mCloneContactsProvider.isAppAllowedToUseParentUsersContacts(testPackageName));
+
+ // Check that the cache has been updated with an entry corresponding to current app uid
+ ContactsProvider2.LaunchableCloneAppsCacheEntry cacheEntry =
+ launchableCloneAppsCache.get(processUid);
+ assertNotNull(cacheEntry);
+ assertEquals(1, launchableCloneAppsCache.size());
+ assertFalse(cacheEntry.doesAppHaveLaunchableActivity);
+ }
+}
diff --git a/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
index fca00afc..a4165ce5 100644
--- a/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
+++ b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
-
import android.accounts.Account;
import android.content.ContentValues;
import android.content.Context;
@@ -38,10 +36,15 @@ import android.test.mock.MockContentProvider;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
+import androidx.test.platform.app.InstrumentationRegistry;
+
import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
import com.google.android.collect.Lists;
+import java.util.Arrays;
+import java.util.Set;
+
/**
* Unit tests for {@link ContactDirectoryManager}. Run the test like this:
*
@@ -634,8 +637,17 @@ public class ContactDirectoryManagerTest extends BaseContactsProvider2Test {
return;
}
+ try {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .executeShellCommand("am wait-for-broadcast-idle");
+ Thread.sleep(1000); // wait for the system
+ } catch (Exception ignored) { }
+
// If installed, getDirectoryProviderPackages() should return it.
- assertTrue(ContactDirectoryManager.getDirectoryProviderPackages(pm).contains(googleSync));
+ Set<String> dirProviderPackages = ContactDirectoryManager.getDirectoryProviderPackages(pm);
+ assertTrue(googleSync + " package not found in the list of directory provider packages: "
+ + Arrays.toString(dirProviderPackages.toArray()),
+ dirProviderPackages.contains(googleSync));
}
protected PackageInfo createProviderPackage(String packageName, String authority) {
diff --git a/tests/src/com/android/providers/contacts/ContactsActor.java b/tests/src/com/android/providers/contacts/ContactsActor.java
index e3c606e2..0d7d9b3b 100644
--- a/tests/src/com/android/providers/contacts/ContactsActor.java
+++ b/tests/src/com/android/providers/contacts/ContactsActor.java
@@ -16,6 +16,10 @@
package com.android.providers.contacts;
+import static android.content.pm.UserProperties.SHOW_IN_LAUNCHER_WITH_PARENT;
+import static com.android.providers.contacts.ContactsActor.MockUserManager.CLONE_PROFILE_USER;
+import static com.android.providers.contacts.ContactsActor.MockUserManager.PRIMARY_USER;
+
import static org.mockito.Mockito.when;
import android.accounts.Account;
@@ -25,6 +29,7 @@ import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OnAccountsUpdateListener;
import android.accounts.OperationCanceledException;
+import android.annotation.NonNull;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -37,6 +42,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.UserInfo;
+import android.content.pm.UserProperties;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
@@ -170,6 +176,8 @@ public class ContactsActor {
public static final UserInfo CORP_USER = createUserInfo("corp", 10, 0,
UserInfo.FLAG_MANAGED_PROFILE);
public static final UserInfo SECONDARY_USER = createUserInfo("2nd", 11, 11, 0);
+ public static final UserInfo CLONE_PROFILE_USER = createUserInfo("clone", 12, 0,
+ UserInfo.FLAG_PROFILE);
/** "My" user. Set it to change the current user. */
public int myUser = DEFAULT_USER_ID;
@@ -253,6 +261,18 @@ public class ContactsActor {
public boolean isUserRunning(int userId) {
return true;
}
+
+ @Override
+ public UserProperties getUserProperties(@NonNull UserHandle userHandle) {
+ if (CLONE_PROFILE_USER.getUserHandle().equals(userHandle)) {
+ return new UserProperties.Builder()
+ .setUseParentsContacts(true)
+ .setShowInLauncher(SHOW_IN_LAUNCHER_WITH_PARENT)
+ .setStartWithParent(true)
+ .build();
+ }
+ return new UserProperties.Builder().build();
+ }
}
private MockTelephonyManager mMockTelephonyManager;
@@ -411,6 +431,15 @@ public class ContactsActor {
}
@Override
+ public UserHandle getUser() {
+ if (mockUserManager != null &&
+ mockUserManager.getProcessUserId() == CLONE_PROFILE_USER.id) {
+ return CLONE_PROFILE_USER.getUserHandle();
+ }
+ return PRIMARY_USER.getUserHandle();
+ }
+
+ @Override
public void sendBroadcast(Intent intent, String receiverPermission) {
// Ignore.
}
diff --git a/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
index a9420dda..62f17eab 100644
--- a/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
+++ b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
@@ -24,6 +24,7 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.os.Binder;
+import android.os.UserHandle;
import android.test.mock.MockPackageManager;
import java.util.ArrayList;
@@ -149,4 +150,15 @@ public class ContactsMockPackageManager extends MockPackageManager {
}
return ret;
}
+
+ @Override
+ public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, ResolveInfoFlags flags,
+ UserHandle user) {
+ return new ArrayList<>();
+ }
+
+ @Override
+ public int getPackageUid(String packageName, int flags) throws NameNotFoundException {
+ return 123;
+ }
}
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
index 09ea19fc..69ae0fb2 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -8163,50 +8163,6 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test {
assertEquals("default", helper.getProperty("existent1", "default"));
}
- private class VCardTestUriCreator {
- private String mLookup1;
- private String mLookup2;
-
- public VCardTestUriCreator(String lookup1, String lookup2) {
- super();
- mLookup1 = lookup1;
- mLookup2 = lookup2;
- }
-
- public Uri getUri1() {
- return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup1);
- }
-
- public Uri getUri2() {
- return Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, mLookup2);
- }
-
- public Uri getCombinedUri() {
- return Uri.withAppendedPath(Contacts.CONTENT_MULTI_VCARD_URI,
- Uri.encode(mLookup1 + ":" + mLookup2));
- }
- }
-
- private VCardTestUriCreator createVCardTestContacts() {
- final long rawContactId1 = RawContactUtil.createRawContact(mResolver, mAccount,
- RawContacts.SOURCE_ID, "4:12");
- DataUtil.insertStructuredName(mResolver, rawContactId1, "John", "Doe");
-
- final long rawContactId2 = RawContactUtil.createRawContact(mResolver, mAccount,
- RawContacts.SOURCE_ID, "3:4%121");
- DataUtil.insertStructuredName(mResolver, rawContactId2, "Jane", "Doh");
-
- final long contactId1 = queryContactId(rawContactId1);
- final long contactId2 = queryContactId(rawContactId2);
- final Uri contact1Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId1);
- final Uri contact2Uri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId2);
- final String lookup1 =
- Uri.encode(Contacts.getLookupUri(mResolver, contact1Uri).getPathSegments().get(2));
- final String lookup2 =
- Uri.encode(Contacts.getLookupUri(mResolver, contact2Uri).getPathSegments().get(2));
- return new VCardTestUriCreator(lookup1, lookup2);
- }
-
public void testQueryMultiVCard() {
// No need to create any contacts here, because the query for multiple vcards
// does not go into the database at all
@@ -9688,27 +9644,6 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test {
return c;
}
- private String readToEnd(FileInputStream inputStream) {
- try {
- System.out.println("DECLARED INPUT STREAM LENGTH: " + inputStream.available());
- int ch;
- StringBuilder stringBuilder = new StringBuilder();
- int index = 0;
- while (true) {
- ch = inputStream.read();
- System.out.println("READ CHARACTER: " + index + " " + ch);
- if (ch == -1) {
- break;
- }
- stringBuilder.append((char)ch);
- index++;
- }
- return stringBuilder.toString();
- } catch (IOException e) {
- return null;
- }
- }
-
private void assertQueryParameter(String uriString, String parameter, String expectedValue) {
assertEquals(expectedValue, ContactsProvider2.getQueryParameter(
Uri.parse(uriString), parameter));
@@ -9908,24 +9843,4 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test {
}
return false;
}
-
-
- /**
- * Asserts the equality of two Uri objects, ignoring the order of the query parameters.
- */
- public static void assertUriEquals(Uri expected, Uri actual) {
- assertEquals(expected.getScheme(), actual.getScheme());
- assertEquals(expected.getAuthority(), actual.getAuthority());
- assertEquals(expected.getPath(), actual.getPath());
- assertEquals(expected.getFragment(), actual.getFragment());
- Set<String> expectedParameterNames = expected.getQueryParameterNames();
- Set<String> actualParameterNames = actual.getQueryParameterNames();
- assertEquals(expectedParameterNames.size(), actualParameterNames.size());
- assertTrue(expectedParameterNames.containsAll(actualParameterNames));
- for (String parameterName : expectedParameterNames) {
- assertEquals(expected.getQueryParameter(parameterName),
- actual.getQueryParameter(parameterName));
- }
-
- }
}
diff --git a/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java b/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java
index c2ab74fc..ca8cb669 100644
--- a/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java
+++ b/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java
@@ -32,7 +32,8 @@ import java.util.Locale;
public class SynchronousContactsProvider2 extends ContactsProvider2 {
public static final String READ_ONLY_ACCOUNT_TYPE = "ro";
- private static Boolean sDataWiped = false;
+ private static final Object sDataWipedLock = new Object();
+ private static boolean sDataWiped = false;
private static ContactsDatabaseHelper sDbHelper;
private Account mAccount;
private boolean mNetworkNotified;
@@ -93,7 +94,7 @@ public class SynchronousContactsProvider2 extends ContactsProvider2 {
@Override
public boolean onCreate() {
boolean created = super.onCreate();
- synchronized (sDataWiped) {
+ synchronized (sDataWipedLock) {
if (!sDataWiped) {
sDataWiped = true;
wipeData();
@@ -178,6 +179,11 @@ public class SynchronousContactsProvider2 extends ContactsProvider2 {
}
@Override
+ protected boolean isContactSharingEnabledForCloneProfile() {
+ return true;
+ }
+
+ @Override
public boolean isWritableAccountWithDataSet(String accountType) {
return !READ_ONLY_ACCOUNT_TYPE.equals(accountType);
}
diff --git a/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java b/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java
index 2e5241fb..5aedd8d0 100644
--- a/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java
+++ b/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java
@@ -17,6 +17,7 @@ package com.android.providers.contacts.enterprise;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.UserHandle;
@@ -31,6 +32,9 @@ import org.mockito.Matchers;
import java.util.Arrays;
import java.util.List;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -49,6 +53,7 @@ public class EnterprisePolicyGuardTest extends FixedAndroidTestCase {
private static final String CONTACT_EMAIL = "david.green@android.com";
private static final String CONTACT_PHONE = "+1234567890";
private static final long DIRECTORY_ID = Directory.ENTERPRISE_DEFAULT;
+ private static final String CALLING_PACKAGE = "package";
private static final Uri URI_CONTACTS_ID_PHOTO =
Uri.parse("content://com.android.contacts/contacts/" + CONTACT_ID + "/photo");
@@ -179,6 +184,32 @@ public class EnterprisePolicyGuardTest extends FixedAndroidTestCase {
checkCrossProfile(guard, URI_CONTACTS_ID_PHOTO, false);
checkCrossProfile(guard, URI_CONTACTS_ID_DISPLAY_PHOTO, false);
checkCrossProfile(guard, URI_OTHER, false);
+
+ // ManagedProfile is paused
+ context = getMockContext(true, true, false);
+ guard = new EnterprisePolicyGuardTestable(context, true);
+ checkCrossProfile(guard, appendRemoteDirectoryId(URI_PHONE_LOOKUP), false);
+ checkCrossProfile(guard, appendRemoteDirectoryId(URI_EMAILS_LOOKUP), false);
+ checkCrossProfile(guard, appendRemoteDirectoryId(URI_CONTACTS_FILTER), false);
+ checkCrossProfile(guard, appendRemoteDirectoryId(URI_PHONES_FILTER), false);
+ checkCrossProfile(guard, appendRemoteDirectoryId(URI_CALLABLES_FILTER), false);
+ checkCrossProfile(guard, appendRemoteDirectoryId(URI_EMAILS_FILTER), false);
+ checkCrossProfile(guard, URI_DIRECTORY_FILE, false);
+
+ // Always allow uri with no directory support.
+ 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);
+
+ // Always allow uri with no remote directory id.
+ 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);
}
public void testCrossProfile_userSettingOff() {
@@ -210,6 +241,7 @@ public class EnterprisePolicyGuardTest extends FixedAndroidTestCase {
checkCrossProfile(guard, URI_EMAILS_FILTER, true);
}
+
private static Uri appendRemoteDirectoryId(Uri uri) {
return appendDirectoryId(uri, REMOTE_DIRECTORY_ID);
}
@@ -231,13 +263,13 @@ public class EnterprisePolicyGuardTest extends FixedAndroidTestCase {
}
}
- private static void checkCrossProfile(EnterprisePolicyGuard guard, Uri uri, boolean expected) {
+ private void checkCrossProfile(EnterprisePolicyGuard guard, Uri uri, boolean expected) {
if (expected) {
assertTrue("Expected true but got false for uri: " + uri,
- guard.isCrossProfileAllowed(uri));
+ guard.isCrossProfileAllowed(uri, CALLING_PACKAGE));
} else {
assertFalse("Expected false but got true for uri: " + uri,
- guard.isCrossProfileAllowed(uri));
+ guard.isCrossProfileAllowed(uri, CALLING_PACKAGE));
}
}
@@ -256,11 +288,16 @@ public class EnterprisePolicyGuardTest extends FixedAndroidTestCase {
private Context getMockContext(boolean isCallerIdEnabled, boolean isContactsSearchEnabled) {
+ return getMockContext(isCallerIdEnabled, isContactsSearchEnabled, true);
+ }
+
+ private Context getMockContext(boolean isCallerIdEnabled, boolean isContactsSearchEnabled,
+ boolean isManagedProfileEnabled) {
DevicePolicyManager mockDpm = mock(DevicePolicyManager.class);
- when(mockDpm.getCrossProfileCallerIdDisabled(Matchers.<UserHandle>any()))
- .thenReturn(!isCallerIdEnabled);
- when(mockDpm.getCrossProfileContactsSearchDisabled(Matchers.<UserHandle>any()))
- .thenReturn(!isContactsSearchEnabled);
+ when(mockDpm.hasManagedProfileCallerIdAccess(Matchers.any(),Matchers.any()))
+ .thenReturn(isCallerIdEnabled);
+ when(mockDpm.hasManagedProfileContactsAccess(Matchers.any(),Matchers.any()))
+ .thenReturn(isContactsSearchEnabled);
List<UserInfo> userInfos = MANAGED_USERINFO_LIST;
UserManager mockUm = mock(UserManager.class);
@@ -268,8 +305,14 @@ public class EnterprisePolicyGuardTest extends FixedAndroidTestCase {
when(mockUm.getUsers()).thenReturn(userInfos);
when(mockUm.getProfiles(Matchers.anyInt())).thenReturn(userInfos);
when(mockUm.getProfileParent(WORK_USER_ID)).thenReturn(CURRENT_USER_INFO);
+ when(mockUm.isQuietModeEnabled(UserHandle.of(WORK_USER_ID)))
+ .thenReturn(!isManagedProfileEnabled);
- Context mockContext = new TestMockContext(getContext(), mockDpm, mockUm);
+ PackageManager mockPm = mock(PackageManager.class);
+ when(mockPm.checkPermission(INTERACT_ACROSS_USERS, CALLING_PACKAGE))
+ .thenReturn(PERMISSION_GRANTED);
+
+ Context mockContext = new TestMockContext(getContext(), mockDpm, mockUm, mockPm);
return mockContext;
}
@@ -278,11 +321,19 @@ public class EnterprisePolicyGuardTest extends FixedAndroidTestCase {
private Context mRealContext;
private DevicePolicyManager mDpm;
private UserManager mUm;
+ private PackageManager mPm;
- public TestMockContext(Context realContext, DevicePolicyManager dpm, UserManager um) {
+ public TestMockContext(
+ Context realContext, DevicePolicyManager dpm, UserManager um, PackageManager pm) {
mRealContext = realContext;
mDpm = dpm;
mUm = um;
+ mPm = pm;
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return mPm;
}
public Object getSystemService(String name) {
diff --git a/tests/src/com/android/providers/contacts/util/UserUtilsTest.java b/tests/src/com/android/providers/contacts/util/UserUtilsTest.java
index 93613cf5..c672697a 100644
--- a/tests/src/com/android/providers/contacts/util/UserUtilsTest.java
+++ b/tests/src/com/android/providers/contacts/util/UserUtilsTest.java
@@ -18,6 +18,7 @@ package com.android.providers.contacts.util;
import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
import android.content.Context;
+import android.os.UserHandle;
import android.provider.ContactsContract;
import android.test.suitebuilder.annotation.SmallTest;
@@ -77,5 +78,82 @@ public class UserUtilsTest extends FixedAndroidTestCase {
um.myUser = MockUserManager.SECONDARY_USER.id;
assertEquals(-1, UserUtils.getCorpUserId(c));
+
+ // Primary + clone + corp
+ um.setUsers(MockUserManager.PRIMARY_USER, MockUserManager.CLONE_PROFILE_USER,
+ MockUserManager.CORP_USER);
+
+ um.myUser = MockUserManager.PRIMARY_USER.id;
+ assertEquals(MockUserManager.CORP_USER.id, UserUtils.getCorpUserId(c));
+
+ um.myUser = MockUserManager.CLONE_PROFILE_USER.id;
+ assertEquals(-1, UserUtils.getCorpUserId(c));
+
+ um.myUser = MockUserManager.CORP_USER.id;
+ assertEquals(-1, UserUtils.getCorpUserId(c));
+ }
+
+ public void testShouldUseParentsContacts() {
+ final Context c = mActor.getProviderContext();
+ final MockUserManager um = mActor.mockUserManager;
+
+ um.setUsers(MockUserManager.PRIMARY_USER, MockUserManager.SECONDARY_USER,
+ MockUserManager.CLONE_PROFILE_USER, MockUserManager.CORP_USER);
+
+ um.myUser = MockUserManager.PRIMARY_USER.id;
+ assertFalse(UserUtils.shouldUseParentsContacts(c));
+ assertFalse(UserUtils.shouldUseParentsContacts(c,
+ MockUserManager.PRIMARY_USER.getUserHandle()));
+
+ um.myUser = MockUserManager.SECONDARY_USER.id;
+ assertFalse(UserUtils.shouldUseParentsContacts(c));
+ assertFalse(UserUtils.shouldUseParentsContacts(c,
+ MockUserManager.SECONDARY_USER.getUserHandle()));
+
+ um.myUser = MockUserManager.CORP_USER.id;
+ assertFalse(UserUtils.shouldUseParentsContacts(c));
+ assertFalse(UserUtils.shouldUseParentsContacts(c,
+ MockUserManager.CORP_USER.getUserHandle()));
+
+ um.myUser = MockUserManager.CLONE_PROFILE_USER.id;
+ assertTrue(UserUtils.shouldUseParentsContacts(c));
+ assertTrue(UserUtils.shouldUseParentsContacts(c,
+ MockUserManager.CLONE_PROFILE_USER.getUserHandle()));
+
+ }
+
+ public void testIsParentUser() {
+ final Context c = mActor.getProviderContext();
+ final MockUserManager um = mActor.mockUserManager;
+ um.setUsers(MockUserManager.PRIMARY_USER, MockUserManager.SECONDARY_USER,
+ MockUserManager.CLONE_PROFILE_USER, MockUserManager.CORP_USER);
+
+ UserHandle primaryProfileUserHandle = MockUserManager.PRIMARY_USER.getUserHandle();
+ UserHandle cloneUserHandle = MockUserManager.CLONE_PROFILE_USER.getUserHandle();
+ UserHandle corpUserHandle = MockUserManager.CORP_USER.getUserHandle();
+
+ assertTrue(UserUtils.isParentUser(c, primaryProfileUserHandle, cloneUserHandle));
+ assertTrue(UserUtils.isParentUser(c, primaryProfileUserHandle, corpUserHandle));
+ assertFalse(UserUtils.isParentUser(c, primaryProfileUserHandle, primaryProfileUserHandle));
+ assertFalse(UserUtils.isParentUser(c, cloneUserHandle, cloneUserHandle));
+ assertFalse(UserUtils.isParentUser(c, cloneUserHandle, primaryProfileUserHandle));
+ assertFalse(UserUtils.isParentUser(c, corpUserHandle, primaryProfileUserHandle));
+ }
+
+ public void testGetProfileParent() {
+ final Context c = mActor.getProviderContext();
+ final MockUserManager um = mActor.mockUserManager;
+
+ um.setUsers(MockUserManager.PRIMARY_USER, MockUserManager.SECONDARY_USER,
+ MockUserManager.CLONE_PROFILE_USER, MockUserManager.CORP_USER);
+
+ um.myUser = MockUserManager.PRIMARY_USER.id;
+ assertNull(UserUtils.getProfileParentUser(c));
+
+ um.myUser = MockUserManager.CLONE_PROFILE_USER.id;
+ assertEquals(MockUserManager.PRIMARY_USER, UserUtils.getProfileParentUser(c));
+
+ um.myUser = MockUserManager.CORP_USER.id;
+ assertEquals(MockUserManager.PRIMARY_USER, UserUtils.getProfileParentUser(c));
}
}