Loading services/core/java/com/android/server/notification/ZenModeFiltering.java +51 −18 Original line number Diff line number Diff line Loading @@ -112,7 +112,7 @@ public class ZenModeFiltering { } if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { if (consolidatedPolicy.allowRepeatCallers() && REPEAT_CALLERS.isRepeat(context, extras)) { && REPEAT_CALLERS.isRepeat(context, extras, null)) { ZenLog.traceMatchesCallFilter(true, "repeat caller"); return true; } Loading Loading @@ -229,7 +229,8 @@ public class ZenModeFiltering { } if (isCall(record)) { if (policy.allowRepeatCallers() && REPEAT_CALLERS.isRepeat(mContext, extras(record))) { && REPEAT_CALLERS.isRepeat( mContext, extras(record), record.getPhoneNumbers())) { ZenLog.traceNotIntercepted(record, "repeatCaller"); return false; } Loading Loading @@ -350,6 +351,9 @@ public class ZenModeFiltering { private final ArrayMap<String, Long> mOtherCalls = new ArrayMap<>(); private int mThresholdMinutes; // Record all people URIs in the extras bundle as well as the provided phoneNumbers set // as callers. The phoneNumbers set is used to pass in any additional phone numbers // associated with the people URIs as separately retrieved from contacts. private synchronized void recordCall(Context context, Bundle extras, ArraySet<String> phoneNumbers) { setThresholdMinutes(context); Loading @@ -362,7 +366,13 @@ public class ZenModeFiltering { recordCallers(extraPeople, phoneNumbers, now); } private synchronized boolean isRepeat(Context context, Bundle extras) { // Determine whether any people in the provided extras bundle or phone number set is // a repeat caller. The extras bundle contains the people associated with a specific // notification, and will suffice for most callers; the phoneNumbers array may be used // to additionally check any specific phone numbers previously retrieved from contacts // associated with the people in the extras bundle. private synchronized boolean isRepeat(Context context, Bundle extras, ArraySet<String> phoneNumbers) { setThresholdMinutes(context); if (mThresholdMinutes <= 0 || extras == null) return false; final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras); Loading @@ -370,7 +380,7 @@ public class ZenModeFiltering { final long now = System.currentTimeMillis(); cleanUp(mTelCalls, now); cleanUp(mOtherCalls, now); return checkCallers(context, extraPeople); return checkCallers(context, extraPeople, phoneNumbers); } private synchronized void cleanUp(ArrayMap<String, Long> calls, long now) { Loading Loading @@ -433,16 +443,9 @@ public class ZenModeFiltering { } } private synchronized boolean checkCallers(Context context, String[] people) { // get the default country code for checking telephone numbers final String defaultCountryCode = context.getSystemService(TelephonyManager.class).getNetworkCountryIso(); for (int i = 0; i < people.length; i++) { String person = people[i]; if (person == null) continue; final Uri uri = Uri.parse(person); if ("tel".equals(uri.getScheme())) { String number = uri.getSchemeSpecificPart(); // helper function to check mTelCalls array for a number, and also check its decoded // version private synchronized boolean checkForNumber(String number, String defaultCountryCode) { if (mTelCalls.containsKey(number)) { // check directly via map first return true; Loading @@ -458,12 +461,42 @@ public class ZenModeFiltering { } } } return false; } // Check whether anyone in the provided array of people URIs or phone number set matches a // previously recorded phone call. private synchronized boolean checkCallers(Context context, String[] people, ArraySet<String> phoneNumbers) { // get the default country code for checking telephone numbers final String defaultCountryCode = context.getSystemService(TelephonyManager.class).getNetworkCountryIso(); for (int i = 0; i < people.length; i++) { String person = people[i]; if (person == null) continue; final Uri uri = Uri.parse(person); if ("tel".equals(uri.getScheme())) { String number = uri.getSchemeSpecificPart(); if (checkForNumber(number, defaultCountryCode)) { return true; } } else { if (mOtherCalls.containsKey(person)) { return true; } } } // also check any passed-in phone numbers if (phoneNumbers != null) { for (String num : phoneNumbers) { if (checkForNumber(num, defaultCountryCode)) { return true; } } } // no matches return false; } } Loading services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java +37 −5 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ public class ZenModeFilteringTest extends UiServiceTestCase { // Create a notification record with the people String array as the // bundled extras, and the numbers ArraySet as additional phone numbers. private NotificationRecord getRecordWithPeopleInfo(String[] people, private NotificationRecord getCallRecordWithPeopleInfo(String[] people, ArraySet<String> numbers) { // set up notification record NotificationRecord r = mock(NotificationRecord.class); Loading @@ -131,6 +131,8 @@ public class ZenModeFilteringTest extends UiServiceTestCase { when(sbn.getNotification()).thenReturn(notification); when(r.getSbn()).thenReturn(sbn); when(r.getPhoneNumbers()).thenReturn(numbers); when(r.getCriticality()).thenReturn(CriticalNotificationExtractor.NORMAL); when(r.isCategory(CATEGORY_CALL)).thenReturn(true); return r; } Loading Loading @@ -349,12 +351,42 @@ public class ZenModeFilteringTest extends UiServiceTestCase { assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r)); } @Test public void testRepeatCallers_checksPhoneNumbers() { // set up telephony manager behavior when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); // first, record a phone call from a telephone number String[] callNumber = new String[]{"tel:12345678910"}; mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(callNumber, null)); // set up policy to only allow repeat callers Policy policy = new Policy( PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE); // make sure that a record with the phone number in extras is correctly allowed through NotificationRecord r = getCallRecordWithPeopleInfo(callNumber, null); assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r)); // make sure that a record with the phone number in the phone numbers array is also // allowed through NotificationRecord r2 = getCallRecordWithPeopleInfo(new String[]{"some_contact_uri"}, new ArraySet<>(new String[]{"12345678910"})); assertFalse(mZenModeFiltering.shouldIntercept( ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r2)); // A record with the phone number in neither of the above should be intercepted NotificationRecord r3 = getCallRecordWithPeopleInfo(new String[]{"tel:10987654321"}, new ArraySet<>(new String[]{"15555555555"})); assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r3)); } @Test public void testMatchesCallFilter_repeatCallers_directMatch() { // after calls given an email with an exact string match, make sure that // matchesCallFilter returns the right thing String[] mailSource = new String[]{"mailto:hello.world"}; mZenModeFiltering.recordCall(getRecordWithPeopleInfo(mailSource, null)); mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(mailSource, null)); // set up policy to only allow repeat callers Policy policy = new Policy( Loading @@ -377,7 +409,7 @@ public class ZenModeFilteringTest extends UiServiceTestCase { when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); String[] telSource = new String[]{"tel:+1-617-555-1212"}; mZenModeFiltering.recordCall(getRecordWithPeopleInfo(telSource, null)); mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(telSource, null)); // set up policy to only allow repeat callers Policy policy = new Policy( Loading Loading @@ -421,7 +453,7 @@ public class ZenModeFilteringTest extends UiServiceTestCase { when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); String[] telSource = new String[]{"tel:%2B16175551212"}; mZenModeFiltering.recordCall(getRecordWithPeopleInfo(telSource, null)); mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(telSource, null)); // set up policy to only allow repeat callers Policy policy = new Policy( Loading Loading @@ -468,7 +500,7 @@ public class ZenModeFilteringTest extends UiServiceTestCase { String[] contactSource = new String[]{"content://contacts/lookup/uri-here"}; ArraySet<String> contactNumbers = new ArraySet<>( new String[]{"1-617-555-1212", "1-617-555-3434"}); NotificationRecord record = getRecordWithPeopleInfo(contactSource, contactNumbers); NotificationRecord record = getCallRecordWithPeopleInfo(contactSource, contactNumbers); record.mergePhoneNumbers(contactNumbers); mZenModeFiltering.recordCall(record); Loading Loading
services/core/java/com/android/server/notification/ZenModeFiltering.java +51 −18 Original line number Diff line number Diff line Loading @@ -112,7 +112,7 @@ public class ZenModeFiltering { } if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { if (consolidatedPolicy.allowRepeatCallers() && REPEAT_CALLERS.isRepeat(context, extras)) { && REPEAT_CALLERS.isRepeat(context, extras, null)) { ZenLog.traceMatchesCallFilter(true, "repeat caller"); return true; } Loading Loading @@ -229,7 +229,8 @@ public class ZenModeFiltering { } if (isCall(record)) { if (policy.allowRepeatCallers() && REPEAT_CALLERS.isRepeat(mContext, extras(record))) { && REPEAT_CALLERS.isRepeat( mContext, extras(record), record.getPhoneNumbers())) { ZenLog.traceNotIntercepted(record, "repeatCaller"); return false; } Loading Loading @@ -350,6 +351,9 @@ public class ZenModeFiltering { private final ArrayMap<String, Long> mOtherCalls = new ArrayMap<>(); private int mThresholdMinutes; // Record all people URIs in the extras bundle as well as the provided phoneNumbers set // as callers. The phoneNumbers set is used to pass in any additional phone numbers // associated with the people URIs as separately retrieved from contacts. private synchronized void recordCall(Context context, Bundle extras, ArraySet<String> phoneNumbers) { setThresholdMinutes(context); Loading @@ -362,7 +366,13 @@ public class ZenModeFiltering { recordCallers(extraPeople, phoneNumbers, now); } private synchronized boolean isRepeat(Context context, Bundle extras) { // Determine whether any people in the provided extras bundle or phone number set is // a repeat caller. The extras bundle contains the people associated with a specific // notification, and will suffice for most callers; the phoneNumbers array may be used // to additionally check any specific phone numbers previously retrieved from contacts // associated with the people in the extras bundle. private synchronized boolean isRepeat(Context context, Bundle extras, ArraySet<String> phoneNumbers) { setThresholdMinutes(context); if (mThresholdMinutes <= 0 || extras == null) return false; final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras); Loading @@ -370,7 +380,7 @@ public class ZenModeFiltering { final long now = System.currentTimeMillis(); cleanUp(mTelCalls, now); cleanUp(mOtherCalls, now); return checkCallers(context, extraPeople); return checkCallers(context, extraPeople, phoneNumbers); } private synchronized void cleanUp(ArrayMap<String, Long> calls, long now) { Loading Loading @@ -433,16 +443,9 @@ public class ZenModeFiltering { } } private synchronized boolean checkCallers(Context context, String[] people) { // get the default country code for checking telephone numbers final String defaultCountryCode = context.getSystemService(TelephonyManager.class).getNetworkCountryIso(); for (int i = 0; i < people.length; i++) { String person = people[i]; if (person == null) continue; final Uri uri = Uri.parse(person); if ("tel".equals(uri.getScheme())) { String number = uri.getSchemeSpecificPart(); // helper function to check mTelCalls array for a number, and also check its decoded // version private synchronized boolean checkForNumber(String number, String defaultCountryCode) { if (mTelCalls.containsKey(number)) { // check directly via map first return true; Loading @@ -458,12 +461,42 @@ public class ZenModeFiltering { } } } return false; } // Check whether anyone in the provided array of people URIs or phone number set matches a // previously recorded phone call. private synchronized boolean checkCallers(Context context, String[] people, ArraySet<String> phoneNumbers) { // get the default country code for checking telephone numbers final String defaultCountryCode = context.getSystemService(TelephonyManager.class).getNetworkCountryIso(); for (int i = 0; i < people.length; i++) { String person = people[i]; if (person == null) continue; final Uri uri = Uri.parse(person); if ("tel".equals(uri.getScheme())) { String number = uri.getSchemeSpecificPart(); if (checkForNumber(number, defaultCountryCode)) { return true; } } else { if (mOtherCalls.containsKey(person)) { return true; } } } // also check any passed-in phone numbers if (phoneNumbers != null) { for (String num : phoneNumbers) { if (checkForNumber(num, defaultCountryCode)) { return true; } } } // no matches return false; } } Loading
services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java +37 −5 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ public class ZenModeFilteringTest extends UiServiceTestCase { // Create a notification record with the people String array as the // bundled extras, and the numbers ArraySet as additional phone numbers. private NotificationRecord getRecordWithPeopleInfo(String[] people, private NotificationRecord getCallRecordWithPeopleInfo(String[] people, ArraySet<String> numbers) { // set up notification record NotificationRecord r = mock(NotificationRecord.class); Loading @@ -131,6 +131,8 @@ public class ZenModeFilteringTest extends UiServiceTestCase { when(sbn.getNotification()).thenReturn(notification); when(r.getSbn()).thenReturn(sbn); when(r.getPhoneNumbers()).thenReturn(numbers); when(r.getCriticality()).thenReturn(CriticalNotificationExtractor.NORMAL); when(r.isCategory(CATEGORY_CALL)).thenReturn(true); return r; } Loading Loading @@ -349,12 +351,42 @@ public class ZenModeFilteringTest extends UiServiceTestCase { assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r)); } @Test public void testRepeatCallers_checksPhoneNumbers() { // set up telephony manager behavior when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); // first, record a phone call from a telephone number String[] callNumber = new String[]{"tel:12345678910"}; mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(callNumber, null)); // set up policy to only allow repeat callers Policy policy = new Policy( PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE); // make sure that a record with the phone number in extras is correctly allowed through NotificationRecord r = getCallRecordWithPeopleInfo(callNumber, null); assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r)); // make sure that a record with the phone number in the phone numbers array is also // allowed through NotificationRecord r2 = getCallRecordWithPeopleInfo(new String[]{"some_contact_uri"}, new ArraySet<>(new String[]{"12345678910"})); assertFalse(mZenModeFiltering.shouldIntercept( ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r2)); // A record with the phone number in neither of the above should be intercepted NotificationRecord r3 = getCallRecordWithPeopleInfo(new String[]{"tel:10987654321"}, new ArraySet<>(new String[]{"15555555555"})); assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r3)); } @Test public void testMatchesCallFilter_repeatCallers_directMatch() { // after calls given an email with an exact string match, make sure that // matchesCallFilter returns the right thing String[] mailSource = new String[]{"mailto:hello.world"}; mZenModeFiltering.recordCall(getRecordWithPeopleInfo(mailSource, null)); mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(mailSource, null)); // set up policy to only allow repeat callers Policy policy = new Policy( Loading @@ -377,7 +409,7 @@ public class ZenModeFilteringTest extends UiServiceTestCase { when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); String[] telSource = new String[]{"tel:+1-617-555-1212"}; mZenModeFiltering.recordCall(getRecordWithPeopleInfo(telSource, null)); mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(telSource, null)); // set up policy to only allow repeat callers Policy policy = new Policy( Loading Loading @@ -421,7 +453,7 @@ public class ZenModeFilteringTest extends UiServiceTestCase { when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); String[] telSource = new String[]{"tel:%2B16175551212"}; mZenModeFiltering.recordCall(getRecordWithPeopleInfo(telSource, null)); mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(telSource, null)); // set up policy to only allow repeat callers Policy policy = new Policy( Loading Loading @@ -468,7 +500,7 @@ public class ZenModeFilteringTest extends UiServiceTestCase { String[] contactSource = new String[]{"content://contacts/lookup/uri-here"}; ArraySet<String> contactNumbers = new ArraySet<>( new String[]{"1-617-555-1212", "1-617-555-3434"}); NotificationRecord record = getRecordWithPeopleInfo(contactSource, contactNumbers); NotificationRecord record = getCallRecordWithPeopleInfo(contactSource, contactNumbers); record.mergePhoneNumbers(contactNumbers); mZenModeFiltering.recordCall(record); Loading