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.settings.applications; 18 19 import static android.text.format.DateUtils.DAY_IN_MILLIS; 20 21 import static com.android.settings.applications.AppStateNotificationBridge 22 .FILTER_APP_NOTIFICATION_BLOCKED; 23 import static com.android.settings.applications.AppStateNotificationBridge 24 .FILTER_APP_NOTIFICATION_FREQUENCY; 25 import static com.android.settings.applications.AppStateNotificationBridge 26 .FILTER_APP_NOTIFICATION_RECENCY; 27 import static com.android.settings.applications.AppStateNotificationBridge 28 .FREQUENCY_NOTIFICATION_COMPARATOR; 29 import static com.android.settings.applications.AppStateNotificationBridge 30 .RECENT_NOTIFICATION_COMPARATOR; 31 32 import static com.google.common.truth.Truth.assertThat; 33 34 import static org.junit.Assert.assertFalse; 35 import static org.junit.Assert.assertTrue; 36 import static org.mockito.ArgumentMatchers.any; 37 import static org.mockito.ArgumentMatchers.anyInt; 38 import static org.mockito.ArgumentMatchers.anyLong; 39 import static org.mockito.ArgumentMatchers.anyString; 40 import static org.mockito.ArgumentMatchers.eq; 41 import static org.mockito.Mockito.mock; 42 import static org.mockito.Mockito.verify; 43 import static org.mockito.Mockito.when; 44 45 import android.app.usage.IUsageStatsManager; 46 import android.app.usage.UsageEvents; 47 import android.app.usage.UsageEvents.Event; 48 import android.content.Context; 49 import android.content.pm.ApplicationInfo; 50 import android.os.Looper; 51 import android.os.Parcel; 52 import android.os.RemoteException; 53 import android.os.UserHandle; 54 import android.os.UserManager; 55 import android.view.ViewGroup; 56 import android.widget.CompoundButton; 57 import android.widget.Switch; 58 59 import com.android.settings.R; 60 import com.android.settings.applications.AppStateNotificationBridge.NotificationsSentState; 61 import com.android.settings.notification.NotificationBackend; 62 import com.android.settingslib.applications.ApplicationsState; 63 import com.android.settingslib.applications.ApplicationsState.AppEntry; 64 65 import org.junit.Before; 66 import org.junit.Test; 67 import org.junit.runner.RunWith; 68 import org.mockito.Mock; 69 import org.mockito.MockitoAnnotations; 70 import org.robolectric.RobolectricTestRunner; 71 import org.robolectric.RuntimeEnvironment; 72 73 import java.util.ArrayList; 74 import java.util.List; 75 import java.util.Map; 76 77 @RunWith(RobolectricTestRunner.class) 78 public class AppStateNotificationBridgeTest { 79 80 private static String PKG1 = "pkg1"; 81 private static String PKG2 = "pkg2"; 82 83 @Mock 84 private ApplicationsState.Session mSession; 85 @Mock 86 private ApplicationsState mState; 87 @Mock 88 private IUsageStatsManager mUsageStats; 89 @Mock 90 private UserManager mUserManager; 91 @Mock 92 private NotificationBackend mBackend; 93 private Context mContext; 94 private AppStateNotificationBridge mBridge; 95 96 @Before setUp()97 public void setUp() { 98 MockitoAnnotations.initMocks(this); 99 when(mState.newSession(any())).thenReturn(mSession); 100 when(mState.getBackgroundLooper()).thenReturn(mock(Looper.class)); 101 when(mBackend.getNotificationsBanned(anyString(), anyInt())).thenReturn(true); 102 when(mBackend.isSystemApp(any(), any())).thenReturn(true); 103 // most tests assume no work profile 104 when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{}); 105 mContext = RuntimeEnvironment.application.getApplicationContext(); 106 107 mBridge = new AppStateNotificationBridge(mContext, mState, 108 mock(AppStateBaseBridge.Callback.class), mUsageStats, mUserManager, mBackend); 109 } 110 getMockAppEntry(String pkg)111 private AppEntry getMockAppEntry(String pkg) { 112 AppEntry entry = mock(AppEntry.class); 113 entry.info = mock(ApplicationInfo.class); 114 entry.info.packageName = pkg; 115 return entry; 116 } 117 getUsageEvents(List<Event> events)118 private UsageEvents getUsageEvents(List<Event> events) { 119 UsageEvents usageEvents = new UsageEvents(events, new String[] {PKG1, PKG2}); 120 Parcel parcel = Parcel.obtain(); 121 parcel.setDataPosition(0); 122 usageEvents.writeToParcel(parcel, 0); 123 parcel.setDataPosition(0); 124 return UsageEvents.CREATOR.createFromParcel(parcel); 125 } 126 127 @Test testGetAggregatedUsageEvents_noEvents()128 public void testGetAggregatedUsageEvents_noEvents() throws Exception { 129 when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString())) 130 .thenReturn(mock(UsageEvents.class)); 131 132 assertThat(mBridge.getAggregatedUsageEvents()).isEmpty(); 133 } 134 135 @Test testGetAggregatedUsageEvents_onlyNotificationEvents()136 public void testGetAggregatedUsageEvents_onlyNotificationEvents() throws Exception { 137 List<Event> events = new ArrayList<>(); 138 Event good = new Event(); 139 good.mEventType = Event.NOTIFICATION_INTERRUPTION; 140 good.mPackage = PKG1; 141 good.mTimeStamp = 1; 142 events.add(good); 143 Event bad = new Event(); 144 bad.mEventType = Event.CHOOSER_ACTION; 145 bad.mPackage = PKG1; 146 bad.mTimeStamp = 2; 147 events.add(bad); 148 149 UsageEvents usageEvents = getUsageEvents(events); 150 when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString())) 151 .thenReturn(usageEvents); 152 153 Map<String, NotificationsSentState> map = mBridge.getAggregatedUsageEvents(); 154 assertThat(map.get(AppStateNotificationBridge.getKey(0, PKG1)).sentCount).isEqualTo(1); 155 } 156 157 @Test testGetAggregatedUsageEvents_multipleEventsAgg()158 public void testGetAggregatedUsageEvents_multipleEventsAgg() throws Exception { 159 List<Event> events = new ArrayList<>(); 160 Event good = new Event(); 161 good.mEventType = Event.NOTIFICATION_INTERRUPTION; 162 good.mPackage = PKG1; 163 good.mTimeStamp = 6; 164 events.add(good); 165 Event good1 = new Event(); 166 good1.mEventType = Event.NOTIFICATION_INTERRUPTION; 167 good1.mPackage = PKG1; 168 good1.mTimeStamp = 1; 169 events.add(good1); 170 171 UsageEvents usageEvents = getUsageEvents(events); 172 when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString())) 173 .thenReturn(usageEvents); 174 175 Map<String, NotificationsSentState> map = mBridge.getAggregatedUsageEvents(); 176 assertThat(map.get(AppStateNotificationBridge.getKey(0, PKG1)).sentCount).isEqualTo(2); 177 assertThat(map.get(AppStateNotificationBridge.getKey(0, PKG1)).lastSent).isEqualTo(6); 178 } 179 180 @Test testGetAggregatedUsageEvents_multiplePkgs()181 public void testGetAggregatedUsageEvents_multiplePkgs() throws Exception { 182 List<Event> events = new ArrayList<>(); 183 Event good = new Event(); 184 good.mEventType = Event.NOTIFICATION_INTERRUPTION; 185 good.mPackage = PKG1; 186 good.mTimeStamp = 6; 187 events.add(good); 188 Event good1 = new Event(); 189 good1.mEventType = Event.NOTIFICATION_INTERRUPTION; 190 good1.mPackage = PKG2; 191 good1.mTimeStamp = 1; 192 events.add(good1); 193 194 UsageEvents usageEvents = getUsageEvents(events); 195 when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString())) 196 .thenReturn(usageEvents); 197 198 Map<String, NotificationsSentState> map 199 = mBridge.getAggregatedUsageEvents(); 200 assertThat(map.get(AppStateNotificationBridge.getKey(0, PKG1)).sentCount).isEqualTo(1); 201 assertThat(map.get(AppStateNotificationBridge.getKey(0, PKG2)).sentCount).isEqualTo(1); 202 assertThat(map.get(AppStateNotificationBridge.getKey(0, PKG1)).lastSent).isEqualTo(6); 203 assertThat(map.get(AppStateNotificationBridge.getKey(0, PKG2)).lastSent).isEqualTo(1); 204 } 205 206 @Test testLoadAllExtraInfo_noEvents()207 public void testLoadAllExtraInfo_noEvents() throws RemoteException { 208 when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString())) 209 .thenReturn(mock(UsageEvents.class)); 210 ArrayList<AppEntry> apps = new ArrayList<>(); 211 apps.add(getMockAppEntry(PKG1)); 212 when(mSession.getAllApps()).thenReturn(apps); 213 214 mBridge.loadAllExtraInfo(); 215 // extra info should exist and blocked status should be populated 216 assertThat(apps.get(0).extraInfo).isNotNull(); 217 verify(mBackend).getNotificationsBanned(PKG1, 0); 218 // but the recent/frequent counts should be 0 so they don't appear on those screens 219 assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentDaily).isEqualTo(0); 220 assertThat(((NotificationsSentState) apps.get(0).extraInfo).lastSent).isEqualTo(0); 221 } 222 223 @Test testLoadAllExtraInfo_multipleEventsAgg()224 public void testLoadAllExtraInfo_multipleEventsAgg() throws RemoteException { 225 List<Event> events = new ArrayList<>(); 226 for (int i = 0; i < 7; i++) { 227 Event good = new Event(); 228 good.mEventType = Event.NOTIFICATION_INTERRUPTION; 229 good.mPackage = PKG1; 230 good.mTimeStamp = i; 231 events.add(good); 232 } 233 234 UsageEvents usageEvents = getUsageEvents(events); 235 when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString())) 236 .thenReturn(usageEvents); 237 238 ArrayList<AppEntry> apps = new ArrayList<>(); 239 apps.add(getMockAppEntry(PKG1)); 240 when(mSession.getAllApps()).thenReturn(apps); 241 242 mBridge.loadAllExtraInfo(); 243 assertThat(((NotificationsSentState) apps.get(0).extraInfo).sentCount).isEqualTo(7); 244 assertThat(((NotificationsSentState) apps.get(0).extraInfo).lastSent).isEqualTo(6); 245 assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentDaily).isEqualTo(1); 246 assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentWeekly).isEqualTo(0); 247 assertThat(((NotificationsSentState) apps.get(0).extraInfo).blocked).isTrue(); 248 assertThat(((NotificationsSentState) apps.get(0).extraInfo).systemApp).isTrue(); 249 assertThat(((NotificationsSentState) apps.get(0).extraInfo).blockable).isTrue(); 250 } 251 252 @Test testLoadAllExtraInfo_multiplePkgs()253 public void testLoadAllExtraInfo_multiplePkgs() throws RemoteException { 254 List<Event> events = new ArrayList<>(); 255 for (int i = 0; i < 8; i++) { 256 Event good = new Event(); 257 good.mEventType = Event.NOTIFICATION_INTERRUPTION; 258 good.mPackage = PKG1; 259 good.mTimeStamp = i; 260 events.add(good); 261 } 262 Event good1 = new Event(); 263 good1.mEventType = Event.NOTIFICATION_INTERRUPTION; 264 good1.mPackage = PKG2; 265 good1.mTimeStamp = 1; 266 events.add(good1); 267 268 UsageEvents usageEvents = getUsageEvents(events); 269 when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString())) 270 .thenReturn(usageEvents); 271 272 ArrayList<AppEntry> apps = new ArrayList<>(); 273 apps.add(getMockAppEntry(PKG1)); 274 apps.add(getMockAppEntry(PKG2)); 275 when(mSession.getAllApps()).thenReturn(apps); 276 277 mBridge.loadAllExtraInfo(); 278 assertThat(((NotificationsSentState) apps.get(0).extraInfo).sentCount).isEqualTo(8); 279 assertThat(((NotificationsSentState) apps.get(0).extraInfo).lastSent).isEqualTo(7); 280 assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentWeekly).isEqualTo(0); 281 assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentDaily).isEqualTo(1); 282 283 assertThat(((NotificationsSentState) apps.get(1).extraInfo).sentCount).isEqualTo(1); 284 assertThat(((NotificationsSentState) apps.get(1).extraInfo).lastSent).isEqualTo(1); 285 assertThat(((NotificationsSentState) apps.get(1).extraInfo).avgSentWeekly).isEqualTo(1); 286 assertThat(((NotificationsSentState) apps.get(1).extraInfo).avgSentDaily).isEqualTo(0); 287 } 288 289 @Test testLoadAllExtraInfo_multipleUsers()290 public void testLoadAllExtraInfo_multipleUsers() throws RemoteException { 291 // has work profile 292 when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{1}); 293 mBridge = new AppStateNotificationBridge(mContext, mState, 294 mock(AppStateBaseBridge.Callback.class), mUsageStats, mUserManager, mBackend); 295 296 List<Event> eventsProfileOwner = new ArrayList<>(); 297 for (int i = 0; i < 8; i++) { 298 Event good = new Event(); 299 good.mEventType = Event.NOTIFICATION_INTERRUPTION; 300 good.mPackage = PKG1; 301 good.mTimeStamp = i; 302 eventsProfileOwner.add(good); 303 } 304 305 List<Event> eventsProfile = new ArrayList<>(); 306 for (int i = 0; i < 4; i++) { 307 Event good = new Event(); 308 good.mEventType = Event.NOTIFICATION_INTERRUPTION; 309 good.mPackage = PKG1; 310 good.mTimeStamp = i; 311 eventsProfile.add(good); 312 } 313 314 UsageEvents usageEventsOwner = getUsageEvents(eventsProfileOwner); 315 when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), eq(0), anyString())) 316 .thenReturn(usageEventsOwner); 317 318 UsageEvents usageEventsProfile = getUsageEvents(eventsProfile); 319 when(mUsageStats.queryEventsForUser(anyLong(), anyLong(), eq(1), anyString())) 320 .thenReturn(usageEventsProfile); 321 322 ArrayList<AppEntry> apps = new ArrayList<>(); 323 AppEntry owner = getMockAppEntry(PKG1); 324 owner.info.uid = 1; 325 apps.add(owner); 326 327 AppEntry profile = getMockAppEntry(PKG1); 328 profile.info.uid = UserHandle.PER_USER_RANGE + 1; 329 apps.add(profile); 330 when(mSession.getAllApps()).thenReturn(apps); 331 332 mBridge.loadAllExtraInfo(); 333 334 assertThat(((NotificationsSentState) apps.get(0).extraInfo).sentCount).isEqualTo(8); 335 assertThat(((NotificationsSentState) apps.get(0).extraInfo).lastSent).isEqualTo(7); 336 assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentWeekly).isEqualTo(0); 337 assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentDaily).isEqualTo(1); 338 339 assertThat(((NotificationsSentState) apps.get(1).extraInfo).sentCount).isEqualTo(4); 340 assertThat(((NotificationsSentState) apps.get(1).extraInfo).lastSent).isEqualTo(3); 341 assertThat(((NotificationsSentState) apps.get(1).extraInfo).avgSentWeekly).isEqualTo(4); 342 assertThat(((NotificationsSentState) apps.get(1).extraInfo).avgSentDaily).isEqualTo(1); 343 } 344 345 @Test testUpdateExtraInfo_noEvents()346 public void testUpdateExtraInfo_noEvents() throws RemoteException { 347 when(mUsageStats.queryEventsForPackageForUser( 348 anyLong(), anyLong(), anyInt(), anyString(), anyString())) 349 .thenReturn(mock(UsageEvents.class)); 350 AppEntry entry = getMockAppEntry(PKG1); 351 352 mBridge.updateExtraInfo(entry, "", 0); 353 assertThat(entry.extraInfo).isNull(); 354 } 355 356 @Test testUpdateExtraInfo_multipleEventsAgg()357 public void testUpdateExtraInfo_multipleEventsAgg() throws RemoteException { 358 List<Event> events = new ArrayList<>(); 359 for (int i = 0; i < 13; i++) { 360 Event good = new Event(); 361 good.mEventType = Event.NOTIFICATION_INTERRUPTION; 362 good.mPackage = PKG1; 363 good.mTimeStamp = i; 364 events.add(good); 365 } 366 367 UsageEvents usageEvents = getUsageEvents(events); 368 when(mUsageStats.queryEventsForPackageForUser( 369 anyLong(), anyLong(), anyInt(), anyString(), anyString())).thenReturn(usageEvents); 370 371 AppEntry entry = getMockAppEntry(PKG1); 372 mBridge.updateExtraInfo(entry, "", 0); 373 374 assertThat(((NotificationsSentState) entry.extraInfo).sentCount).isEqualTo(13); 375 assertThat(((NotificationsSentState) entry.extraInfo).lastSent).isEqualTo(12); 376 assertThat(((NotificationsSentState) entry.extraInfo).avgSentDaily).isEqualTo(2); 377 assertThat(((NotificationsSentState) entry.extraInfo).avgSentWeekly).isEqualTo(0); 378 assertThat(((NotificationsSentState) entry.extraInfo).blocked).isTrue(); 379 assertThat(((NotificationsSentState) entry.extraInfo).systemApp).isTrue(); 380 assertThat(((NotificationsSentState) entry.extraInfo).blockable).isTrue(); 381 } 382 383 @Test testSummary_recency()384 public void testSummary_recency() { 385 NotificationsSentState neverSent = new NotificationsSentState(); 386 NotificationsSentState sent = new NotificationsSentState(); 387 sent.lastSent = System.currentTimeMillis() - (2 * DAY_IN_MILLIS); 388 389 assertThat(AppStateNotificationBridge.getSummary( 390 mContext, neverSent, R.id.sort_order_recent_notification)).isEqualTo( 391 mContext.getString(R.string.notifications_sent_never)); 392 assertThat(AppStateNotificationBridge.getSummary( 393 mContext, sent, R.id.sort_order_recent_notification).toString()).contains("2"); 394 } 395 396 @Test testSummary_frequency()397 public void testSummary_frequency() { 398 NotificationsSentState sentRarely = new NotificationsSentState(); 399 sentRarely.avgSentWeekly = 1; 400 NotificationsSentState sentOften = new NotificationsSentState(); 401 sentOften.avgSentDaily = 8; 402 403 assertThat(AppStateNotificationBridge.getSummary( 404 mContext, sentRarely, R.id.sort_order_frequent_notification).toString()) 405 .contains("1"); 406 assertThat(AppStateNotificationBridge.getSummary( 407 mContext, sentRarely, R.id.sort_order_frequent_notification).toString()) 408 .contains("notification "); 409 assertThat(AppStateNotificationBridge.getSummary( 410 mContext, sentRarely, R.id.sort_order_frequent_notification).toString()) 411 .contains("week"); 412 assertThat(AppStateNotificationBridge.getSummary( 413 mContext, sentOften, R.id.sort_order_frequent_notification).toString()) 414 .contains("8"); 415 assertThat(AppStateNotificationBridge.getSummary( 416 mContext, sentOften, R.id.sort_order_frequent_notification).toString()) 417 .contains("notifications"); 418 assertThat(AppStateNotificationBridge.getSummary( 419 mContext, sentOften, R.id.sort_order_frequent_notification).toString()) 420 .contains("day"); 421 } 422 423 @Test testSummary_alpha()424 public void testSummary_alpha() { 425 NotificationsSentState sentRarely = new NotificationsSentState(); 426 sentRarely.avgSentWeekly = 1; 427 assertThat(AppStateNotificationBridge.getSummary( 428 mContext, sentRarely, R.id.sort_order_alpha).toString()) 429 .isEqualTo(""); 430 } 431 432 @Test testFilterRecency()433 public void testFilterRecency() { 434 NotificationsSentState allowState = new NotificationsSentState(); 435 allowState.lastSent = 1; 436 AppEntry allow = mock(AppEntry.class); 437 allow.extraInfo = allowState; 438 439 440 assertTrue(FILTER_APP_NOTIFICATION_RECENCY.filterApp(allow)); 441 442 NotificationsSentState denyState = new NotificationsSentState(); 443 denyState.lastSent = 0; 444 AppEntry deny = mock(AppEntry.class); 445 deny.extraInfo = denyState; 446 447 assertFalse(FILTER_APP_NOTIFICATION_RECENCY.filterApp(deny)); 448 } 449 450 @Test testFilterFrequency()451 public void testFilterFrequency() { 452 NotificationsSentState allowState = new NotificationsSentState(); 453 allowState.sentCount = 1; 454 AppEntry allow = mock(AppEntry.class); 455 allow.extraInfo = allowState; 456 457 assertTrue(FILTER_APP_NOTIFICATION_FREQUENCY.filterApp(allow)); 458 459 NotificationsSentState denyState = new NotificationsSentState(); 460 denyState.sentCount = 0; 461 AppEntry deny = mock(AppEntry.class); 462 deny.extraInfo = denyState; 463 464 assertFalse(FILTER_APP_NOTIFICATION_FREQUENCY.filterApp(deny)); 465 } 466 467 @Test testFilterBlocked()468 public void testFilterBlocked() { 469 NotificationsSentState allowState = new NotificationsSentState(); 470 allowState.blocked = true; 471 AppEntry allow = mock(AppEntry.class); 472 allow.extraInfo = allowState; 473 474 assertTrue(FILTER_APP_NOTIFICATION_BLOCKED.filterApp(allow)); 475 476 NotificationsSentState denyState = new NotificationsSentState(); 477 denyState.blocked = false; 478 AppEntry deny = mock(AppEntry.class); 479 deny.extraInfo = denyState; 480 481 assertFalse(FILTER_APP_NOTIFICATION_BLOCKED.filterApp(deny)); 482 } 483 484 @Test testComparators_nullsNoCrash()485 public void testComparators_nullsNoCrash() { 486 List<AppEntry> entries = new ArrayList<>(); 487 AppEntry a = mock(AppEntry.class); 488 a.label = "1"; 489 AppEntry b = mock(AppEntry.class); 490 b.label = "2"; 491 entries.add(a); 492 entries.add(b); 493 494 entries.sort(RECENT_NOTIFICATION_COMPARATOR); 495 entries.sort(FREQUENCY_NOTIFICATION_COMPARATOR); 496 } 497 498 @Test testRecencyComparator()499 public void testRecencyComparator() { 500 List<AppEntry> entries = new ArrayList<>(); 501 502 NotificationsSentState earlier = new NotificationsSentState(); 503 earlier.lastSent = 1; 504 AppEntry earlyEntry = mock(AppEntry.class); 505 earlyEntry.extraInfo = earlier; 506 entries.add(earlyEntry); 507 508 NotificationsSentState later = new NotificationsSentState(); 509 later.lastSent = 8; 510 AppEntry lateEntry = mock(AppEntry.class); 511 lateEntry.extraInfo = later; 512 entries.add(lateEntry); 513 514 entries.sort(RECENT_NOTIFICATION_COMPARATOR); 515 516 assertThat(entries).containsExactly(lateEntry, earlyEntry); 517 } 518 519 @Test testFrequencyComparator()520 public void testFrequencyComparator() { 521 List<AppEntry> entries = new ArrayList<>(); 522 523 NotificationsSentState notFrequentWeekly = new NotificationsSentState(); 524 notFrequentWeekly.sentCount = 2; 525 AppEntry notFrequentWeeklyEntry = mock(AppEntry.class); 526 notFrequentWeeklyEntry.extraInfo = notFrequentWeekly; 527 entries.add(notFrequentWeeklyEntry); 528 529 NotificationsSentState notFrequentDaily = new NotificationsSentState(); 530 notFrequentDaily.sentCount = 7; 531 AppEntry notFrequentDailyEntry = mock(AppEntry.class); 532 notFrequentDailyEntry.extraInfo = notFrequentDaily; 533 entries.add(notFrequentDailyEntry); 534 535 NotificationsSentState veryFrequentWeekly = new NotificationsSentState(); 536 veryFrequentWeekly.sentCount = 6; 537 AppEntry veryFrequentWeeklyEntry = mock(AppEntry.class); 538 veryFrequentWeeklyEntry.extraInfo = veryFrequentWeekly; 539 entries.add(veryFrequentWeeklyEntry); 540 541 NotificationsSentState veryFrequentDaily = new NotificationsSentState(); 542 veryFrequentDaily.sentCount = 19; 543 AppEntry veryFrequentDailyEntry = mock(AppEntry.class); 544 veryFrequentDailyEntry.extraInfo = veryFrequentDaily; 545 entries.add(veryFrequentDailyEntry); 546 547 entries.sort(FREQUENCY_NOTIFICATION_COMPARATOR); 548 549 assertThat(entries).containsExactly(veryFrequentDailyEntry, notFrequentDailyEntry, 550 veryFrequentWeeklyEntry, notFrequentWeeklyEntry); 551 } 552 553 @Test testSwitchOnChangeListener()554 public void testSwitchOnChangeListener() { 555 Switch toggle = mock(Switch.class); 556 when(toggle.isChecked()).thenReturn(true); 557 when(toggle.isEnabled()).thenReturn(true); 558 559 AppEntry entry = mock(AppEntry.class); 560 entry.info = new ApplicationInfo(); 561 entry.info.packageName = "pkg"; 562 entry.info.uid = 1356; 563 entry.extraInfo = new NotificationsSentState(); 564 565 CompoundButton.OnCheckedChangeListener listener = mBridge.getSwitchOnCheckedListener(entry); 566 listener.onCheckedChanged(toggle, true); 567 568 verify(mBackend).setNotificationsEnabledForPackage( 569 entry.info.packageName, entry.info.uid, true); 570 assertThat(((NotificationsSentState) entry.extraInfo).blocked).isFalse(); 571 } 572 573 @Test testSwitchViews_nullDoesNotCrash()574 public void testSwitchViews_nullDoesNotCrash() { 575 AppStateNotificationBridge.enableSwitch(null); 576 AppStateNotificationBridge.checkSwitch(null); 577 } 578 } 579