Merge "Add phone numbers to NotificationRecord from a cached contacts lookup" into tm-qpr-dev
This commit is contained in:
@@ -131,6 +131,17 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For tests: just do the setting of various local variables without actually doing work
|
||||||
|
@VisibleForTesting
|
||||||
|
protected void initForTests(Context context, NotificationUsageStats usageStats,
|
||||||
|
LruCache peopleCache) {
|
||||||
|
mUserToContextMap = new ArrayMap<>();
|
||||||
|
mBaseContext = context;
|
||||||
|
mUsageStats = usageStats;
|
||||||
|
mPeopleCache = peopleCache;
|
||||||
|
mEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
public RankingReconsideration process(NotificationRecord record) {
|
public RankingReconsideration process(NotificationRecord record) {
|
||||||
if (!mEnabled) {
|
if (!mEnabled) {
|
||||||
if (VERBOSE) Slog.i(TAG, "disabled");
|
if (VERBOSE) Slog.i(TAG, "disabled");
|
||||||
@@ -179,7 +190,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
|
|||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
final PeopleRankingReconsideration prr =
|
final PeopleRankingReconsideration prr =
|
||||||
validatePeople(context, key, extras, null, affinityOut);
|
validatePeople(context, key, extras, null, affinityOut, null);
|
||||||
float affinity = affinityOut[0];
|
float affinity = affinityOut[0];
|
||||||
|
|
||||||
if (prr != null) {
|
if (prr != null) {
|
||||||
@@ -224,15 +235,21 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RankingReconsideration validatePeople(Context context,
|
@VisibleForTesting
|
||||||
|
protected RankingReconsideration validatePeople(Context context,
|
||||||
final NotificationRecord record) {
|
final NotificationRecord record) {
|
||||||
final String key = record.getKey();
|
final String key = record.getKey();
|
||||||
final Bundle extras = record.getNotification().extras;
|
final Bundle extras = record.getNotification().extras;
|
||||||
final float[] affinityOut = new float[1];
|
final float[] affinityOut = new float[1];
|
||||||
|
ArraySet<String> phoneNumbersOut = new ArraySet<>();
|
||||||
final PeopleRankingReconsideration rr =
|
final PeopleRankingReconsideration rr =
|
||||||
validatePeople(context, key, extras, record.getPeopleOverride(), affinityOut);
|
validatePeople(context, key, extras, record.getPeopleOverride(), affinityOut,
|
||||||
|
phoneNumbersOut);
|
||||||
final float affinity = affinityOut[0];
|
final float affinity = affinityOut[0];
|
||||||
record.setContactAffinity(affinity);
|
record.setContactAffinity(affinity);
|
||||||
|
if (phoneNumbersOut.size() > 0) {
|
||||||
|
record.mergePhoneNumbers(phoneNumbersOut);
|
||||||
|
}
|
||||||
if (rr == null) {
|
if (rr == null) {
|
||||||
mUsageStats.registerPeopleAffinity(record, affinity > NONE, affinity == STARRED_CONTACT,
|
mUsageStats.registerPeopleAffinity(record, affinity > NONE, affinity == STARRED_CONTACT,
|
||||||
true /* cached */);
|
true /* cached */);
|
||||||
@@ -243,7 +260,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PeopleRankingReconsideration validatePeople(Context context, String key, Bundle extras,
|
private PeopleRankingReconsideration validatePeople(Context context, String key, Bundle extras,
|
||||||
List<String> peopleOverride, float[] affinityOut) {
|
List<String> peopleOverride, float[] affinityOut, ArraySet<String> phoneNumbersOut) {
|
||||||
float affinity = NONE;
|
float affinity = NONE;
|
||||||
if (extras == null) {
|
if (extras == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -270,6 +287,15 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
|
|||||||
}
|
}
|
||||||
if (lookupResult != null) {
|
if (lookupResult != null) {
|
||||||
affinity = Math.max(affinity, lookupResult.getAffinity());
|
affinity = Math.max(affinity, lookupResult.getAffinity());
|
||||||
|
|
||||||
|
// add all phone numbers associated with this lookup result, if they exist
|
||||||
|
// and if requested
|
||||||
|
if (phoneNumbersOut != null) {
|
||||||
|
ArraySet<String> phoneNumbers = lookupResult.getPhoneNumbers();
|
||||||
|
if (phoneNumbers != null && phoneNumbers.size() > 0) {
|
||||||
|
phoneNumbersOut.addAll(phoneNumbers);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (++personIdx == MAX_PEOPLE) {
|
if (++personIdx == MAX_PEOPLE) {
|
||||||
@@ -289,7 +315,8 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
|
|||||||
return new PeopleRankingReconsideration(context, key, pendingLookups);
|
return new PeopleRankingReconsideration(context, key, pendingLookups);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getCacheKey(int userId, String handle) {
|
@VisibleForTesting
|
||||||
|
protected static String getCacheKey(int userId, String handle) {
|
||||||
return Integer.toString(userId) + ":" + handle;
|
return Integer.toString(userId) + ":" + handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,7 +512,8 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LookupResult {
|
@VisibleForTesting
|
||||||
|
protected static class LookupResult {
|
||||||
private static final long CONTACT_REFRESH_MILLIS = 60 * 60 * 1000; // 1hr
|
private static final long CONTACT_REFRESH_MILLIS = 60 * 60 * 1000; // 1hr
|
||||||
|
|
||||||
private final long mExpireMillis;
|
private final long mExpireMillis;
|
||||||
@@ -574,7 +602,8 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
|
|||||||
return mPhoneNumbers;
|
return mPhoneNumbers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isExpired() {
|
@VisibleForTesting
|
||||||
|
protected boolean isExpired() {
|
||||||
return mExpireMillis < System.currentTimeMillis();
|
return mExpireMillis < System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ package com.android.server.notification;
|
|||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.contains;
|
import static org.mockito.ArgumentMatchers.contains;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
@@ -30,6 +32,7 @@ import static org.mockito.Mockito.verify;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
import android.app.Person;
|
import android.app.Person;
|
||||||
import android.content.ContentProvider;
|
import android.content.ContentProvider;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
@@ -39,8 +42,11 @@ import android.net.Uri;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
import android.util.LruCache;
|
||||||
|
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
@@ -323,6 +329,69 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
|||||||
isNull()); // sort order
|
isNull()); // sort order
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidatePeople_needsLookupWhenNoCache() {
|
||||||
|
final Context mockContext = mock(Context.class);
|
||||||
|
final ContentResolver mockContentResolver = mock(ContentResolver.class);
|
||||||
|
when(mockContext.getContentResolver()).thenReturn(mockContentResolver);
|
||||||
|
final NotificationUsageStats mockNotificationUsageStats =
|
||||||
|
mock(NotificationUsageStats.class);
|
||||||
|
|
||||||
|
// Create validator with empty cache
|
||||||
|
ValidateNotificationPeople vnp = new ValidateNotificationPeople();
|
||||||
|
LruCache cache = new LruCache<String, ValidateNotificationPeople.LookupResult>(5);
|
||||||
|
vnp.initForTests(mockContext, mockNotificationUsageStats, cache);
|
||||||
|
|
||||||
|
NotificationRecord record = getNotificationRecord();
|
||||||
|
String[] callNumber = new String[]{"tel:12345678910"};
|
||||||
|
setNotificationPeople(record, callNumber);
|
||||||
|
|
||||||
|
// Returned ranking reconsideration not null indicates that there is a lookup to be done
|
||||||
|
RankingReconsideration rr = vnp.validatePeople(mockContext, record);
|
||||||
|
assertNotNull(rr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidatePeople_noLookupWhenCached_andPopulatesContactInfo() {
|
||||||
|
final Context mockContext = mock(Context.class);
|
||||||
|
final ContentResolver mockContentResolver = mock(ContentResolver.class);
|
||||||
|
when(mockContext.getContentResolver()).thenReturn(mockContentResolver);
|
||||||
|
when(mockContext.getUserId()).thenReturn(1);
|
||||||
|
final NotificationUsageStats mockNotificationUsageStats =
|
||||||
|
mock(NotificationUsageStats.class);
|
||||||
|
|
||||||
|
// Information to be passed in & returned from the lookup result
|
||||||
|
String lookup = "lookup:contactinfohere";
|
||||||
|
String lookupTel = "16175551234";
|
||||||
|
float affinity = 0.7f;
|
||||||
|
|
||||||
|
// Create a fake LookupResult for the data we'll pass in
|
||||||
|
LruCache cache = new LruCache<String, ValidateNotificationPeople.LookupResult>(5);
|
||||||
|
ValidateNotificationPeople.LookupResult lr =
|
||||||
|
mock(ValidateNotificationPeople.LookupResult.class);
|
||||||
|
when(lr.getAffinity()).thenReturn(affinity);
|
||||||
|
when(lr.getPhoneNumbers()).thenReturn(new ArraySet<>(new String[]{lookupTel}));
|
||||||
|
when(lr.isExpired()).thenReturn(false);
|
||||||
|
cache.put(ValidateNotificationPeople.getCacheKey(1, lookup), lr);
|
||||||
|
|
||||||
|
// Create validator with the established cache
|
||||||
|
ValidateNotificationPeople vnp = new ValidateNotificationPeople();
|
||||||
|
vnp.initForTests(mockContext, mockNotificationUsageStats, cache);
|
||||||
|
|
||||||
|
NotificationRecord record = getNotificationRecord();
|
||||||
|
String[] peopleInfo = new String[]{lookup};
|
||||||
|
setNotificationPeople(record, peopleInfo);
|
||||||
|
|
||||||
|
// Returned ranking reconsideration null indicates that there is no pending work to be done
|
||||||
|
RankingReconsideration rr = vnp.validatePeople(mockContext, record);
|
||||||
|
assertNull(rr);
|
||||||
|
|
||||||
|
// Confirm that the affinity & phone number made it into our record
|
||||||
|
assertEquals(affinity, record.getContactAffinity(), 1e-8);
|
||||||
|
assertNotNull(record.getPhoneNumbers());
|
||||||
|
assertTrue(record.getPhoneNumbers().contains(lookupTel));
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a cursor that points to one item of Contacts data with the specified
|
// Creates a cursor that points to one item of Contacts data with the specified
|
||||||
// columns.
|
// columns.
|
||||||
private Cursor makeMockCursor(int id, String lookupKey, int starred, int hasPhone) {
|
private Cursor makeMockCursor(int id, String lookupKey, int starred, int hasPhone) {
|
||||||
@@ -365,4 +434,17 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
|||||||
String resultString = Arrays.toString(result);
|
String resultString = Arrays.toString(result);
|
||||||
assertEquals(message + ": arrays differ", expectedString, resultString);
|
assertEquals(message + ": arrays differ", expectedString, resultString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NotificationRecord getNotificationRecord() {
|
||||||
|
StatusBarNotification sbn = mock(StatusBarNotification.class);
|
||||||
|
Notification notification = mock(Notification.class);
|
||||||
|
when(sbn.getNotification()).thenReturn(notification);
|
||||||
|
return new NotificationRecord(mContext, sbn, mock(NotificationChannel.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setNotificationPeople(NotificationRecord r, String[] people) {
|
||||||
|
Bundle extras = new Bundle();
|
||||||
|
extras.putObject(Notification.EXTRA_PEOPLE_LIST, people);
|
||||||
|
r.getSbn().getNotification().extras = extras;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user