1 /*
2  * Copyright (C) 2017 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.systemui;
18 
19 import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
20 
21 import static junit.framework.Assert.assertEquals;
22 import static junit.framework.Assert.assertNull;
23 import static junit.framework.TestCase.fail;
24 
25 import static org.junit.Assert.assertFalse;
26 import static org.junit.Assert.assertTrue;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.verify;
29 import static org.mockito.Mockito.when;
30 
31 import android.annotation.UserIdInt;
32 import android.app.AppOpsManager;
33 import android.app.Notification;
34 import android.app.NotificationManager;
35 import android.os.Bundle;
36 import android.os.Handler;
37 import android.os.UserHandle;
38 import android.service.notification.StatusBarNotification;
39 import android.testing.AndroidTestingRunner;
40 import android.testing.TestableLooper;
41 import android.widget.RemoteViews;
42 
43 import androidx.test.filters.SmallTest;
44 
45 import com.android.internal.messages.nano.SystemMessageProto;
46 import com.android.systemui.appops.AppOpsController;
47 import com.android.systemui.statusbar.notification.NotificationEntryListener;
48 import com.android.systemui.statusbar.notification.NotificationEntryManager;
49 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
50 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
51 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
52 import com.android.systemui.util.time.FakeSystemClock;
53 
54 import org.junit.Before;
55 import org.junit.Test;
56 import org.junit.runner.RunWith;
57 import org.mockito.ArgumentCaptor;
58 import org.mockito.Mock;
59 import org.mockito.MockitoAnnotations;
60 
61 @SmallTest
62 @RunWith(AndroidTestingRunner.class)
63 @TestableLooper.RunWithLooper
64 public class ForegroundServiceControllerTest extends SysuiTestCase {
65     private ForegroundServiceController mFsc;
66     private ForegroundServiceNotificationListener mListener;
67     private NotificationEntryListener mEntryListener;
68     private final FakeSystemClock mClock = new FakeSystemClock();
69     @Mock private NotificationEntryManager mEntryManager;
70     @Mock private AppOpsController mAppOpsController;
71     @Mock private Handler mMainHandler;
72     @Mock private NotifPipeline mNotifPipeline;
73 
74     @Before
setUp()75     public void setUp() throws Exception {
76         // allow the TestLooper to be asserted as the main thread these tests
77         allowTestableLooperAsMainThread();
78 
79         MockitoAnnotations.initMocks(this);
80         mFsc = new ForegroundServiceController(mAppOpsController, mMainHandler);
81         mListener = new ForegroundServiceNotificationListener(
82                 mContext, mFsc, mEntryManager, mNotifPipeline, mClock);
83         ArgumentCaptor<NotificationEntryListener> entryListenerCaptor =
84                 ArgumentCaptor.forClass(NotificationEntryListener.class);
85         verify(mEntryManager).addNotificationEntryListener(
86                 entryListenerCaptor.capture());
87         mEntryListener = entryListenerCaptor.getValue();
88     }
89 
90     @Test
testAppOpsChangedCalledFromBgThread()91     public void testAppOpsChangedCalledFromBgThread() {
92         try {
93             // WHEN onAppOpChanged is called from a different thread than the MainLooper
94             disallowTestableLooperAsMainThread();
95             NotificationEntry entry = createFgEntry();
96             mFsc.onAppOpChanged(
97                     AppOpsManager.OP_CAMERA,
98                     entry.getSbn().getUid(),
99                     entry.getSbn().getPackageName(),
100                     true);
101 
102             // This test is run on the TestableLooper, which is not the MainLooper, so
103             // we expect an exception to be thrown
104             fail("onAppOpChanged shouldn't be allowed to be called from a bg thread.");
105         } catch (IllegalStateException e) {
106             // THEN expect an exception
107         }
108     }
109 
110     @Test
testAppOpsCRUD()111     public void testAppOpsCRUD() {
112         // no crash on remove that doesn't exist
113         mFsc.onAppOpChanged(9, 1000, "pkg1", false);
114         assertNull(mFsc.getAppOps(0, "pkg1"));
115 
116         // multiuser & multipackage
117         mFsc.onAppOpChanged(8, 50, "pkg1", true);
118         mFsc.onAppOpChanged(1, 60, "pkg3", true);
119         mFsc.onAppOpChanged(7, 500000, "pkg2", true);
120 
121         assertEquals(1, mFsc.getAppOps(0, "pkg1").size());
122         assertTrue(mFsc.getAppOps(0, "pkg1").contains(8));
123 
124         assertEquals(1, mFsc.getAppOps(UserHandle.getUserId(500000), "pkg2").size());
125         assertTrue(mFsc.getAppOps(UserHandle.getUserId(500000), "pkg2").contains(7));
126 
127         assertEquals(1, mFsc.getAppOps(0, "pkg3").size());
128         assertTrue(mFsc.getAppOps(0, "pkg3").contains(1));
129 
130         // multiple ops for the same package
131         mFsc.onAppOpChanged(9, 50, "pkg1", true);
132         mFsc.onAppOpChanged(5, 50, "pkg1", true);
133 
134         assertEquals(3, mFsc.getAppOps(0, "pkg1").size());
135         assertTrue(mFsc.getAppOps(0, "pkg1").contains(8));
136         assertTrue(mFsc.getAppOps(0, "pkg1").contains(9));
137         assertTrue(mFsc.getAppOps(0, "pkg1").contains(5));
138 
139         assertEquals(1, mFsc.getAppOps(UserHandle.getUserId(500000), "pkg2").size());
140         assertTrue(mFsc.getAppOps(UserHandle.getUserId(500000), "pkg2").contains(7));
141 
142         // remove one of the multiples
143         mFsc.onAppOpChanged(9, 50, "pkg1", false);
144         assertEquals(2, mFsc.getAppOps(0, "pkg1").size());
145         assertTrue(mFsc.getAppOps(0, "pkg1").contains(8));
146         assertTrue(mFsc.getAppOps(0, "pkg1").contains(5));
147 
148         // remove last op
149         mFsc.onAppOpChanged(1, 60, "pkg3", false);
150         assertNull(mFsc.getAppOps(0, "pkg3"));
151     }
152 
153     @Test
testDisclosurePredicate()154     public void testDisclosurePredicate() {
155         StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
156                 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
157         StatusBarNotification sbn_user1_disclosure = makeMockSBN(USERID_ONE, "android",
158                 SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
159                 null, Notification.FLAG_NO_CLEAR);
160 
161         assertTrue(mFsc.isDisclosureNotification(sbn_user1_disclosure));
162         assertFalse(mFsc.isDisclosureNotification(sbn_user1_app1));
163     }
164 
165     @Test
testNeedsDisclosureAfterRemovingUnrelatedNotification()166     public void testNeedsDisclosureAfterRemovingUnrelatedNotification() {
167         final String PKG1 = "com.example.app100";
168 
169         StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
170                 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
171         StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1);
172 
173         // first add a normal notification
174         entryAdded(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
175         // nothing required yet
176         assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE));
177         // now the app starts a fg service
178         entryAdded(makeMockDisclosure(USERID_ONE, new String[]{PKG1}),
179                 NotificationManager.IMPORTANCE_DEFAULT);
180         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required!
181         // add the fg notification
182         entryAdded(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
183         assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); // app1 has got it covered
184         // remove the boring notification
185         entryRemoved(sbn_user1_app1);
186         assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); // app1 has STILL got it covered
187         entryRemoved(sbn_user1_app1_fg);
188         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required!
189     }
190 
191     @Test
testSimpleAddRemove()192     public void testSimpleAddRemove() {
193         final String PKG1 = "com.example.app1";
194         final String PKG2 = "com.example.app2";
195 
196         StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
197                 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
198         entryAdded(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
199 
200         // no services are "running"
201         entryAdded(makeMockDisclosure(USERID_ONE, null),
202                 NotificationManager.IMPORTANCE_DEFAULT);
203 
204         assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE));
205         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
206 
207         entryUpdated(makeMockDisclosure(USERID_ONE, new String[]{PKG1}),
208                 NotificationManager.IMPORTANCE_DEFAULT);
209         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required!
210         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
211 
212         // switch to different package
213         entryUpdated(makeMockDisclosure(USERID_ONE, new String[]{PKG2}),
214                 NotificationManager.IMPORTANCE_DEFAULT);
215         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE));
216         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
217 
218         entryUpdated(makeMockDisclosure(USERID_TWO, new String[]{PKG1}),
219                 NotificationManager.IMPORTANCE_DEFAULT);
220         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE));
221         assertTrue(mFsc.isDisclosureNeededForUser(USERID_TWO)); // finally user2 needs one too
222 
223         entryUpdated(makeMockDisclosure(USERID_ONE, new String[]{PKG2, PKG1}),
224                 NotificationManager.IMPORTANCE_DEFAULT);
225         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE));
226         assertTrue(mFsc.isDisclosureNeededForUser(USERID_TWO));
227 
228         entryRemoved(makeMockDisclosure(USERID_ONE, null /*unused*/));
229         assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE));
230         assertTrue(mFsc.isDisclosureNeededForUser(USERID_TWO));
231 
232         entryRemoved(makeMockDisclosure(USERID_TWO, null /*unused*/));
233         assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE));
234         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
235     }
236 
237     @Test
testDisclosureBasic()238     public void testDisclosureBasic() {
239         final String PKG1 = "com.example.app0";
240 
241         StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
242                 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
243         StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1);
244 
245         entryAdded(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT); // not fg
246         entryAdded(makeMockDisclosure(USERID_ONE, new String[]{PKG1}),
247                 NotificationManager.IMPORTANCE_DEFAULT);
248         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required!
249         entryAdded(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
250         assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); // app1 has got it covered
251         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
252 
253         // let's take out the other notification and see what happens.
254 
255         entryRemoved(sbn_user1_app1);
256         assertFalse(
257                 mFsc.isDisclosureNeededForUser(USERID_ONE)); // still covered by sbn_user1_app1_fg
258         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
259 
260         // let's attempt to downgrade the notification from FLAG_FOREGROUND and see what we get
261         StatusBarNotification sbn_user1_app1_fg_sneaky = makeMockFgSBN(USERID_ONE, PKG1);
262         sbn_user1_app1_fg_sneaky.getNotification().flags = 0;
263         entryUpdated(sbn_user1_app1_fg_sneaky,
264                 NotificationManager.IMPORTANCE_DEFAULT);
265         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required!
266         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
267 
268         // ok, ok, we'll put it back
269         sbn_user1_app1_fg_sneaky.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
270         entryUpdated(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
271         assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE));
272         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
273 
274         entryRemoved(sbn_user1_app1_fg_sneaky);
275         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required!
276         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
277 
278         // now let's test an upgrade
279         entryAdded(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
280         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE));
281         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
282         sbn_user1_app1.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
283         entryUpdated(sbn_user1_app1,
284                 NotificationManager.IMPORTANCE_DEFAULT); // this is now a fg notification
285 
286         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
287         assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE));
288 
289         // remove it, make sure we're out of compliance again
290         entryRemoved(sbn_user1_app1); // was fg, should return true
291         entryRemoved(sbn_user1_app1);
292         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
293         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE));
294 
295         // importance upgrade
296         entryAdded(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_MIN);
297         assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE));
298         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
299         sbn_user1_app1.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
300         entryUpdated(sbn_user1_app1_fg,
301                 NotificationManager.IMPORTANCE_DEFAULT); // this is now a fg notification
302 
303         // finally, let's turn off the service
304         entryAdded(makeMockDisclosure(USERID_ONE, null),
305                 NotificationManager.IMPORTANCE_DEFAULT);
306 
307         assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE));
308         assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO));
309     }
310 
311     @Test
testNoNotifsNorAppOps_noSystemAlertWarningRequired()312     public void testNoNotifsNorAppOps_noSystemAlertWarningRequired() {
313         // no notifications nor app op signals that this package/userId requires system alert
314         // warning
315         assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_ONE, "any"));
316     }
317 
318     @Test
testCustomLayouts_systemAlertWarningRequired()319     public void testCustomLayouts_systemAlertWarningRequired() {
320         // GIVEN a notification with a custom layout
321         final String pkg = "com.example.app0";
322         StatusBarNotification customLayoutNotif = makeMockSBN(USERID_ONE, pkg, 0,
323                 false);
324 
325         // WHEN the custom layout entry is added
326         entryAdded(customLayoutNotif, NotificationManager.IMPORTANCE_MIN);
327 
328         // THEN a system alert warning is required since there aren't any notifications that can
329         // display the app ops
330         assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg));
331     }
332 
333     @Test
testStandardLayoutExists_noSystemAlertWarningRequired()334     public void testStandardLayoutExists_noSystemAlertWarningRequired() {
335         // GIVEN two notifications (one with a custom layout, the other with a standard layout)
336         final String pkg = "com.example.app0";
337         StatusBarNotification customLayoutNotif = makeMockSBN(USERID_ONE, pkg, 0,
338                 false);
339         StatusBarNotification standardLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, true);
340 
341         // WHEN the entries are added
342         entryAdded(customLayoutNotif, NotificationManager.IMPORTANCE_MIN);
343         entryAdded(standardLayoutNotif, NotificationManager.IMPORTANCE_MIN);
344 
345         // THEN no system alert warning is required, since there is at least one notification
346         // with a standard layout that can display the app ops on the notification
347         assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg));
348     }
349 
350     @Test
testStandardLayoutRemoved_systemAlertWarningRequired()351     public void testStandardLayoutRemoved_systemAlertWarningRequired() {
352         // GIVEN two notifications (one with a custom layout, the other with a standard layout)
353         final String pkg = "com.example.app0";
354         StatusBarNotification customLayoutNotif = makeMockSBN(USERID_ONE, pkg, 0,
355                 false);
356         StatusBarNotification standardLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, true);
357 
358         // WHEN the entries are added and then the standard layout notification is removed
359         entryAdded(customLayoutNotif, NotificationManager.IMPORTANCE_MIN);
360         entryAdded(standardLayoutNotif, NotificationManager.IMPORTANCE_MIN);
361         entryRemoved(standardLayoutNotif);
362 
363         // THEN a system alert warning is required since there aren't any notifications that can
364         // display the app ops
365         assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg));
366     }
367 
368     @Test
testStandardLayoutUpdatedToCustomLayout_systemAlertWarningRequired()369     public void testStandardLayoutUpdatedToCustomLayout_systemAlertWarningRequired() {
370         // GIVEN a standard layout notification and then an updated version with a customLayout
371         final String pkg = "com.example.app0";
372         StatusBarNotification standardLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, true);
373         StatusBarNotification updatedToCustomLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, false);
374 
375         // WHEN the entries is added and then updated to a custom layout
376         entryAdded(standardLayoutNotif, NotificationManager.IMPORTANCE_MIN);
377         entryUpdated(updatedToCustomLayoutNotif, NotificationManager.IMPORTANCE_MIN);
378 
379         // THEN a system alert warning is required since there aren't any notifications that can
380         // display the app ops
381         assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg));
382     }
383 
makeMockSBN(int userId, String pkg, int id, String tag, int flags)384     private StatusBarNotification makeMockSBN(int userId, String pkg, int id, String tag,
385             int flags) {
386         final Notification n = mock(Notification.class);
387         n.extras = new Bundle();
388         n.flags = flags;
389         return makeMockSBN(userId, pkg, id, tag, n);
390     }
391 
makeMockSBN(int userid, String pkg, int id, String tag, Notification n)392     private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag,
393             Notification n) {
394         final StatusBarNotification sbn = mock(StatusBarNotification.class);
395         when(sbn.getNotification()).thenReturn(n);
396         when(sbn.getId()).thenReturn(id);
397         when(sbn.getPackageName()).thenReturn(pkg);
398         when(sbn.getTag()).thenReturn(tag);
399         when(sbn.getUserId()).thenReturn(userid);
400         when(sbn.getUser()).thenReturn(new UserHandle(userid));
401         when(sbn.getKey()).thenReturn("MOCK:"+userid+"|"+pkg+"|"+id+"|"+tag);
402         return sbn;
403     }
404 
makeMockSBN(int uid, String pkg, int id, boolean usesStdLayout)405     private StatusBarNotification makeMockSBN(int uid, String pkg, int id,
406             boolean usesStdLayout) {
407         StatusBarNotification sbn = makeMockSBN(uid, pkg, id, "foo", 0);
408         if (usesStdLayout) {
409             sbn.getNotification().contentView = null;
410             sbn.getNotification().headsUpContentView = null;
411             sbn.getNotification().bigContentView = null;
412         } else {
413             sbn.getNotification().contentView = mock(RemoteViews.class);
414         }
415         return sbn;
416     }
417 
makeMockFgSBN(int uid, String pkg, int id, boolean usesStdLayout)418     private StatusBarNotification makeMockFgSBN(int uid, String pkg, int id,
419             boolean usesStdLayout) {
420         StatusBarNotification sbn =
421                 makeMockSBN(uid, pkg, id, "foo", Notification.FLAG_FOREGROUND_SERVICE);
422         if (usesStdLayout) {
423             sbn.getNotification().contentView = null;
424             sbn.getNotification().headsUpContentView = null;
425             sbn.getNotification().bigContentView = null;
426         } else {
427             sbn.getNotification().contentView = mock(RemoteViews.class);
428         }
429         return sbn;
430     }
431 
makeMockFgSBN(int uid, String pkg)432     private StatusBarNotification makeMockFgSBN(int uid, String pkg) {
433         return makeMockSBN(uid, pkg, 1000, "foo", Notification.FLAG_FOREGROUND_SERVICE);
434     }
435 
makeMockDisclosure(int userid, String[] pkgs)436     private StatusBarNotification makeMockDisclosure(int userid, String[] pkgs) {
437         final Notification n = mock(Notification.class);
438         n.flags = Notification.FLAG_ONGOING_EVENT;
439         final Bundle extras = new Bundle();
440         if (pkgs != null) extras.putStringArray(Notification.EXTRA_FOREGROUND_APPS, pkgs);
441         n.extras = extras;
442         n.when = System.currentTimeMillis() - 10000; // ten seconds ago
443         final StatusBarNotification sbn = makeMockSBN(userid, "android",
444                 SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
445                 null, n);
446         sbn.getNotification().extras = extras;
447         return sbn;
448     }
449 
addFgEntry()450     private NotificationEntry addFgEntry() {
451         NotificationEntry entry = createFgEntry();
452         mEntryListener.onPendingEntryAdded(entry);
453         return entry;
454     }
455 
createFgEntry()456     private NotificationEntry createFgEntry() {
457         return new NotificationEntryBuilder()
458                 .setSbn(makeMockFgSBN(0, TEST_PACKAGE_NAME, 1000, true))
459                 .setImportance(NotificationManager.IMPORTANCE_DEFAULT)
460                 .build();
461     }
462 
entryRemoved(StatusBarNotification notification)463     private void entryRemoved(StatusBarNotification notification) {
464         mEntryListener.onEntryRemoved(
465                 new NotificationEntryBuilder()
466                         .setSbn(notification)
467                         .build(),
468                 null,
469                 false,
470                 REASON_APP_CANCEL);
471     }
472 
entryAdded(StatusBarNotification notification, int importance)473     private void entryAdded(StatusBarNotification notification, int importance) {
474         NotificationEntry entry = new NotificationEntryBuilder()
475                 .setSbn(notification)
476                 .setImportance(importance)
477                 .build();
478         mEntryListener.onPendingEntryAdded(entry);
479     }
480 
entryUpdated(StatusBarNotification notification, int importance)481     private void entryUpdated(StatusBarNotification notification, int importance) {
482         NotificationEntry entry = new NotificationEntryBuilder()
483                 .setSbn(notification)
484                 .setImportance(importance)
485                 .build();
486         mEntryListener.onPreEntryUpdated(entry);
487     }
488 
489     @UserIdInt private static final int USERID_ONE = 10; // UserManagerService.MIN_USER_ID;
490     @UserIdInt private static final int USERID_TWO = USERID_ONE + 1;
491     private static final String TEST_PACKAGE_NAME = "test";
492 }
493