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