• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.notification;
18 
19 import static android.app.Notification.CATEGORY_CALL;
20 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
21 import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
22 import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
23 import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_NONE;
24 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
25 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
26 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
27 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
28 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
29 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
30 import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
31 import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
32 import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
33 import static android.provider.Settings.Global.ZEN_MODE_OFF;
34 
35 import static junit.framework.Assert.assertFalse;
36 import static junit.framework.Assert.assertTrue;
37 
38 import static org.mockito.ArgumentMatchers.any;
39 import static org.mockito.Mockito.mock;
40 import static org.mockito.Mockito.when;
41 
42 import android.app.Notification;
43 import android.app.NotificationChannel;
44 import android.app.NotificationManager.Policy;
45 import android.media.AudioAttributes;
46 import android.os.Bundle;
47 import android.os.UserHandle;
48 import android.service.notification.StatusBarNotification;
49 import android.telephony.TelephonyManager;
50 import android.test.suitebuilder.annotation.SmallTest;
51 import android.testing.AndroidTestingRunner;
52 import android.testing.TestableLooper;
53 import android.util.ArraySet;
54 
55 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
56 import com.android.internal.util.NotificationMessagingUtil;
57 import com.android.server.UiServiceTestCase;
58 
59 import org.junit.After;
60 import org.junit.Before;
61 import org.junit.Test;
62 import org.junit.runner.RunWith;
63 import org.mockito.Mock;
64 import org.mockito.MockitoAnnotations;
65 
66 @SmallTest
67 @RunWith(AndroidTestingRunner.class)
68 @TestableLooper.RunWithLooper
69 public class ZenModeFilteringTest extends UiServiceTestCase {
70 
71     @Mock
72     private NotificationMessagingUtil mMessagingUtil;
73     private ZenModeFiltering mZenModeFiltering;
74 
75     @Mock private TelephonyManager mTelephonyManager;
76 
77     private long mTestStartTime;
78 
79     @Before
setUp()80     public void setUp() {
81         MockitoAnnotations.initMocks(this);
82         mZenModeFiltering = new ZenModeFiltering(mContext, mMessagingUtil);
83 
84         // for repeat callers / matchesCallFilter
85         mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
86         mTestStartTime = System.currentTimeMillis();
87     }
88 
89     @After
tearDown()90     public void tearDown() {
91         // make sure to get rid of any data stored in repeat callers
92         mZenModeFiltering.cleanUpCallersAfter(mTestStartTime);
93     }
94 
getNotificationRecord()95     private NotificationRecord getNotificationRecord() {
96         return getNotificationRecord(mock(NotificationChannel.class));
97     }
98 
getNotificationRecord(NotificationChannel c)99     private NotificationRecord getNotificationRecord(NotificationChannel c) {
100         StatusBarNotification sbn = mock(StatusBarNotification.class);
101         Notification notification = mock(Notification.class);
102         when(sbn.getNotification()).thenReturn(notification);
103         return new NotificationRecord(mContext, sbn, c);
104     }
105 
getConversationRecord(NotificationChannel c, StatusBarNotification sbn)106     private NotificationRecord getConversationRecord(NotificationChannel c,
107             StatusBarNotification sbn) {
108         NotificationRecord r = mock(NotificationRecord.class);
109         when(r.getCriticality()).thenReturn(CriticalNotificationExtractor.NORMAL);
110         when(r.getSbn()).thenReturn(sbn);
111         when(r.getChannel()).thenReturn(c);
112         when(r.isConversation()).thenReturn(true);
113         return r;
114     }
115 
makeExtrasBundleWithPeople(String[] people)116     private Bundle makeExtrasBundleWithPeople(String[] people) {
117         Bundle extras = new Bundle();
118         extras.putObject(Notification.EXTRA_PEOPLE_LIST, people);
119         return extras;
120     }
121 
122     // Create a notification record with the people String array as the
123     // bundled extras, and the numbers ArraySet as additional phone numbers.
getCallRecordWithPeopleInfo(String[] people, ArraySet<String> numbers)124     private NotificationRecord getCallRecordWithPeopleInfo(String[] people,
125             ArraySet<String> numbers) {
126         // set up notification record
127         NotificationRecord r = mock(NotificationRecord.class);
128         StatusBarNotification sbn = mock(StatusBarNotification.class);
129         Notification notification = mock(Notification.class);
130         notification.extras = makeExtrasBundleWithPeople(people);
131         when(sbn.getNotification()).thenReturn(notification);
132         when(r.getSbn()).thenReturn(sbn);
133         when(r.getPhoneNumbers()).thenReturn(numbers);
134         when(r.getCriticality()).thenReturn(CriticalNotificationExtractor.NORMAL);
135         when(r.isCategory(CATEGORY_CALL)).thenReturn(true);
136         return r;
137     }
138 
139     @Test
testIsMessage()140     public void testIsMessage() {
141         NotificationRecord r = getNotificationRecord();
142 
143         when(mMessagingUtil.isMessaging(any())).thenReturn(true);
144         assertTrue(mZenModeFiltering.isMessage(r));
145 
146         when(mMessagingUtil.isMessaging(any())).thenReturn(false);
147         assertFalse(mZenModeFiltering.isMessage(r));
148     }
149 
150     @Test
testIsAlarm()151     public void testIsAlarm() {
152         NotificationChannel c = mock(NotificationChannel.class);
153         when(c.getAudioAttributes()).thenReturn(new AudioAttributes.Builder()
154                 .setUsage(AudioAttributes.USAGE_ALARM)
155                 .build());
156         NotificationRecord r = getNotificationRecord(c);
157         assertTrue(mZenModeFiltering.isAlarm(r));
158 
159         r = getNotificationRecord();
160         r.getSbn().getNotification().category = Notification.CATEGORY_ALARM;
161         assertTrue(mZenModeFiltering.isAlarm(r));
162     }
163 
164     @Test
testIsAlarm_wrongCategory()165     public void testIsAlarm_wrongCategory() {
166         NotificationRecord r = getNotificationRecord();
167         r.getSbn().getNotification().category = CATEGORY_CALL;
168         assertFalse(mZenModeFiltering.isAlarm(r));
169     }
170 
171     @Test
testIsAlarm_wrongUsage()172     public void testIsAlarm_wrongUsage() {
173         NotificationChannel c = mock(NotificationChannel.class);
174         when(c.getAudioAttributes()).thenReturn(new AudioAttributes.Builder()
175                 .setUsage(AudioAttributes.USAGE_NOTIFICATION)
176                 .build());
177         NotificationRecord r = getNotificationRecord(c);
178         assertFalse(mZenModeFiltering.isAlarm(r));
179     }
180 
181     @Test
testSuppressDNDInfo_yes_VisEffectsAllowed()182     public void testSuppressDNDInfo_yes_VisEffectsAllowed() {
183         NotificationRecord r = getNotificationRecord();
184         when(r.getSbn().getPackageName()).thenReturn("android");
185         when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
186         Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects()
187                 - SUPPRESSED_EFFECT_STATUS_BAR, 0);
188 
189         assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
190     }
191 
192     @Test
testSuppressDNDInfo_yes_WrongId()193     public void testSuppressDNDInfo_yes_WrongId() {
194         NotificationRecord r = getNotificationRecord();
195         when(r.getSbn().getPackageName()).thenReturn("android");
196         when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION);
197         Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects(), 0);
198 
199         assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
200     }
201 
202     @Test
testSuppressDNDInfo_yes_WrongPackage()203     public void testSuppressDNDInfo_yes_WrongPackage() {
204         NotificationRecord r = getNotificationRecord();
205         when(r.getSbn().getPackageName()).thenReturn("android2");
206         when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
207         Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects(), 0);
208 
209         assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
210     }
211 
212     @Test
testSuppressDNDInfo_no()213     public void testSuppressDNDInfo_no() {
214         NotificationRecord r = getNotificationRecord();
215         when(r.getSbn().getPackageName()).thenReturn("android");
216         when(r.getSbn().getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
217         Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects(), 0);
218 
219         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
220         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_ALARMS, policy, r));
221         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, policy, r));
222     }
223 
224     @Test
testSuppressAnything_yes_ZenModeOff()225     public void testSuppressAnything_yes_ZenModeOff() {
226         NotificationRecord r = getNotificationRecord();
227         when(r.getSbn().getPackageName()).thenReturn("bananas");
228         Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects());
229 
230         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_OFF, policy, r));
231     }
232 
233     @Test
testSuppressAnything_bypass_ZenModeOn()234     public void testSuppressAnything_bypass_ZenModeOn() {
235         NotificationRecord r = getNotificationRecord();
236         r.setCriticality(CriticalNotificationExtractor.CRITICAL);
237         when(r.getSbn().getPackageName()).thenReturn("bananas");
238         Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects(), 0);
239 
240         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, policy, r));
241 
242         r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
243         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, policy, r));
244     }
245 
246     @Test
testConversation_allAllowed()247     public void testConversation_allAllowed() {
248         Notification n = new Notification.Builder(mContext, "a").build();
249         StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0, n,
250                 UserHandle.SYSTEM, null, 0);
251 
252         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
253         channel.setConversationId("parent", "me, work");
254 
255         NotificationRecord r = getConversationRecord(channel, sbn);
256         when(r.isConversation()).thenReturn(true);
257 
258         Policy policy = new Policy(
259                 PRIORITY_CATEGORY_CONVERSATIONS, 0, 0, 0, CONVERSATION_SENDERS_ANYONE);
260 
261         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
262     }
263 
264     @Test
testConversation_importantAllowed_isImportant()265     public void testConversation_importantAllowed_isImportant() {
266         Notification n = new Notification.Builder(mContext, "a").build();
267         StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0, n,
268                 UserHandle.SYSTEM, null, 0);
269 
270         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
271         channel.setConversationId("parent", "me, work");
272         channel.setImportantConversation(true);
273 
274         NotificationRecord r = getConversationRecord(channel, sbn);
275 
276         Policy policy = new Policy(
277                 PRIORITY_CATEGORY_CONVERSATIONS, 0, 0, 0, CONVERSATION_SENDERS_IMPORTANT);
278 
279         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
280     }
281 
282     @Test
testConversation_importantAllowed_isNotImportant()283     public void testConversation_importantAllowed_isNotImportant() {
284         Notification n = new Notification.Builder(mContext, "a").build();
285         StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0, n,
286                 UserHandle.SYSTEM, null, 0);
287 
288         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
289         channel.setConversationId("parent", "me, work");
290 
291         NotificationRecord r = getConversationRecord(channel, sbn);
292 
293         Policy policy = new Policy(
294                 PRIORITY_CATEGORY_CONVERSATIONS, 0, 0, 0, CONVERSATION_SENDERS_IMPORTANT);
295 
296         assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
297     }
298 
299     @Test
testConversation_noneAllowed_notCallOrMsg()300     public void testConversation_noneAllowed_notCallOrMsg() {
301         Notification n = new Notification.Builder(mContext, "a").build();
302         StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0, n,
303                 UserHandle.SYSTEM, null, 0);
304 
305         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
306         channel.setConversationId("parent", "me, work");
307 
308         NotificationRecord r = getConversationRecord(channel, sbn);
309 
310         Policy policy =
311                 new Policy(PRIORITY_CATEGORY_CONVERSATIONS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
312 
313         assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
314     }
315 
316     @Test
testConversation_noneAllowed_callAllowed()317     public void testConversation_noneAllowed_callAllowed() {
318         Notification n = new Notification.Builder(mContext, "a").build();
319         StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0, n,
320                 UserHandle.SYSTEM, null, 0);
321 
322         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
323         channel.setConversationId("parent", "me, work");
324 
325         NotificationRecord r = getConversationRecord(channel, sbn);
326         when(r.isCategory(CATEGORY_CALL)).thenReturn(true);
327 
328         Policy policy =
329                 new Policy(PRIORITY_CATEGORY_CALLS,
330                         PRIORITY_SENDERS_ANY, 0, 0, CONVERSATION_SENDERS_NONE);
331 
332         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
333     }
334 
335     @Test
testConversation_noneAllowed_msgAllowed()336     public void testConversation_noneAllowed_msgAllowed() {
337         when(mMessagingUtil.isMessaging(any())).thenReturn(true);
338         Notification n = new Notification.Builder(mContext, "a").build();
339         StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0, n,
340                 UserHandle.SYSTEM, null, 0);
341 
342         NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT);
343         channel.setConversationId("parent", "me, work");
344 
345         NotificationRecord r = getConversationRecord(channel, sbn);
346 
347         Policy policy =
348                 new Policy(PRIORITY_CATEGORY_MESSAGES,
349                         0, PRIORITY_SENDERS_ANY, 0, CONVERSATION_SENDERS_NONE);
350 
351         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
352     }
353 
354     @Test
testRepeatCallers_checksPhoneNumbers()355     public void testRepeatCallers_checksPhoneNumbers() {
356         // set up telephony manager behavior
357         when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us");
358 
359         // first, record a phone call from a telephone number
360         String[] callNumber = new String[]{"tel:12345678910"};
361         mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(callNumber, null));
362 
363         // set up policy to only allow repeat callers
364         Policy policy = new Policy(
365                 PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
366 
367         // make sure that a record with the phone number in extras is correctly allowed through
368         NotificationRecord r = getCallRecordWithPeopleInfo(callNumber, null);
369         assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
370 
371         // make sure that a record with the phone number in the phone numbers array is also
372         // allowed through
373         NotificationRecord r2 = getCallRecordWithPeopleInfo(new String[]{"some_contact_uri"},
374                 new ArraySet<>(new String[]{"12345678910"}));
375         assertFalse(mZenModeFiltering.shouldIntercept(
376                 ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r2));
377 
378         // A record with the phone number in neither of the above should be intercepted
379         NotificationRecord r3 = getCallRecordWithPeopleInfo(new String[]{"tel:10987654321"},
380                 new ArraySet<>(new String[]{"15555555555"}));
381         assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r3));
382     }
383 
384     @Test
testMatchesCallFilter_repeatCallers_directMatch()385     public void testMatchesCallFilter_repeatCallers_directMatch() {
386         // after calls given an email with an exact string match, make sure that
387         // matchesCallFilter returns the right thing
388         String[] mailSource = new String[]{"mailto:hello.world"};
389         mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(mailSource, null));
390 
391         // set up policy to only allow repeat callers
392         Policy policy = new Policy(
393                 PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
394 
395         // check whether matchesCallFilter returns the right thing
396         Bundle inputMatches = makeExtrasBundleWithPeople(new String[]{"mailto:hello.world"});
397         Bundle inputWrong = makeExtrasBundleWithPeople(new String[]{"mailto:nope"});
398         assertTrue(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
399                 policy, UserHandle.SYSTEM,
400                 inputMatches, null, 0, 0, 0));
401         assertFalse(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
402                 policy, UserHandle.SYSTEM,
403                 inputWrong, null, 0, 0, 0));
404     }
405 
406     @Test
testMatchesCallFilter_repeatCallers_telephoneVariants()407     public void testMatchesCallFilter_repeatCallers_telephoneVariants() {
408         // set up telephony manager behavior
409         when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us");
410 
411         String[] telSource = new String[]{"tel:+1-617-555-1212"};
412         mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(telSource, null));
413 
414         // set up policy to only allow repeat callers
415         Policy policy = new Policy(
416                 PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
417 
418         // cases to test:
419         //   - identical number
420         //   - same number, different formatting
421         //   - different number
422         //   - garbage
423         Bundle identical = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"});
424         Bundle same = makeExtrasBundleWithPeople(new String[]{"tel:16175551212"});
425         Bundle different = makeExtrasBundleWithPeople(new String[]{"tel:123-456-7890"});
426         Bundle garbage = makeExtrasBundleWithPeople(new String[]{"asdfghjkl;"});
427 
428         assertTrue("identical numbers should match",
429                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
430                 policy, UserHandle.SYSTEM,
431                 identical, null, 0, 0, 0));
432         assertTrue("equivalent but non-identical numbers should match",
433                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
434                 policy, UserHandle.SYSTEM,
435                 same, null, 0, 0, 0));
436         assertFalse("non-equivalent numbers should not match",
437                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
438                 policy, UserHandle.SYSTEM,
439                 different, null, 0, 0, 0));
440         assertFalse("non-tel strings should not match",
441                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
442                 policy, UserHandle.SYSTEM,
443                 garbage, null, 0, 0, 0));
444     }
445 
446     @Test
testMatchesCallFilter_repeatCallers_urlEncodedTels()447     public void testMatchesCallFilter_repeatCallers_urlEncodedTels() {
448         // this is not intended to be a supported case but is one that we have seen
449         // sometimes in the wild, so make sure we handle url-encoded telephone numbers correctly
450         // when somebody provides one.
451 
452         // set up telephony manager behavior
453         when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us");
454 
455         String[] telSource = new String[]{"tel:%2B16175551212"};
456         mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(telSource, null));
457 
458         // set up policy to only allow repeat callers
459         Policy policy = new Policy(
460                 PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
461 
462         // test cases for various forms of the same phone number and different ones
463         Bundle same1 = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"});
464         Bundle same2 = makeExtrasBundleWithPeople(new String[]{"tel:%2B1-617-555-1212"});
465         Bundle same3 = makeExtrasBundleWithPeople(new String[]{"tel:6175551212"});
466         Bundle different1 = makeExtrasBundleWithPeople(new String[]{"tel:%2B16175553434"});
467         Bundle different2 = makeExtrasBundleWithPeople(new String[]{"tel:+16175553434"});
468 
469         assertTrue("same number 1 should match",
470                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
471                         policy, UserHandle.SYSTEM,
472                         same1, null, 0, 0, 0));
473         assertTrue("same number 2 should match",
474                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
475                         policy, UserHandle.SYSTEM,
476                         same2, null, 0, 0, 0));
477         assertTrue("same number 3 should match",
478                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
479                         policy, UserHandle.SYSTEM,
480                         same3, null, 0, 0, 0));
481         assertFalse("different number 1 should not match",
482                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
483                         policy, UserHandle.SYSTEM,
484                         different1, null, 0, 0, 0));
485         assertFalse("different number 2 should not match",
486                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
487                         policy, UserHandle.SYSTEM,
488                         different2, null, 0, 0, 0));
489     }
490 
491     @Test
testMatchesCallFilter_repeatCallers_viaRecordPhoneNumbers()492     public void testMatchesCallFilter_repeatCallers_viaRecordPhoneNumbers() {
493         // make sure that phone numbers that are passed in via the NotificationRecord's
494         // cached phone numbers field (from a contact lookup if the record is provided a contact
495         // uri) also get recorded in the repeat callers list.
496 
497         // set up telephony manager behavior
498         when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us");
499 
500         String[] contactSource = new String[]{"content://contacts/lookup/uri-here"};
501         ArraySet<String> contactNumbers = new ArraySet<>(
502                 new String[]{"1-617-555-1212", "1-617-555-3434"});
503         NotificationRecord record = getCallRecordWithPeopleInfo(contactSource, contactNumbers);
504         record.mergePhoneNumbers(contactNumbers);
505         mZenModeFiltering.recordCall(record);
506 
507         // set up policy to only allow repeat callers
508         Policy policy = new Policy(
509                 PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
510 
511         // both phone numbers should register here
512         Bundle tel1 = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"});
513         Bundle tel2 = makeExtrasBundleWithPeople(new String[]{"tel:16175553434"});
514         Bundle different = makeExtrasBundleWithPeople(new String[]{"tel:16175555656"});
515 
516         assertTrue("contact number 1 should match",
517                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
518                         policy, UserHandle.SYSTEM,
519                         tel1, null, 0, 0, 0));
520         assertTrue("contact number 2 should match",
521                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
522                         policy, UserHandle.SYSTEM,
523                         tel2, null, 0, 0, 0));
524         assertFalse("different number should not match",
525                 ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
526                         policy, UserHandle.SYSTEM,
527                         different, null, 0, 0, 0));
528     }
529 }
530