Merge "Make DnD check work profile contacts" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-03-19 17:33:18 +00:00
committed by Android (Google) Code Review
3 changed files with 139 additions and 10 deletions

View File

@@ -57,6 +57,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
@@ -2210,6 +2211,28 @@ public final class ContactsContract {
public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) {
return openContactPhotoInputStream(cr, contactUri, false);
}
/**
* Creates and returns a corp lookup URI from the given enterprise lookup URI by removing
* {@link #ENTERPRISE_CONTACT_LOOKUP_PREFIX} from the key. Returns {@code null} if the given
* URI is not an enterprise lookup URI.
*
* @hide
*/
@Nullable
public static Uri createCorpLookupUriFromEnterpriseLookupUri(
@NonNull Uri enterpriseLookupUri) {
final List<String> pathSegments = enterpriseLookupUri.getPathSegments();
if (pathSegments == null || pathSegments.size() <= 2) {
return null;
}
final String key = pathSegments.get(2);
if (TextUtils.isEmpty(key) || !key.startsWith(ENTERPRISE_CONTACT_LOOKUP_PREFIX)) {
return null;
}
final String actualKey = key.substring(ENTERPRISE_CONTACT_LOOKUP_PREFIX.length());
return Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, actualKey);
}
}
/**

View File

@@ -19,6 +19,7 @@ package com.android.server.notification;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.Person;
import android.content.ContentProvider;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
@@ -28,6 +29,7 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.Settings;
@@ -38,6 +40,8 @@ import android.util.Log;
import android.util.LruCache;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import libcore.util.EmptyArray;
import java.util.ArrayList;
@@ -392,26 +396,57 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
return searchContacts(context, numberUri);
}
private LookupResult searchContacts(Context context, Uri lookupUri) {
@VisibleForTesting
LookupResult searchContacts(Context context, Uri lookupUri) {
LookupResult lookupResult = new LookupResult();
Cursor c = null;
try {
c = context.getContentResolver().query(lookupUri, LOOKUP_PROJECTION, null, null, null);
final Uri corpLookupUri =
ContactsContract.Contacts.createCorpLookupUriFromEnterpriseLookupUri(lookupUri);
if (corpLookupUri == null) {
addContacts(lookupResult, context, lookupUri);
} else {
addWorkContacts(lookupResult, context, corpLookupUri);
}
return lookupResult;
}
private void addWorkContacts(LookupResult lookupResult, Context context, Uri corpLookupUri) {
final int workUserId = findWorkUserId(context);
if (workUserId == -1) {
Slog.w(TAG, "Work profile user ID not found for work contact: " + corpLookupUri);
return;
}
final Uri corpLookupUriWithUserId =
ContentProvider.maybeAddUserId(corpLookupUri, workUserId);
addContacts(lookupResult, context, corpLookupUriWithUserId);
}
/** Returns the user ID of the managed profile or -1 if none is found. */
private int findWorkUserId(Context context) {
final UserManager userManager = context.getSystemService(UserManager.class);
final int[] profileIds =
userManager.getProfileIds(context.getUserId(), /* enabledOnly= */ true);
for (int profileId : profileIds) {
if (userManager.isManagedProfile(profileId)) {
return profileId;
}
}
return -1;
}
/** Modifies the given lookup result to add contacts found at the given URI. */
private void addContacts(LookupResult lookupResult, Context context, Uri uri) {
try (Cursor c = context.getContentResolver().query(
uri, LOOKUP_PROJECTION, null, null, null)) {
if (c == null) {
Slog.w(TAG, "Null cursor from contacts query.");
return lookupResult;
return;
}
while (c.moveToNext()) {
lookupResult.mergeContact(c);
}
} catch (Throwable t) {
Slog.w(TAG, "Problem getting content resolver or performing contacts query.", t);
} finally {
if (c != null) {
c.close();
}
}
return lookupResult;
}
private static class LookupResult {

View File

@@ -16,11 +16,23 @@
package com.android.server.notification;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Notification;
import android.app.Person;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserManager;
import android.provider.ContactsContract;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.SpannableString;
@@ -30,6 +42,7 @@ import com.android.server.UiServiceTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -169,6 +182,64 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
assertStringArrayEquals("testPeopleArrayList", expected, result);
}
@Test
public void testSearchContacts_workContact_queriesWorkContactProvider()
throws Exception {
final int personalUserId = 0;
final int workUserId = 12;
final int contactId = 12345;
final Context mockContext = mock(Context.class);
when(mockContext.getUserId()).thenReturn(personalUserId);
final UserManager mockUserManager = mock(UserManager.class);
when(mockContext.getSystemService(UserManager.class)).thenReturn(mockUserManager);
when(mockUserManager.getProfileIds(personalUserId, /* enabledOnly= */ true))
.thenReturn(new int[] {personalUserId, workUserId});
when(mockUserManager.isManagedProfile(workUserId)).thenReturn(true);
final ContentResolver mockContentResolver = mock(ContentResolver.class);
when(mockContext.getContentResolver()).thenReturn(mockContentResolver);
final Uri lookupUri = Uri.withAppendedPath(
ContactsContract.Contacts.CONTENT_LOOKUP_URI,
ContactsContract.Contacts.ENTERPRISE_CONTACT_LOOKUP_PREFIX + contactId);
new ValidateNotificationPeople().searchContacts(mockContext, lookupUri);
ArgumentCaptor<Uri> queryUri = ArgumentCaptor.forClass(Uri.class);
verify(mockContentResolver).query(
queryUri.capture(),
any(),
/* selection= */ isNull(),
/* selectionArgs= */ isNull(),
/* sortOrder= */ isNull());
assertEquals(workUserId, ContentProvider.getUserIdFromUri(queryUri.getValue()));
}
@Test
public void testSearchContacts_personalContact_queriesPersonalContactProvider()
throws Exception {
final int personalUserId = 0;
final int workUserId = 12;
final int contactId = 12345;
final Context mockContext = mock(Context.class);
when(mockContext.getUserId()).thenReturn(personalUserId);
final UserManager mockUserManager = mock(UserManager.class);
when(mockContext.getSystemService(UserManager.class)).thenReturn(mockUserManager);
final ContentResolver mockContentResolver = mock(ContentResolver.class);
when(mockContext.getContentResolver()).thenReturn(mockContentResolver);
final Uri lookupUri = Uri.withAppendedPath(
ContactsContract.Contacts.CONTENT_LOOKUP_URI, String.valueOf(contactId));
new ValidateNotificationPeople().searchContacts(mockContext, lookupUri);
ArgumentCaptor<Uri> queryUri = ArgumentCaptor.forClass(Uri.class);
verify(mockContentResolver).query(
queryUri.capture(),
any(),
/* selection= */ isNull(),
/* selectionArgs= */ isNull(),
/* sortOrder= */ isNull());
assertFalse(ContentProvider.uriHasUserId(queryUri.getValue()));
}
private void assertStringArrayEquals(String message, String[] expected, String[] result) {
String expectedString = Arrays.toString(expected);
String resultString = Arrays.toString(result);