1 /* 2 * Copyright (C) 2020 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.people.data; 18 19 import static android.app.people.ConversationStatus.ACTIVITY_ANNIVERSARY; 20 import static android.app.people.ConversationStatus.ACTIVITY_GAME; 21 import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED; 22 import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED; 23 import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED; 24 25 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 26 27 import static com.google.common.truth.Truth.assertThat; 28 29 import static junit.framework.Assert.fail; 30 31 import static org.junit.Assert.assertEquals; 32 import static org.junit.Assert.assertFalse; 33 import static org.junit.Assert.assertNotNull; 34 import static org.junit.Assert.assertNull; 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.anyList; 39 import static org.mockito.ArgumentMatchers.anyLong; 40 import static org.mockito.ArgumentMatchers.anyString; 41 import static org.mockito.Mockito.doAnswer; 42 import static org.mockito.Mockito.eq; 43 import static org.mockito.Mockito.mock; 44 import static org.mockito.Mockito.never; 45 import static org.mockito.Mockito.times; 46 import static org.mockito.Mockito.verify; 47 import static org.mockito.Mockito.when; 48 49 import android.annotation.NonNull; 50 import android.annotation.Nullable; 51 import android.annotation.UserIdInt; 52 import android.app.AlarmManager; 53 import android.app.Notification; 54 import android.app.NotificationChannel; 55 import android.app.NotificationManager; 56 import android.app.Person; 57 import android.app.job.JobScheduler; 58 import android.app.people.ConversationChannel; 59 import android.app.people.ConversationStatus; 60 import android.app.prediction.AppTarget; 61 import android.app.prediction.AppTargetEvent; 62 import android.app.prediction.AppTargetId; 63 import android.app.usage.UsageStatsManagerInternal; 64 import android.content.BroadcastReceiver; 65 import android.content.ContentResolver; 66 import android.content.Context; 67 import android.content.Intent; 68 import android.content.IntentFilter; 69 import android.content.pm.LauncherApps.ShortcutChangeCallback; 70 import android.content.pm.LauncherApps.ShortcutQuery; 71 import android.content.pm.PackageManager; 72 import android.content.pm.PackageManagerInternal; 73 import android.content.pm.ShortcutInfo; 74 import android.content.pm.ShortcutServiceInternal; 75 import android.content.pm.UserInfo; 76 import android.database.ContentObserver; 77 import android.net.Uri; 78 import android.os.CancellationSignal; 79 import android.os.Looper; 80 import android.os.UserHandle; 81 import android.os.UserManager; 82 import android.os.test.TestLooper; 83 import android.provider.ContactsContract; 84 import android.service.notification.NotificationListenerService; 85 import android.service.notification.StatusBarNotification; 86 import android.telecom.TelecomManager; 87 import android.telephony.TelephonyManager; 88 import android.text.format.DateUtils; 89 import android.util.Range; 90 91 import com.android.internal.app.ChooserActivity; 92 import com.android.internal.content.PackageMonitor; 93 import com.android.server.LocalServices; 94 import com.android.server.notification.NotificationManagerInternal; 95 import com.android.server.people.PeopleService; 96 import com.android.server.pm.pkg.AndroidPackage; 97 98 import com.google.common.collect.Iterables; 99 100 import org.junit.After; 101 import org.junit.Before; 102 import org.junit.Test; 103 import org.junit.runner.RunWith; 104 import org.junit.runners.JUnit4; 105 import org.mockito.ArgumentCaptor; 106 import org.mockito.Captor; 107 import org.mockito.Mock; 108 import org.mockito.MockitoAnnotations; 109 110 import java.util.ArrayList; 111 import java.util.Arrays; 112 import java.util.Collections; 113 import java.util.List; 114 import java.util.Set; 115 import java.util.concurrent.Executor; 116 import java.util.concurrent.ScheduledExecutorService; 117 import java.util.function.BiConsumer; 118 import java.util.function.Consumer; 119 import java.util.function.Function; 120 121 @RunWith(JUnit4.class) 122 public final class DataManagerTest { 123 124 private static final int USER_ID_PRIMARY = 0; 125 private static final int USER_ID_PRIMARY_MANAGED = 10; 126 private static final int USER_ID_SECONDARY = 11; 127 private static final String TEST_PKG_NAME = "pkg"; 128 private static final String TEST_CLASS_NAME = "class"; 129 private static final String TEST_SHORTCUT_ID = "sc"; 130 private static final String TEST_SHORTCUT_ID_2 = "sc2"; 131 private static final int TEST_PKG_UID = 35; 132 private static final String CONTACT_URI = "content://com.android.contacts/contacts/lookup/123"; 133 private static final String PHONE_NUMBER = "+1234567890"; 134 private static final String NOTIFICATION_CHANNEL_ID = "test : sc"; 135 private static final String PARENT_NOTIFICATION_CHANNEL_ID = "test"; 136 private static final long MILLIS_PER_MINUTE = 1000L * 60L; 137 private static final String GENERIC_KEY = "key"; 138 private static final String CUSTOM_KEY = "custom"; 139 140 @Mock 141 private Context mContext; 142 @Mock 143 private ShortcutServiceInternal mShortcutServiceInternal; 144 @Mock 145 private UsageStatsManagerInternal mUsageStatsManagerInternal; 146 @Mock 147 private PackageManagerInternal mPackageManagerInternal; 148 @Mock 149 private NotificationManagerInternal mNotificationManagerInternal; 150 @Mock 151 private UserManager mUserManager; 152 @Mock 153 private PackageManager mPackageManager; 154 @Mock 155 private TelephonyManager mTelephonyManager; 156 @Mock 157 private TelecomManager mTelecomManager; 158 @Mock 159 private ContentResolver mContentResolver; 160 @Mock 161 private JobScheduler mJobScheduler; 162 @Mock 163 private StatusBarNotification mGenericSbn; 164 @Mock 165 private StatusBarNotification mConvoSbn; 166 @Mock 167 private NotificationListenerService.RankingMap mRankingMap; 168 @Mock 169 private Notification mNotification; 170 @Mock 171 private AlarmManager mAlarmManager; 172 173 @Captor 174 private ArgumentCaptor<ShortcutChangeCallback> mShortcutChangeCallbackCaptor; 175 @Captor 176 private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor; 177 @Captor 178 private ArgumentCaptor<Integer> mQueryFlagsCaptor; 179 180 private ScheduledExecutorService mExecutorService; 181 private NotificationChannel mNotificationChannel; 182 private NotificationChannel mParentNotificationChannel; 183 private DataManager mDataManager; 184 private CancellationSignal mCancellationSignal; 185 private ShortcutChangeCallback mShortcutChangeCallback; 186 private ShortcutInfo mShortcutInfo; 187 private TestInjector mInjector; 188 private TestLooper mLooper; 189 190 @Before setUp()191 public void setUp() throws PackageManager.NameNotFoundException { 192 MockitoAnnotations.initMocks(this); 193 194 addLocalServiceMock(ShortcutServiceInternal.class, mShortcutServiceInternal); 195 196 addLocalServiceMock(UsageStatsManagerInternal.class, mUsageStatsManagerInternal); 197 198 addLocalServiceMock(PackageManagerInternal.class, mPackageManagerInternal); 199 AndroidPackage androidPackage = mock(AndroidPackage.class); 200 when(androidPackage.getPackageName()).thenReturn(TEST_PKG_NAME); 201 doAnswer(ans -> { 202 Consumer<AndroidPackage> callback = (Consumer<AndroidPackage>) ans.getArguments()[0]; 203 callback.accept(androidPackage); 204 return null; 205 }).when(mPackageManagerInternal).forEachInstalledPackage(any(Consumer.class), anyInt()); 206 207 addLocalServiceMock(NotificationManagerInternal.class, mNotificationManagerInternal); 208 mParentNotificationChannel = new NotificationChannel( 209 PARENT_NOTIFICATION_CHANNEL_ID, "test channel", 210 NotificationManager.IMPORTANCE_DEFAULT); 211 212 when(mContext.getContentResolver()).thenReturn(mContentResolver); 213 when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper()); 214 when(mContext.getPackageName()).thenReturn("android"); 215 when(mContext.getPackageManager()).thenReturn(mPackageManager); 216 217 Context originalContext = getInstrumentation().getTargetContext(); 218 when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo()); 219 when(mContext.getUser()).thenReturn(originalContext.getUser()); 220 when(mContext.getPackageName()).thenReturn(originalContext.getPackageName()); 221 222 when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); 223 when(mContext.getSystemServiceName(UserManager.class)).thenReturn( 224 Context.USER_SERVICE); 225 when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager); 226 when(mContext.getSystemServiceName(AlarmManager.class)).thenReturn( 227 Context.ALARM_SERVICE); 228 229 when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); 230 231 when(mContext.getSystemService(Context.TELECOM_SERVICE)).thenReturn(mTelecomManager); 232 when(mContext.getSystemServiceName(TelecomManager.class)).thenReturn( 233 Context.TELECOM_SERVICE); 234 when(mTelecomManager.getDefaultDialerPackage(any(UserHandle.class))) 235 .thenReturn(TEST_PKG_NAME); 236 237 when(mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE)).thenReturn(mJobScheduler); 238 when(mContext.getSystemServiceName(JobScheduler.class)).thenReturn( 239 Context.JOB_SCHEDULER_SERVICE); 240 241 mExecutorService = new MockScheduledExecutorService(); 242 243 when(mUserManager.getEnabledProfiles(USER_ID_PRIMARY)) 244 .thenReturn(Arrays.asList( 245 buildUserInfo(USER_ID_PRIMARY), 246 buildUserInfo(USER_ID_PRIMARY_MANAGED))); 247 when(mUserManager.getEnabledProfiles(USER_ID_SECONDARY)) 248 .thenReturn(Collections.singletonList(buildUserInfo(USER_ID_SECONDARY))); 249 250 when(mPackageManager.getPackageUidAsUser(TEST_PKG_NAME, USER_ID_PRIMARY)) 251 .thenReturn(TEST_PKG_UID); 252 253 mNotificationChannel = new NotificationChannel( 254 NOTIFICATION_CHANNEL_ID, "test channel", NotificationManager.IMPORTANCE_DEFAULT); 255 mNotificationChannel.setConversationId(PARENT_NOTIFICATION_CHANNEL_ID, TEST_SHORTCUT_ID); 256 when(mNotificationManagerInternal.getNotificationChannel(anyString(), anyInt(), 257 eq(mNotificationChannel.getId()))).thenReturn(mNotificationChannel); 258 when(mNotificationManagerInternal.getNotificationChannel(anyString(), anyInt(), 259 eq(mParentNotificationChannel.getId()))).thenReturn(mParentNotificationChannel); 260 261 when(mGenericSbn.getKey()).thenReturn(GENERIC_KEY); 262 when(mGenericSbn.getNotification()).thenReturn(mNotification); 263 when(mGenericSbn.getPackageName()).thenReturn(TEST_PKG_NAME); 264 when(mGenericSbn.getUser()).thenReturn(UserHandle.of(USER_ID_PRIMARY)); 265 when(mGenericSbn.getPostTime()).thenReturn(System.currentTimeMillis()); 266 when(mConvoSbn.getKey()).thenReturn(CUSTOM_KEY); 267 when(mConvoSbn.getNotification()).thenReturn(mNotification); 268 when(mConvoSbn.getPackageName()).thenReturn(TEST_PKG_NAME); 269 when(mConvoSbn.getUser()).thenReturn(UserHandle.of(USER_ID_PRIMARY)); 270 when(mConvoSbn.getPostTime()).thenReturn(System.currentTimeMillis()); 271 272 when(mNotification.getShortcutId()).thenReturn(TEST_SHORTCUT_ID); 273 274 mCancellationSignal = new CancellationSignal(); 275 276 mInjector = new TestInjector(); 277 mLooper = new TestLooper(); 278 mDataManager = new DataManager(mContext, mInjector, mLooper.getLooper()); 279 mDataManager.initialize(); 280 281 when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(), 282 anyString(), anyInt(), any())).thenReturn(true); 283 284 mShortcutInfo = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 285 buildPerson()); 286 when(mShortcutServiceInternal.getShortcuts( 287 anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(), 288 anyInt(), anyInt(), anyInt(), anyInt())) 289 .thenReturn(Collections.singletonList(mShortcutInfo)); 290 verify(mShortcutServiceInternal).addShortcutChangeCallback( 291 mShortcutChangeCallbackCaptor.capture()); 292 mShortcutChangeCallback = mShortcutChangeCallbackCaptor.getValue(); 293 294 verify(mContext, times(1)).registerReceiver(any(), any()); 295 verify(mContext, times(1)).registerReceiver(any(), any(), anyInt()); 296 } 297 298 @After tearDown()299 public void tearDown() { 300 LocalServices.removeServiceForTest(ShortcutServiceInternal.class); 301 LocalServices.removeServiceForTest(UsageStatsManagerInternal.class); 302 LocalServices.removeServiceForTest(PackageManagerInternal.class); 303 } 304 305 @Test testAccessConversationFromTheSameProfileGroup()306 public void testAccessConversationFromTheSameProfileGroup() { 307 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 308 mDataManager.onUserUnlocked(USER_ID_PRIMARY_MANAGED); 309 mDataManager.onUserUnlocked(USER_ID_SECONDARY); 310 311 mDataManager.addOrUpdateConversationInfo( 312 buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1", 313 buildPerson(true, false))); 314 mDataManager.addOrUpdateConversationInfo( 315 buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2", 316 buildPerson(false, true))); 317 mDataManager.addOrUpdateConversationInfo( 318 buildShortcutInfo("pkg_3", USER_ID_SECONDARY, "sc_3", buildPerson())); 319 320 List<ConversationInfo> conversations = getConversationsInPrimary(); 321 322 // USER_ID_SECONDARY is not in the same profile group as USER_ID_PRIMARY. 323 assertEquals(2, conversations.size()); 324 325 assertEquals("sc_1", conversations.get(0).getShortcutId()); 326 assertTrue(conversations.get(0).isPersonImportant()); 327 assertFalse(conversations.get(0).isPersonBot()); 328 assertFalse(conversations.get(0).isContactStarred()); 329 assertEquals(PHONE_NUMBER, conversations.get(0).getContactPhoneNumber()); 330 331 assertEquals("sc_2", conversations.get(1).getShortcutId()); 332 assertFalse(conversations.get(1).isPersonImportant()); 333 assertTrue(conversations.get(1).isPersonBot()); 334 assertFalse(conversations.get(0).isContactStarred()); 335 assertEquals(PHONE_NUMBER, conversations.get(0).getContactPhoneNumber()); 336 } 337 338 @Test testAccessConversationForUnlockedUsersOnly()339 public void testAccessConversationForUnlockedUsersOnly() { 340 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 341 mDataManager.addOrUpdateConversationInfo( 342 buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1", buildPerson())); 343 mDataManager.addOrUpdateConversationInfo( 344 buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2", buildPerson())); 345 346 List<ConversationInfo> conversations = getConversationsInPrimary(); 347 348 // USER_ID_PRIMARY_MANAGED is not locked, so only USER_ID_PRIMARY's conversation is stored. 349 assertEquals(1, conversations.size()); 350 assertEquals("sc_1", conversations.get(0).getShortcutId()); 351 352 mDataManager.onUserStopping(USER_ID_PRIMARY); 353 conversations = getConversationsInPrimary(); 354 assertTrue(conversations.isEmpty()); 355 } 356 357 @Test testGetShortcut()358 public void testGetShortcut() { 359 mDataManager.getShortcut(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID); 360 verify(mShortcutServiceInternal).getShortcuts(anyInt(), anyString(), anyLong(), 361 eq(TEST_PKG_NAME), eq(Collections.singletonList(TEST_SHORTCUT_ID)), 362 eq(null), eq(null), anyInt(), eq(USER_ID_PRIMARY), anyInt(), anyInt()); 363 } 364 365 @Test testReportAppTargetEvent_directSharing()366 public void testReportAppTargetEvent_directSharing() 367 throws IntentFilter.MalformedMimeTypeException { 368 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 369 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 370 buildPerson()); 371 mDataManager.addOrUpdateConversationInfo(shortcut); 372 373 AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut) 374 .build(); 375 AppTargetEvent appTargetEvent = 376 new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH) 377 .setLaunchLocation(ChooserActivity.LAUNCH_LOCATION_DIRECT_SHARE) 378 .build(); 379 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg"); 380 mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter); 381 382 List<Range<Long>> activeShareTimeSlots = getActiveSlotsForTestShortcut( 383 Event.SHARE_EVENT_TYPES); 384 assertEquals(1, activeShareTimeSlots.size()); 385 } 386 387 @Test testReportAppTargetEvent_directSharing_createConversation()388 public void testReportAppTargetEvent_directSharing_createConversation() 389 throws IntentFilter.MalformedMimeTypeException { 390 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 391 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 392 null); 393 AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut) 394 .build(); 395 AppTargetEvent appTargetEvent = 396 new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH) 397 .setLaunchLocation(ChooserActivity.LAUNCH_LOCATION_DIRECT_SHARE) 398 .build(); 399 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg"); 400 401 mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter); 402 403 List<Range<Long>> activeShareTimeSlots = getActiveSlotsForTestShortcut( 404 Event.SHARE_EVENT_TYPES); 405 assertEquals(1, activeShareTimeSlots.size()); 406 ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY) 407 .getConversationStore() 408 .getConversation(TEST_SHORTCUT_ID); 409 assertNotNull(conversationInfo); 410 assertEquals(conversationInfo.getShortcutId(), TEST_SHORTCUT_ID); 411 } 412 413 @Test testReportAppTargetEvent_appSharing()414 public void testReportAppTargetEvent_appSharing() 415 throws IntentFilter.MalformedMimeTypeException { 416 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 417 AppTarget appTarget = new AppTarget.Builder( 418 new AppTargetId(TEST_SHORTCUT_ID), 419 TEST_PKG_NAME, 420 UserHandle.of(USER_ID_PRIMARY)) 421 .setClassName(TEST_CLASS_NAME) 422 .build(); 423 AppTargetEvent appTargetEvent = 424 new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH) 425 .build(); 426 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg"); 427 428 mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter); 429 430 List<Range<Long>> activeShareTimeSlots = getActiveSlotsForAppShares(); 431 assertEquals(1, activeShareTimeSlots.size()); 432 } 433 434 @Test testContactsChanged()435 public void testContactsChanged() { 436 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 437 mDataManager.onUserUnlocked(USER_ID_SECONDARY); 438 439 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 440 buildPerson()); 441 mDataManager.addOrUpdateConversationInfo(shortcut); 442 443 final String newPhoneNumber = "+1000000000"; 444 mInjector.mContactsQueryHelper.mIsStarred = true; 445 mInjector.mContactsQueryHelper.mPhoneNumber = newPhoneNumber; 446 447 ContentObserver contentObserver = mDataManager.getContactsContentObserverForTesting( 448 USER_ID_PRIMARY); 449 contentObserver.onChange(false, ContactsContract.Contacts.CONTENT_URI, USER_ID_PRIMARY); 450 451 List<ConversationInfo> conversations = getConversationsInPrimary(); 452 assertEquals(1, conversations.size()); 453 454 assertEquals(TEST_SHORTCUT_ID, conversations.get(0).getShortcutId()); 455 assertTrue(conversations.get(0).isContactStarred()); 456 assertEquals(newPhoneNumber, conversations.get(0).getContactPhoneNumber()); 457 } 458 459 @Test testNotificationPosted()460 public void testNotificationPosted() { 461 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 462 463 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 464 buildPerson()); 465 mDataManager.addOrUpdateConversationInfo(shortcut); 466 467 sendGenericNotification(); 468 469 List<Range<Long>> activeNotificationOpenTimeSlots = getActiveSlotsForTestShortcut( 470 Event.NOTIFICATION_EVENT_TYPES); 471 assertEquals(1, activeNotificationOpenTimeSlots.size()); 472 } 473 474 @Test testNotificationOpened()475 public void testNotificationOpened() { 476 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 477 478 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 479 buildPerson()); 480 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 481 mDataManager.addOrUpdateConversationInfo(shortcut); 482 483 NotificationListenerService listenerService = 484 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 485 486 listenerService.onNotificationRemoved(mGenericSbn, null, 487 NotificationListenerService.REASON_CLICK); 488 489 List<Range<Long>> activeNotificationOpenTimeSlots = getActiveSlotsForTestShortcut( 490 Event.NOTIFICATION_EVENT_TYPES); 491 assertEquals(1, activeNotificationOpenTimeSlots.size()); 492 } 493 494 @Test testUncacheShortcutsWhenNotificationsDismissed()495 public void testUncacheShortcutsWhenNotificationsDismissed() { 496 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 497 NotificationListenerService listenerService = 498 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 499 500 // The cached conversations are above the limit because every conversation has active 501 // notifications. To uncache one of them, the notifications for that conversation need to 502 // be dismissed. 503 String notificationKey = ""; 504 for (int i = 0; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) { 505 String shortcutId = TEST_SHORTCUT_ID + i; 506 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId, 507 buildPerson()); 508 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 509 mDataManager.addOrUpdateConversationInfo(shortcut); 510 when(mNotification.getShortcutId()).thenReturn(shortcutId); 511 notificationKey = String.format("notification-key-%d", i); 512 sendGenericNotificationWithKey(notificationKey); 513 } 514 515 // Post another notification for the last conversation. 516 String otherNotificationKey = "other-notification-key"; 517 sendGenericNotificationWithKey(otherNotificationKey); 518 519 // Removing one of the two notifications does not un-cache the shortcut. 520 listenerService.onNotificationRemoved(mGenericSbn, null, 521 NotificationListenerService.REASON_CANCEL); 522 verify(mShortcutServiceInternal, never()).uncacheShortcuts( 523 anyInt(), any(), anyString(), any(), anyInt(), anyInt()); 524 525 // Removing the second notification un-caches the shortcut. 526 when(mGenericSbn.getKey()).thenReturn(notificationKey); 527 listenerService.onNotificationRemoved(mGenericSbn, null, 528 NotificationListenerService.REASON_CANCEL_ALL); 529 verify(mShortcutServiceInternal).uncacheShortcuts( 530 anyInt(), any(), eq(TEST_PKG_NAME), anyList(), eq(USER_ID_PRIMARY), 531 eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 532 } 533 534 @Test testConversationIsNotRecentIfCustomized()535 public void testConversationIsNotRecentIfCustomized() { 536 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 537 538 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 539 buildPerson()); 540 mDataManager.addOrUpdateConversationInfo(shortcut); 541 542 NotificationListenerService listenerService = 543 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 544 545 sendGenericNotification(); 546 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 547 mDataManager.addOrUpdateConversationInfo(shortcut); 548 549 assertEquals(1, mDataManager.getRecentConversations(USER_ID_PRIMARY).size()); 550 551 listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY), 552 mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED); 553 554 assertTrue(mDataManager.getRecentConversations(USER_ID_PRIMARY).isEmpty()); 555 } 556 557 @Test testAddConversationsListener()558 public void testAddConversationsListener() throws Exception { 559 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 560 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 561 buildPerson()); 562 mDataManager.addOrUpdateConversationInfo(shortcut); 563 ConversationChannel conversationChannel = mDataManager.getConversation(TEST_PKG_NAME, 564 USER_ID_PRIMARY, 565 TEST_SHORTCUT_ID); 566 567 PeopleService.ConversationsListener listener = mock( 568 PeopleService.ConversationsListener.class); 569 mDataManager.addConversationsListener(listener); 570 571 List<ConversationChannel> changedConversations = Arrays.asList(conversationChannel); 572 verify(listener, times(0)).onConversationsUpdate(eq(changedConversations)); 573 mDataManager.notifyConversationsListeners(changedConversations); 574 mLooper.dispatchAll(); 575 576 verify(listener, times(1)).onConversationsUpdate(eq(changedConversations)); 577 } 578 579 @Test testAddConversationListenersNotifiesMultipleConversations()580 public void testAddConversationListenersNotifiesMultipleConversations() throws Exception { 581 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 582 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 583 buildPerson()); 584 mDataManager.addOrUpdateConversationInfo(shortcut); 585 ConversationChannel conversationChannel = mDataManager.getConversation(TEST_PKG_NAME, 586 USER_ID_PRIMARY, 587 TEST_SHORTCUT_ID); 588 ShortcutInfo shortcut2 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, 589 TEST_SHORTCUT_ID_2, 590 buildPerson()); 591 mDataManager.addOrUpdateConversationInfo(shortcut2); 592 mLooper.dispatchAll(); 593 ConversationChannel conversationChannel2 = mDataManager.getConversation(TEST_PKG_NAME, 594 USER_ID_PRIMARY, 595 TEST_SHORTCUT_ID_2); 596 PeopleService.ConversationsListener listener = mock( 597 PeopleService.ConversationsListener.class); 598 mDataManager.addConversationsListener(listener); 599 600 List<ConversationChannel> changedConversations = Arrays.asList(conversationChannel, 601 conversationChannel2); 602 verify(listener, times(0)).onConversationsUpdate(eq(changedConversations)); 603 mDataManager.notifyConversationsListeners(changedConversations); 604 mLooper.dispatchAll(); 605 606 verify(listener, times(1)).onConversationsUpdate(eq(changedConversations)); 607 ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass( 608 List.class); 609 verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture()); 610 assertThat(capturedConversation.getValue()).containsExactly(conversationChannel, 611 conversationChannel2); 612 } 613 614 @Test testAddOrUpdateStatusNotifiesConversationsListeners()615 public void testAddOrUpdateStatusNotifiesConversationsListeners() throws Exception { 616 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 617 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 618 buildPerson()); 619 mDataManager.addOrUpdateConversationInfo(shortcut); 620 mLooper.dispatchAll(); 621 PeopleService.ConversationsListener listener = mock( 622 PeopleService.ConversationsListener.class); 623 mDataManager.addConversationsListener(listener); 624 625 ConversationStatus status = new ConversationStatus.Builder("cs1", ACTIVITY_GAME).build(); 626 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, status); 627 mLooper.dispatchAll(); 628 629 ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass( 630 List.class); 631 verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture()); 632 ConversationChannel result = Iterables.getOnlyElement(capturedConversation.getValue()); 633 assertThat(result.getStatuses()).containsExactly(status); 634 assertEquals(result.getShortcutInfo().getId(), TEST_SHORTCUT_ID); 635 } 636 637 @Test testGetConversationReturnsCustomizedConversation()638 public void testGetConversationReturnsCustomizedConversation() { 639 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 640 641 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 642 buildPerson()); 643 mDataManager.addOrUpdateConversationInfo(shortcut); 644 645 sendConvoNotification(); 646 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 647 mDataManager.addOrUpdateConversationInfo(shortcut); 648 649 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 650 TEST_SHORTCUT_ID)).isNotNull(); 651 652 ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 653 TEST_SHORTCUT_ID); 654 assertThat(result).isNotNull(); 655 assertThat(result.hasBirthdayToday()).isFalse(); 656 assertThat(result.getStatuses()).isEmpty(); 657 } 658 659 @Test testGetConversation()660 public void testGetConversation() { 661 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 662 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 663 TEST_SHORTCUT_ID)).isNull(); 664 665 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 666 buildPerson()); 667 shortcut.setCached(ShortcutInfo.FLAG_PINNED); 668 mDataManager.addOrUpdateConversationInfo(shortcut); 669 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 670 TEST_SHORTCUT_ID)).isNotNull(); 671 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 672 TEST_SHORTCUT_ID + "1")).isNull(); 673 674 sendConvoNotification(); 675 ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build(); 676 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs); 677 678 ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 679 TEST_SHORTCUT_ID); 680 assertThat(result).isNotNull(); 681 assertEquals(shortcut.getId(), result.getShortcutInfo().getId()); 682 assertEquals(1, result.getShortcutInfo().getPersons().length); 683 assertEquals(CONTACT_URI, result.getShortcutInfo().getPersons()[0].getUri()); 684 assertEquals(mNotificationChannel.getId(), result.getNotificationChannel().getId()); 685 assertEquals(mParentNotificationChannel.getId(), 686 result.getNotificationChannel().getParentChannelId()); 687 assertEquals(mConvoSbn.getPostTime(), result.getLastEventTimestamp()); 688 assertTrue(result.hasActiveNotifications()); 689 assertFalse(result.hasBirthdayToday()); 690 assertThat(result.getStatuses()).containsExactly(cs); 691 } 692 693 @Test testGetConversation_trackActiveConversations()694 public void testGetConversation_trackActiveConversations() { 695 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 696 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 697 TEST_SHORTCUT_ID)).isNull(); 698 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 699 buildPerson()); 700 shortcut.setCached(ShortcutInfo.FLAG_PINNED); 701 mDataManager.addOrUpdateConversationInfo(shortcut); 702 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 703 TEST_SHORTCUT_ID)).isNotNull(); 704 705 sendGenericNotification(); 706 sendGenericNotification(); 707 ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 708 TEST_SHORTCUT_ID); 709 assertTrue(result.hasActiveNotifications()); 710 711 // Both generic notifications have the same notification key, so a single dismiss will 712 // remove both of them. 713 NotificationListenerService listenerService = 714 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 715 listenerService.onNotificationRemoved(mGenericSbn, null, 716 NotificationListenerService.REASON_CANCEL); 717 ConversationChannel resultTwo = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 718 TEST_SHORTCUT_ID); 719 assertFalse(resultTwo.hasActiveNotifications()); 720 } 721 722 @Test testGetConversation_unsyncedShortcut()723 public void testGetConversation_unsyncedShortcut() { 724 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 725 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 726 buildPerson()); 727 shortcut.setCached(ShortcutInfo.FLAG_PINNED); 728 mDataManager.addOrUpdateConversationInfo(shortcut); 729 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 730 TEST_SHORTCUT_ID)).isNotNull(); 731 assertThat(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY) 732 .getConversationStore() 733 .getConversation(TEST_SHORTCUT_ID)).isNotNull(); 734 735 when(mShortcutServiceInternal.getShortcuts( 736 anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(), 737 anyInt(), anyInt(), anyInt(), anyInt())) 738 .thenReturn(Collections.emptyList()); 739 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 740 TEST_SHORTCUT_ID)).isNull(); 741 742 // Conversation is removed from store as there is no matching shortcut in ShortcutManager 743 assertThat(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY) 744 .getConversationStore() 745 .getConversation(TEST_SHORTCUT_ID)).isNull(); 746 verify(mNotificationManagerInternal) 747 .onConversationRemoved(TEST_PKG_NAME, TEST_PKG_UID, Set.of(TEST_SHORTCUT_ID)); 748 } 749 750 @Test testOnNotificationChannelModified()751 public void testOnNotificationChannelModified() { 752 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 753 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 754 TEST_SHORTCUT_ID)).isNull(); 755 756 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 757 buildPerson()); 758 shortcut.setCached(ShortcutInfo.FLAG_PINNED); 759 mDataManager.addOrUpdateConversationInfo(shortcut); 760 761 sendConvoNotification(); 762 763 ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 764 TEST_SHORTCUT_ID); 765 assertFalse(result.getNotificationChannel().canBubble()); 766 767 NotificationChannel updated = new NotificationChannel(mNotificationChannel.getId(), 768 mNotificationChannel.getDescription(), mNotificationChannel.getImportance()); 769 updated.setConversationId(mNotificationChannel.getParentChannelId(), 770 mNotificationChannel.getConversationId()); 771 updated.setAllowBubbles(true); 772 NotificationListenerService listenerService = 773 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 774 listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY), 775 updated, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED); 776 777 ConversationInfo ci = mDataManager.getConversationInfo(TEST_PKG_NAME, USER_ID_PRIMARY, 778 TEST_SHORTCUT_ID); 779 assertThat(ci).isNotNull(); 780 assertEquals(mNotificationChannel.getId(), ci.getNotificationChannelId()); 781 assertEquals(mParentNotificationChannel.getId(), ci.getParentNotificationChannelId()); 782 assertTrue(ci.isBubbled()); 783 } 784 785 @Test testGetConversation_demoted()786 public void testGetConversation_demoted() { 787 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 788 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 789 TEST_SHORTCUT_ID)).isNull(); 790 791 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 792 buildPerson()); 793 shortcut.setCached(ShortcutInfo.FLAG_PINNED); 794 mDataManager.addOrUpdateConversationInfo(shortcut); 795 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 796 TEST_SHORTCUT_ID)).isNotNull(); 797 798 mNotificationChannel.setDemoted(true); 799 NotificationListenerService listenerService = 800 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 801 listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY), 802 mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED); 803 804 assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 805 TEST_SHORTCUT_ID)).isNull(); 806 } 807 808 @Test testGetConversationGetsPersonsData()809 public void testGetConversationGetsPersonsData() { 810 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 811 812 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 813 buildPerson()); 814 shortcut.setCached(ShortcutInfo.FLAG_PINNED); 815 mDataManager.addOrUpdateConversationInfo(shortcut); 816 817 sendGenericNotification(); 818 mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID); 819 820 verify(mShortcutServiceInternal).getShortcuts( 821 anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(), 822 mQueryFlagsCaptor.capture(), anyInt(), anyInt(), anyInt()); 823 Integer queryFlags = mQueryFlagsCaptor.getValue(); 824 assertThat(hasFlag(queryFlags, ShortcutQuery.FLAG_GET_PERSONS_DATA)).isTrue(); 825 } 826 827 @Test testIsConversation()828 public void testIsConversation() { 829 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 830 assertThat(mDataManager.isConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 831 TEST_SHORTCUT_ID)).isFalse(); 832 833 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 834 buildPerson()); 835 shortcut.setCached(ShortcutInfo.FLAG_PINNED); 836 mDataManager.addOrUpdateConversationInfo(shortcut); 837 assertThat(mDataManager.isConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 838 TEST_SHORTCUT_ID)).isTrue(); 839 assertThat(mDataManager.isConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 840 TEST_SHORTCUT_ID + "1")).isFalse(); 841 } 842 843 @Test testIsConversation_demoted()844 public void testIsConversation_demoted() { 845 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 846 assertThat(mDataManager.isConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 847 TEST_SHORTCUT_ID)).isFalse(); 848 849 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 850 buildPerson()); 851 shortcut.setCached(ShortcutInfo.FLAG_PINNED); 852 mDataManager.addOrUpdateConversationInfo(shortcut); 853 854 mNotificationChannel.setDemoted(true); 855 NotificationListenerService listenerService = 856 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 857 listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY), 858 mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED); 859 860 assertThat(mDataManager.isConversation(TEST_PKG_NAME, USER_ID_PRIMARY, 861 TEST_SHORTCUT_ID)).isFalse(); 862 } 863 864 @Test testNotificationChannelCreated()865 public void testNotificationChannelCreated() { 866 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 867 mDataManager.onUserUnlocked(USER_ID_SECONDARY); 868 869 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 870 buildPerson()); 871 mDataManager.addOrUpdateConversationInfo(shortcut); 872 873 NotificationListenerService listenerService = 874 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 875 listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY), 876 mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_ADDED); 877 878 ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY) 879 .getConversationStore() 880 .getConversation(TEST_SHORTCUT_ID); 881 assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId()); 882 assertFalse(conversationInfo.isImportant()); 883 assertFalse(conversationInfo.isNotificationSilenced()); 884 assertFalse(conversationInfo.isDemoted()); 885 } 886 887 @Test testNotificationChannelModified()888 public void testNotificationChannelModified() { 889 mNotificationChannel.setImportantConversation(true); 890 891 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 892 mDataManager.onUserUnlocked(USER_ID_SECONDARY); 893 894 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 895 buildPerson()); 896 mDataManager.addOrUpdateConversationInfo(shortcut); 897 898 NotificationListenerService listenerService = 899 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 900 listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY), 901 mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED); 902 903 ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY) 904 .getConversationStore() 905 .getConversation(TEST_SHORTCUT_ID); 906 assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId()); 907 assertTrue(conversationInfo.isImportant()); 908 assertFalse(conversationInfo.isNotificationSilenced()); 909 assertFalse(conversationInfo.isDemoted()); 910 } 911 912 @Test testNotificationChannelDeleted()913 public void testNotificationChannelDeleted() { 914 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 915 mDataManager.onUserUnlocked(USER_ID_SECONDARY); 916 917 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 918 buildPerson()); 919 mDataManager.addOrUpdateConversationInfo(shortcut); 920 921 NotificationListenerService listenerService = 922 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 923 listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY), 924 mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_ADDED); 925 ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY) 926 .getConversationStore() 927 .getConversation(TEST_SHORTCUT_ID); 928 assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId()); 929 930 listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY), 931 mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_DELETED); 932 conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY) 933 .getConversationStore() 934 .getConversation(TEST_SHORTCUT_ID); 935 assertNull(conversationInfo.getNotificationChannelId()); 936 assertFalse(conversationInfo.isImportant()); 937 assertFalse(conversationInfo.isNotificationSilenced()); 938 assertFalse(conversationInfo.isDemoted()); 939 } 940 941 @Test testShortcutAddedOrUpdated()942 public void testShortcutAddedOrUpdated() { 943 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 944 PeopleService.ConversationsListener listener = mock( 945 PeopleService.ConversationsListener.class); 946 mDataManager.addConversationsListener(listener); 947 948 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 949 buildPerson()); 950 mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME, 951 Collections.singletonList(shortcut), UserHandle.of(USER_ID_PRIMARY)); 952 mLooper.dispatchAll(); 953 954 List<ConversationInfo> conversations = getConversationsInPrimary(); 955 956 assertEquals(1, conversations.size()); 957 assertEquals(TEST_SHORTCUT_ID, conversations.get(0).getShortcutId()); 958 ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass( 959 List.class); 960 verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture()); 961 ConversationChannel result = Iterables.getOnlyElement(capturedConversation.getValue()); 962 assertEquals(result.getShortcutInfo().getId(), TEST_SHORTCUT_ID); 963 } 964 965 @Test testShortcutsDeleted()966 public void testShortcutsDeleted() { 967 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 968 969 ShortcutInfo shortcut1 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc1", 970 buildPerson()); 971 ShortcutInfo shortcut2 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc2", 972 buildPerson()); 973 ShortcutInfo shortcut3 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc3", 974 buildPerson()); 975 mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME, 976 Arrays.asList(shortcut1, shortcut2, shortcut3), UserHandle.of(USER_ID_PRIMARY)); 977 mShortcutChangeCallback.onShortcutsRemoved(TEST_PKG_NAME, 978 List.of(shortcut1, shortcut3), UserHandle.of(USER_ID_PRIMARY)); 979 980 List<ConversationInfo> conversations = getConversationsInPrimary(); 981 982 assertEquals(1, conversations.size()); 983 assertEquals("sc2", conversations.get(0).getShortcutId()); 984 985 verify(mNotificationManagerInternal) 986 .onConversationRemoved(TEST_PKG_NAME, TEST_PKG_UID, Set.of("sc1", "sc3")); 987 } 988 989 @Test testCallLogContentObserver()990 public void testCallLogContentObserver() { 991 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 992 mDataManager.onUserUnlocked(USER_ID_SECONDARY); 993 994 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 995 buildPerson()); 996 mDataManager.addOrUpdateConversationInfo(shortcut); 997 998 ContentObserver contentObserver = mDataManager.getCallLogContentObserverForTesting(); 999 contentObserver.onChange(false); 1000 long currentTimestamp = System.currentTimeMillis(); 1001 mInjector.mCallLogQueryHelper.mEventConsumer.accept(PHONE_NUMBER, 1002 new Event(currentTimestamp - MILLIS_PER_MINUTE * 15L, Event.TYPE_CALL_OUTGOING)); 1003 mInjector.mCallLogQueryHelper.mEventConsumer.accept(PHONE_NUMBER, 1004 new Event(currentTimestamp - MILLIS_PER_MINUTE * 10L, Event.TYPE_CALL_INCOMING)); 1005 mInjector.mCallLogQueryHelper.mEventConsumer.accept(PHONE_NUMBER, 1006 new Event(currentTimestamp - MILLIS_PER_MINUTE * 5L, Event.TYPE_CALL_MISSED)); 1007 1008 List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.CALL_EVENT_TYPES); 1009 assertEquals(3, activeTimeSlots.size()); 1010 } 1011 1012 @Test testMmsSmsContentObserver()1013 public void testMmsSmsContentObserver() { 1014 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1015 mDataManager.onUserUnlocked(USER_ID_SECONDARY); 1016 1017 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1018 buildPerson()); 1019 mDataManager.addOrUpdateConversationInfo(shortcut); 1020 mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultSmsApp(TEST_PKG_NAME); 1021 1022 ContentObserver contentObserver = mDataManager.getMmsSmsContentObserverForTesting(); 1023 contentObserver.onChange(false); 1024 long currentTimestamp = System.currentTimeMillis(); 1025 Event outgoingSmsEvent = 1026 new Event(currentTimestamp - MILLIS_PER_MINUTE * 10L, Event.TYPE_SMS_OUTGOING); 1027 Event incomingSmsEvent = 1028 new Event(currentTimestamp - MILLIS_PER_MINUTE * 5L, Event.TYPE_SMS_INCOMING); 1029 mInjector.mMmsQueryHelper.mEventConsumer.accept(PHONE_NUMBER, outgoingSmsEvent); 1030 mInjector.mSmsQueryHelper.mEventConsumer.accept(PHONE_NUMBER, incomingSmsEvent); 1031 1032 List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.SMS_EVENT_TYPES); 1033 assertEquals(2, activeTimeSlots.size()); 1034 } 1035 1036 @Test testConversationLastEventTimestampUpdate()1037 public void testConversationLastEventTimestampUpdate() { 1038 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1039 1040 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1041 buildPerson()); 1042 mDataManager.addOrUpdateConversationInfo(shortcut); 1043 1044 PackageData packageData = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY); 1045 ConversationInfo conversationInfo = 1046 packageData.getConversationStore().getConversation(TEST_SHORTCUT_ID); 1047 Event event = new Event(123L, Event.TYPE_IN_APP_CONVERSATION); 1048 1049 mInjector.mUsageStatsQueryHelper.mEventListener.onEvent(packageData, conversationInfo, 1050 event); 1051 ConversationInfo newConversationInfo = 1052 packageData.getConversationStore().getConversation(TEST_SHORTCUT_ID); 1053 assertEquals(123L, newConversationInfo.getLastEventTimestamp()); 1054 } 1055 1056 @Test testDeleteUninstalledPackageDataOnPackageRemoved()1057 public void testDeleteUninstalledPackageDataOnPackageRemoved() { 1058 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1059 1060 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1061 buildPerson()); 1062 mDataManager.addOrUpdateConversationInfo(shortcut); 1063 assertNotNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)); 1064 1065 PackageMonitor packageMonitor = mDataManager.getPackageMonitorForTesting(USER_ID_PRIMARY); 1066 Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED); 1067 intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_PRIMARY); 1068 intent.setData(Uri.parse("package:" + TEST_PKG_NAME)); 1069 packageMonitor.onReceive(mContext, intent); 1070 assertNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)); 1071 } 1072 1073 @Test testPruneUninstalledPackageData()1074 public void testPruneUninstalledPackageData() { 1075 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1076 1077 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1078 buildPerson()); 1079 mDataManager.addOrUpdateConversationInfo(shortcut); 1080 assertNotNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)); 1081 1082 doAnswer(ans -> null).when(mPackageManagerInternal) 1083 .forEachInstalledPackage(any(Consumer.class), anyInt()); 1084 mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal); 1085 assertNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)); 1086 } 1087 1088 @Test testPruneCallEventsFromNonDialer()1089 public void testPruneCallEventsFromNonDialer() { 1090 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1091 1092 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1093 buildPerson()); 1094 mDataManager.addOrUpdateConversationInfo(shortcut); 1095 1096 long currentTimestamp = System.currentTimeMillis(); 1097 mInjector.mCallLogQueryHelper.mEventConsumer.accept(PHONE_NUMBER, 1098 new Event(currentTimestamp - MILLIS_PER_MINUTE, Event.TYPE_CALL_OUTGOING)); 1099 1100 List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.CALL_EVENT_TYPES); 1101 assertEquals(1, activeTimeSlots.size()); 1102 1103 mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultDialer(null); 1104 mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal); 1105 activeTimeSlots = getActiveSlotsForTestShortcut(Event.CALL_EVENT_TYPES); 1106 assertTrue(activeTimeSlots.isEmpty()); 1107 } 1108 1109 @Test testPruneSmsEventsFromNonDefaultSmsApp()1110 public void testPruneSmsEventsFromNonDefaultSmsApp() { 1111 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1112 1113 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1114 buildPerson()); 1115 mDataManager.addOrUpdateConversationInfo(shortcut); 1116 mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultSmsApp(TEST_PKG_NAME); 1117 1118 long currentTimestamp = System.currentTimeMillis(); 1119 mInjector.mMmsQueryHelper.mEventConsumer.accept(PHONE_NUMBER, 1120 new Event(currentTimestamp - MILLIS_PER_MINUTE, Event.TYPE_SMS_OUTGOING)); 1121 1122 List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.SMS_EVENT_TYPES); 1123 assertEquals(1, activeTimeSlots.size()); 1124 1125 mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultSmsApp(null); 1126 mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal); 1127 activeTimeSlots = getActiveSlotsForTestShortcut(Event.SMS_EVENT_TYPES); 1128 assertTrue(activeTimeSlots.isEmpty()); 1129 } 1130 1131 @Test testPruneExpiredConversationStatuses()1132 public void testPruneExpiredConversationStatuses() { 1133 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1134 1135 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1136 buildPerson()); 1137 mDataManager.addOrUpdateConversationInfo(shortcut); 1138 1139 ConversationStatus cs1 = new ConversationStatus.Builder("cs1", 9) 1140 .setEndTimeMillis(System.currentTimeMillis()) 1141 .build(); 1142 ConversationStatus cs2 = new ConversationStatus.Builder("cs2", 10) 1143 .build(); 1144 ConversationStatus cs3 = new ConversationStatus.Builder("cs3", 1) 1145 .setEndTimeMillis(Long.MAX_VALUE) 1146 .build(); 1147 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs1); 1148 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2); 1149 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs3); 1150 mLooper.dispatchAll(); 1151 1152 PeopleService.ConversationsListener listener = mock( 1153 PeopleService.ConversationsListener.class); 1154 mDataManager.addConversationsListener(listener); 1155 mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal); 1156 mLooper.dispatchAll(); 1157 1158 assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID)) 1159 .doesNotContain(cs1); 1160 assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID)) 1161 .contains(cs2); 1162 assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID)) 1163 .contains(cs3); 1164 ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass( 1165 List.class); 1166 verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture()); 1167 List<ConversationChannel> results = capturedConversation.getValue(); 1168 ConversationChannel result = Iterables.getOnlyElement(capturedConversation.getValue()); 1169 // CHeck cs1 has been removed and only cs2 and cs3 remain. 1170 assertThat(result.getStatuses()).containsExactly(cs2, cs3); 1171 } 1172 1173 @Test testDoNotUncacheShortcutWithActiveNotifications()1174 public void testDoNotUncacheShortcutWithActiveNotifications() { 1175 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1176 NotificationListenerService listenerService = 1177 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 1178 1179 for (int i = 0; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) { 1180 String shortcutId = TEST_SHORTCUT_ID + i; 1181 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId, 1182 buildPerson()); 1183 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1184 mDataManager.addOrUpdateConversationInfo(shortcut); 1185 when(mNotification.getShortcutId()).thenReturn(shortcutId); 1186 sendGenericNotification(); 1187 } 1188 1189 mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal); 1190 1191 verify(mShortcutServiceInternal, never()).uncacheShortcuts( 1192 anyInt(), anyString(), anyString(), anyList(), anyInt(), anyInt()); 1193 } 1194 1195 @Test testUncacheOldestCachedShortcut()1196 public void testUncacheOldestCachedShortcut() { 1197 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1198 NotificationListenerService listenerService = 1199 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 1200 1201 for (int i = 0; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) { 1202 String shortcutId = TEST_SHORTCUT_ID + i; 1203 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId, 1204 buildPerson()); 1205 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1206 mDataManager.addOrUpdateConversationInfo(shortcut); 1207 when(mNotification.getShortcutId()).thenReturn(shortcutId); 1208 when(mGenericSbn.getPostTime()).thenReturn(100L + i); 1209 sendGenericNotification(); 1210 listenerService.onNotificationRemoved(mGenericSbn, null, 1211 NotificationListenerService.REASON_CANCEL); 1212 } 1213 1214 // Only the shortcut #0 is uncached, all the others are not. 1215 verify(mShortcutServiceInternal).uncacheShortcuts( 1216 anyInt(), any(), eq(TEST_PKG_NAME), 1217 eq(Collections.singletonList(TEST_SHORTCUT_ID + 0)), eq(USER_ID_PRIMARY), 1218 eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 1219 for (int i = 1; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) { 1220 verify(mShortcutServiceInternal, never()).uncacheShortcuts( 1221 anyInt(), anyString(), anyString(), 1222 eq(Collections.singletonList(TEST_SHORTCUT_ID + i)), anyInt(), 1223 eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 1224 } 1225 } 1226 1227 @Test testUncacheOldestCachedShortcut_missingNotificationEvents()1228 public void testUncacheOldestCachedShortcut_missingNotificationEvents() { 1229 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1230 1231 for (int i = 0; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) { 1232 String shortcutId = TEST_SHORTCUT_ID + i; 1233 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId, 1234 buildPerson()); 1235 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1236 mShortcutChangeCallback.onShortcutsAddedOrUpdated( 1237 TEST_PKG_NAME, 1238 Collections.singletonList(shortcut), 1239 UserHandle.of(USER_ID_PRIMARY)); 1240 mLooper.dispatchAll(); 1241 } 1242 1243 // Only the shortcut #0 is uncached, all the others are not. 1244 verify(mShortcutServiceInternal).uncacheShortcuts( 1245 anyInt(), any(), eq(TEST_PKG_NAME), 1246 eq(Collections.singletonList(TEST_SHORTCUT_ID + 0)), eq(USER_ID_PRIMARY), 1247 eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 1248 for (int i = 1; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) { 1249 verify(mShortcutServiceInternal, never()).uncacheShortcuts( 1250 anyInt(), anyString(), anyString(), 1251 eq(Collections.singletonList(TEST_SHORTCUT_ID + i)), anyInt(), 1252 eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 1253 } 1254 } 1255 1256 @Test testUncacheOldestCachedShortcut_legacyConversation()1257 public void testUncacheOldestCachedShortcut_legacyConversation() { 1258 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1259 1260 // Add an extra conversation with a legacy type (no creationTime) 1261 ConversationStore conversationStore = mDataManager 1262 .getUserDataForTesting(USER_ID_PRIMARY) 1263 .getOrCreatePackageData(TEST_PKG_NAME) 1264 .getConversationStore(); 1265 ConversationInfo.Builder builder = new ConversationInfo.Builder(); 1266 builder.setShortcutId(TEST_SHORTCUT_ID + 0); 1267 builder.setShortcutFlags(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1268 mDataManager.updateConversationStoreThenNotifyListeners( 1269 conversationStore, 1270 builder.build(), 1271 TEST_PKG_NAME, USER_ID_PRIMARY); 1272 for (int i = 1; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) { 1273 String shortcutId = TEST_SHORTCUT_ID + i; 1274 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId, 1275 buildPerson()); 1276 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1277 mShortcutChangeCallback.onShortcutsAddedOrUpdated( 1278 TEST_PKG_NAME, 1279 Collections.singletonList(shortcut), 1280 UserHandle.of(USER_ID_PRIMARY)); 1281 mLooper.dispatchAll(); 1282 } 1283 1284 // Only the shortcut #0 is uncached, all the others are not. 1285 verify(mShortcutServiceInternal).uncacheShortcuts( 1286 anyInt(), any(), eq(TEST_PKG_NAME), 1287 eq(Collections.singletonList(TEST_SHORTCUT_ID + 0)), eq(USER_ID_PRIMARY), 1288 eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 1289 for (int i = 1; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) { 1290 verify(mShortcutServiceInternal, never()).uncacheShortcuts( 1291 anyInt(), anyString(), anyString(), 1292 eq(Collections.singletonList(TEST_SHORTCUT_ID + i)), anyInt(), 1293 eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 1294 } 1295 } 1296 1297 @Test testBackupAndRestoration()1298 public void testBackupAndRestoration() 1299 throws IntentFilter.MalformedMimeTypeException { 1300 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1301 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1302 null); 1303 AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut) 1304 .build(); 1305 AppTargetEvent appTargetEvent = 1306 new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH) 1307 .setLaunchLocation(ChooserActivity.LAUNCH_LOCATION_DIRECT_SHARE) 1308 .build(); 1309 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg"); 1310 1311 mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter); 1312 byte[] payload = mDataManager.getBackupPayload(USER_ID_PRIMARY); 1313 1314 DataManager dataManager = new DataManager(mContext, mInjector, mLooper.getLooper()); 1315 dataManager.onUserUnlocked(USER_ID_PRIMARY); 1316 dataManager.restore(USER_ID_PRIMARY, payload); 1317 ConversationInfo conversationInfo = dataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY) 1318 .getConversationStore() 1319 .getConversation(TEST_SHORTCUT_ID); 1320 assertNotNull(conversationInfo); 1321 assertEquals(conversationInfo.getShortcutId(), TEST_SHORTCUT_ID); 1322 } 1323 1324 @Test testGetRecentConversations()1325 public void testGetRecentConversations() { 1326 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1327 1328 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1329 buildPerson()); 1330 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1331 mDataManager.addOrUpdateConversationInfo(shortcut); 1332 1333 sendGenericNotification(); 1334 1335 List<ConversationChannel> result = mDataManager.getRecentConversations(USER_ID_PRIMARY); 1336 assertEquals(1, result.size()); 1337 assertEquals(shortcut.getId(), result.get(0).getShortcutInfo().getId()); 1338 assertEquals(1, result.get(0).getShortcutInfo().getPersons().length); 1339 assertEquals(CONTACT_URI, result.get(0).getShortcutInfo().getPersons()[0].getUri()); 1340 assertEquals(mParentNotificationChannel.getId(), 1341 result.get(0).getNotificationChannel().getId()); 1342 assertEquals(null, result.get(0).getNotificationChannel().getParentChannelId()); 1343 assertEquals(mGenericSbn.getPostTime(), result.get(0).getLastEventTimestamp()); 1344 assertTrue(result.get(0).hasActiveNotifications()); 1345 } 1346 1347 @Test testGetRecentConversationsGetsPersonsData()1348 public void testGetRecentConversationsGetsPersonsData() { 1349 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1350 1351 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1352 buildPerson()); 1353 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1354 mDataManager.addOrUpdateConversationInfo(shortcut); 1355 1356 sendGenericNotification(); 1357 1358 mDataManager.getRecentConversations(USER_ID_PRIMARY); 1359 1360 verify(mShortcutServiceInternal).getShortcuts( 1361 anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(), 1362 mQueryFlagsCaptor.capture(), anyInt(), anyInt(), anyInt()); 1363 Integer queryFlags = mQueryFlagsCaptor.getValue(); 1364 assertThat(hasFlag(queryFlags, ShortcutQuery.FLAG_GET_PERSONS_DATA)).isTrue(); 1365 } 1366 1367 @Test testPruneOldRecentConversations()1368 public void testPruneOldRecentConversations() { 1369 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1370 1371 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1372 buildPerson()); 1373 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1374 mDataManager.addOrUpdateConversationInfo(shortcut); 1375 1376 NotificationListenerService listenerService = 1377 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 1378 when(mNotification.getShortcutId()).thenReturn(TEST_SHORTCUT_ID); 1379 sendGenericNotification(); 1380 listenerService.onNotificationRemoved(mGenericSbn, null, 1381 NotificationListenerService.REASON_CLICK); 1382 1383 mDataManager.pruneOldRecentConversations(USER_ID_PRIMARY, 1384 System.currentTimeMillis() + (10 * DateUtils.DAY_IN_MILLIS) + 1); 1385 1386 verify(mShortcutServiceInternal).uncacheShortcuts( 1387 anyInt(), any(), eq(TEST_PKG_NAME), eq(Collections.singletonList(TEST_SHORTCUT_ID)), 1388 eq(USER_ID_PRIMARY), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 1389 } 1390 1391 @Test testGetLastInteraction()1392 public void testGetLastInteraction() { 1393 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1394 1395 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1396 buildPerson()); 1397 mDataManager.addOrUpdateConversationInfo(shortcut); 1398 1399 sendGenericNotification(); 1400 1401 assertEquals(mGenericSbn.getPostTime(), 1402 mDataManager.getLastInteraction(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID)); 1403 assertEquals(0L, 1404 mDataManager.getLastInteraction("not_test_pkg", USER_ID_PRIMARY, TEST_SHORTCUT_ID)); 1405 assertEquals(0L, 1406 mDataManager.getLastInteraction(TEST_PKG_NAME, USER_ID_PRIMARY_MANAGED, 1407 TEST_SHORTCUT_ID)); 1408 assertEquals(0L, 1409 mDataManager.getLastInteraction(TEST_PKG_NAME, USER_ID_SECONDARY, 1410 TEST_SHORTCUT_ID)); 1411 } 1412 1413 @Test testAddOrUpdateStatus_noCachedShortcut()1414 public void testAddOrUpdateStatus_noCachedShortcut() { 1415 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1416 1417 ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build(); 1418 1419 try { 1420 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs); 1421 fail("Updated a conversation info that didn't previously exist"); 1422 } catch (IllegalArgumentException e) { 1423 // good 1424 } 1425 } 1426 1427 @Test testAddOrUpdateStatus()1428 public void testAddOrUpdateStatus() { 1429 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1430 1431 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1432 buildPerson()); 1433 mDataManager.addOrUpdateConversationInfo(shortcut); 1434 1435 ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build(); 1436 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs); 1437 1438 assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID)) 1439 .contains(cs); 1440 1441 ConversationStatus cs2 = new ConversationStatus.Builder("id2", ACTIVITY_GAME).build(); 1442 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2); 1443 1444 assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID)) 1445 .contains(cs); 1446 assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID)) 1447 .contains(cs2); 1448 1449 verify(mAlarmManager, never()).setExactAndAllowWhileIdle(anyInt(), anyLong(), any()); 1450 } 1451 1452 @Test testAddOrUpdateStatus_schedulesJob()1453 public void testAddOrUpdateStatus_schedulesJob() { 1454 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1455 1456 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1457 buildPerson()); 1458 mDataManager.addOrUpdateConversationInfo(shortcut); 1459 1460 ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY) 1461 .setEndTimeMillis(1000) 1462 .build(); 1463 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs); 1464 1465 ConversationStatus cs2 = new ConversationStatus.Builder("id2", ACTIVITY_GAME) 1466 .setEndTimeMillis(3000) 1467 .build(); 1468 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2); 1469 1470 verify(mAlarmManager, times(2)).setExactAndAllowWhileIdle(anyInt(), anyLong(), any()); 1471 } 1472 1473 @Test testClearStatus()1474 public void testClearStatus() { 1475 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1476 1477 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1478 buildPerson()); 1479 mDataManager.addOrUpdateConversationInfo(shortcut); 1480 1481 ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build(); 1482 ConversationStatus cs2 = new ConversationStatus.Builder("id2", ACTIVITY_GAME).build(); 1483 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs); 1484 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2); 1485 mLooper.dispatchAll(); 1486 1487 PeopleService.ConversationsListener listener = mock( 1488 PeopleService.ConversationsListener.class); 1489 mDataManager.addConversationsListener(listener); 1490 mDataManager.clearStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2.getId()); 1491 mLooper.dispatchAll(); 1492 1493 assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID)) 1494 .contains(cs); 1495 assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID)) 1496 .doesNotContain(cs2); 1497 ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass( 1498 List.class); 1499 verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture()); 1500 ConversationChannel result = Iterables.getOnlyElement(capturedConversation.getValue()); 1501 assertThat(result.getStatuses()).containsExactly(cs); 1502 } 1503 1504 @Test testClearStatuses()1505 public void testClearStatuses() { 1506 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1507 1508 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1509 buildPerson()); 1510 mDataManager.addOrUpdateConversationInfo(shortcut); 1511 1512 ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY).build(); 1513 ConversationStatus cs2 = new ConversationStatus.Builder("id2", ACTIVITY_GAME).build(); 1514 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs); 1515 mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2); 1516 mLooper.dispatchAll(); 1517 1518 PeopleService.ConversationsListener listener = mock( 1519 PeopleService.ConversationsListener.class); 1520 mDataManager.addConversationsListener(listener); 1521 mDataManager.clearStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID); 1522 mLooper.dispatchAll(); 1523 1524 assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID)) 1525 .isEmpty(); 1526 ArgumentCaptor<List<ConversationChannel>> capturedConversation = ArgumentCaptor.forClass( 1527 List.class); 1528 verify(listener, times(1)).onConversationsUpdate(capturedConversation.capture()); 1529 ConversationChannel result = Iterables.getOnlyElement(capturedConversation.getValue()); 1530 assertThat(result.getStatuses()).isEmpty(); 1531 } 1532 1533 @Test testNonCachedShortcutNotInRecentList()1534 public void testNonCachedShortcutNotInRecentList() { 1535 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1536 1537 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY_MANAGED, 1538 TEST_SHORTCUT_ID, buildPerson()); 1539 mDataManager.addOrUpdateConversationInfo(shortcut); 1540 1541 sendGenericNotification(); 1542 1543 List<ConversationChannel> result = mDataManager.getRecentConversations(USER_ID_PRIMARY); 1544 assertTrue(result.isEmpty()); 1545 } 1546 1547 @Test testCustomizedConversationNotInRecentList()1548 public void testCustomizedConversationNotInRecentList() { 1549 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1550 1551 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1552 buildPerson()); 1553 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1554 mDataManager.addOrUpdateConversationInfo(shortcut); 1555 1556 // Post a notification and customize the notification settings. 1557 NotificationListenerService listenerService = 1558 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 1559 sendGenericNotification(); 1560 listenerService.onNotificationChannelModified(TEST_PKG_NAME, UserHandle.of(USER_ID_PRIMARY), 1561 mNotificationChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED); 1562 1563 List<ConversationChannel> result = mDataManager.getRecentConversations(USER_ID_PRIMARY); 1564 assertTrue(result.isEmpty()); 1565 } 1566 1567 @Test testNotificationRemoved()1568 public void testNotificationRemoved() { 1569 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1570 1571 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1572 buildPerson()); 1573 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1574 mDataManager.addOrUpdateConversationInfo(shortcut); 1575 1576 NotificationListenerService listenerService = 1577 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 1578 sendGenericNotification(); 1579 // posting updates the last interaction time, so delay before deletion 1580 try { 1581 Thread.sleep(500); 1582 } catch (InterruptedException e) { 1583 e.printStackTrace(); 1584 } 1585 long approxDeletionTime = System.currentTimeMillis(); 1586 listenerService.onNotificationRemoved(mGenericSbn, null, 1587 NotificationListenerService.REASON_CANCEL); 1588 1589 ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY) 1590 .getConversationStore() 1591 .getConversation(TEST_SHORTCUT_ID); 1592 assertTrue(conversationInfo.getLastEventTimestamp() - approxDeletionTime < 100); 1593 } 1594 1595 @Test 1596 public void testRemoveRecentConversation() { 1597 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1598 1599 ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1600 buildPerson()); 1601 shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1602 mDataManager.addOrUpdateConversationInfo(shortcut); 1603 1604 NotificationListenerService listenerService = 1605 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 1606 sendGenericNotification(); 1607 listenerService.onNotificationRemoved(mGenericSbn, null, 1608 NotificationListenerService.REASON_CANCEL); 1609 mDataManager.removeRecentConversation(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, 1610 USER_ID_PRIMARY); 1611 1612 verify(mShortcutServiceInternal).uncacheShortcuts( 1613 anyInt(), any(), eq(TEST_PKG_NAME), eq(Collections.singletonList(TEST_SHORTCUT_ID)), 1614 eq(USER_ID_PRIMARY), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 1615 } 1616 1617 @Test 1618 public void testRemoveAllRecentConversations() { 1619 mDataManager.onUserUnlocked(USER_ID_PRIMARY); 1620 1621 ShortcutInfo shortcut1 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "1", 1622 buildPerson()); 1623 shortcut1.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1624 mDataManager.addOrUpdateConversationInfo(shortcut1); 1625 1626 ShortcutInfo shortcut2 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "2", 1627 buildPerson()); 1628 shortcut2.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS); 1629 mDataManager.addOrUpdateConversationInfo(shortcut2); 1630 1631 NotificationListenerService listenerService = 1632 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 1633 1634 // Post a notification and then dismiss it for conversation #1. 1635 when(mNotification.getShortcutId()).thenReturn("1"); 1636 sendGenericNotification(); 1637 listenerService.onNotificationRemoved(mGenericSbn, null, 1638 NotificationListenerService.REASON_CANCEL); 1639 1640 // Post a notification for conversation #2, but don't dismiss it. Its shortcut won't be 1641 // uncached when removeAllRecentConversations() is called. 1642 when(mNotification.getShortcutId()).thenReturn("2"); 1643 sendGenericNotification(); 1644 1645 mDataManager.removeAllRecentConversations(USER_ID_PRIMARY); 1646 1647 verify(mShortcutServiceInternal).uncacheShortcuts( 1648 anyInt(), any(), eq(TEST_PKG_NAME), eq(Collections.singletonList("1")), 1649 eq(USER_ID_PRIMARY), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 1650 verify(mShortcutServiceInternal, never()).uncacheShortcuts( 1651 anyInt(), any(), eq(TEST_PKG_NAME), eq(Collections.singletonList("2")), 1652 eq(USER_ID_PRIMARY), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS)); 1653 } 1654 1655 private static <T> void addLocalServiceMock(Class<T> clazz, T mock) { 1656 LocalServices.removeServiceForTest(clazz); 1657 LocalServices.addService(clazz, mock); 1658 } 1659 1660 private List<ConversationInfo> getConversationsInPrimary() { 1661 List<ConversationInfo> conversations = new ArrayList<>(); 1662 mDataManager.forPackagesInProfile(USER_ID_PRIMARY, 1663 packageData -> packageData.forAllConversations(conversations::add)); 1664 return conversations; 1665 } 1666 getActiveSlotsForTestShortcut(Set<Integer> eventTypes)1667 private List<Range<Long>> getActiveSlotsForTestShortcut(Set<Integer> eventTypes) { 1668 List<Range<Long>> activeSlots = new ArrayList<>(); 1669 mDataManager.forPackagesInProfile(USER_ID_PRIMARY, packageData -> 1670 activeSlots.addAll( 1671 packageData.getEventHistory(TEST_SHORTCUT_ID) 1672 .getEventIndex(eventTypes) 1673 .getActiveTimeSlots())); 1674 return activeSlots; 1675 } 1676 getActiveSlotsForAppShares()1677 private List<Range<Long>> getActiveSlotsForAppShares() { 1678 List<Range<Long>> activeSlots = new ArrayList<>(); 1679 mDataManager.forPackagesInProfile(USER_ID_PRIMARY, packageData -> 1680 activeSlots.addAll( 1681 packageData.getClassLevelEventHistory(TEST_CLASS_NAME) 1682 .getEventIndex(Event.SHARE_EVENT_TYPES) 1683 .getActiveTimeSlots())); 1684 return activeSlots; 1685 } 1686 buildShortcutInfo(String packageName, int userId, String id, @Nullable Person person)1687 private ShortcutInfo buildShortcutInfo(String packageName, int userId, String id, 1688 @Nullable Person person) { 1689 Context mockContext = mock(Context.class); 1690 when(mockContext.getPackageName()).thenReturn(packageName); 1691 when(mockContext.getUserId()).thenReturn(userId); 1692 when(mockContext.getUser()).thenReturn(UserHandle.of(userId)); 1693 ShortcutInfo.Builder builder = new ShortcutInfo.Builder(mockContext, id) 1694 .setShortLabel(id) 1695 .setLongLived(true) 1696 .setIntent(new Intent("TestIntent")); 1697 if (person != null) { 1698 builder.setPersons(new Person[]{person}); 1699 } 1700 return builder.build(); 1701 } 1702 buildPerson()1703 private Person buildPerson() { 1704 return buildPerson(true, false); 1705 } 1706 buildPerson(boolean isImportant, boolean isBot)1707 private Person buildPerson(boolean isImportant, boolean isBot) { 1708 return new Person.Builder() 1709 .setImportant(isImportant) 1710 .setBot(isBot) 1711 .setUri(CONTACT_URI) 1712 .build(); 1713 } 1714 buildUserInfo(int userId)1715 private UserInfo buildUserInfo(int userId) { 1716 return new UserInfo(userId, "", 0); 1717 } 1718 1719 /** 1720 * Returns {@code true} iff {@link ShortcutQuery}'s {@code queryFlags} has {@code flag} set. 1721 */ hasFlag(int queryFlags, int flag)1722 private static boolean hasFlag(int queryFlags, int flag) { 1723 return (queryFlags & flag) != 0; 1724 } 1725 1726 // "Sends" a notification to a non-customized notification channel - the notification channel 1727 // is something generic like "messages" and the notification has a shortcut id sendGenericNotification()1728 private void sendGenericNotification() { 1729 sendGenericNotificationWithKey(GENERIC_KEY); 1730 } 1731 1732 // "Sends" a notification to a non-customized notification channel with the specified key. sendGenericNotificationWithKey(String key)1733 private void sendGenericNotificationWithKey(String key) { 1734 when(mGenericSbn.getKey()).thenReturn(key); 1735 when(mNotification.getChannelId()).thenReturn(PARENT_NOTIFICATION_CHANNEL_ID); 1736 doAnswer(invocationOnMock -> { 1737 NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking) 1738 invocationOnMock.getArguments()[1]; 1739 ranking.populate( 1740 /* key= */ (String) invocationOnMock.getArguments()[0], 1741 /* rank= */ 0, 1742 /* matchesInterruptionFilter= */ false, 1743 /* visibilityOverride= */ 0, 1744 /* suppressedVisualEffects= */ 0, 1745 mParentNotificationChannel.getImportance(), 1746 /* explanation= */ null, 1747 /* overrideGroupKey= */ null, 1748 mParentNotificationChannel, 1749 /* overridePeople= */ null, 1750 /* snoozeCriteria= */ null, 1751 /* showBadge= */ true, 1752 /* userSentiment= */ 0, 1753 /* hidden= */ false, 1754 /* lastAudiblyAlertedMs= */ -1, 1755 /* noisy= */ false, 1756 /* smartActions= */ null, 1757 /* smartReplies= */ null, 1758 /* canBubble= */ false, 1759 /* isTextChanged= */ false, 1760 /* isConversation= */ false, 1761 /* shortcutInfo= */ null, 1762 /* rankingAdjustment= */ 0, 1763 /* isBubble= */ false, 1764 /* proposedImportance= */ 0, 1765 /* sensitiveContent= */ false 1766 ); 1767 return true; 1768 }).when(mRankingMap).getRanking(eq(key), 1769 any(NotificationListenerService.Ranking.class)); 1770 NotificationListenerService listenerService = 1771 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 1772 listenerService.onNotificationPosted(mGenericSbn, mRankingMap); 1773 } 1774 1775 // "Sends" a notification to a customized notification channel - the notification channel 1776 // is specific to a person, and the channel has a convo id matching the notification's shortcut 1777 // and the channel has a parent channel id sendConvoNotification()1778 private void sendConvoNotification() { 1779 when(mNotification.getChannelId()).thenReturn(NOTIFICATION_CHANNEL_ID); 1780 doAnswer(invocationOnMock -> { 1781 NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking) 1782 invocationOnMock.getArguments()[1]; 1783 ranking.populate( 1784 /* key= */ (String) invocationOnMock.getArguments()[0], 1785 /* rank= */ 0, 1786 /* matchesInterruptionFilter= */ false, 1787 /* visibilityOverride= */ 0, 1788 /* suppressedVisualEffects= */ 0, 1789 mParentNotificationChannel.getImportance(), 1790 /* explanation= */ null, 1791 /* overrideGroupKey= */ null, 1792 mParentNotificationChannel, 1793 /* overridePeople= */ null, 1794 /* snoozeCriteria= */ null, 1795 /* showBadge= */ true, 1796 /* userSentiment= */ 0, 1797 /* hidden= */ false, 1798 /* lastAudiblyAlertedMs= */ -1, 1799 /* noisy= */ false, 1800 /* smartActions= */ null, 1801 /* smartReplies= */ null, 1802 /* canBubble= */ false, 1803 /* isTextChanged= */ false, 1804 /* isConversation= */ false, 1805 /* shortcutInfo= */ null, 1806 /* rankingAdjustment= */ 0, 1807 /* isBubble= */ false, 1808 /* proposedImportance= */ 0, 1809 /* sensitiveContent= */ false 1810 ); 1811 return true; 1812 }).when(mRankingMap).getRanking(eq(CUSTOM_KEY), 1813 any(NotificationListenerService.Ranking.class)); 1814 1815 NotificationListenerService listenerService = 1816 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY); 1817 listenerService.onNotificationPosted(mConvoSbn, mRankingMap); 1818 } 1819 1820 private class TestContactsQueryHelper extends ContactsQueryHelper { 1821 1822 private Uri mContactUri; 1823 private boolean mIsStarred; 1824 private String mPhoneNumber; 1825 TestContactsQueryHelper(Context context)1826 TestContactsQueryHelper(Context context) { 1827 super(context); 1828 mContactUri = Uri.parse(CONTACT_URI); 1829 mIsStarred = false; 1830 mPhoneNumber = PHONE_NUMBER; 1831 } 1832 1833 @Override query(@onNull String contactUri)1834 boolean query(@NonNull String contactUri) { 1835 return true; 1836 } 1837 1838 @Override querySince(long sinceTime)1839 boolean querySince(long sinceTime) { 1840 return true; 1841 } 1842 1843 @Override 1844 @Nullable getContactUri()1845 Uri getContactUri() { 1846 return mContactUri; 1847 } 1848 1849 @Override isStarred()1850 boolean isStarred() { 1851 return mIsStarred; 1852 } 1853 1854 @Override 1855 @Nullable getPhoneNumber()1856 String getPhoneNumber() { 1857 return mPhoneNumber; 1858 } 1859 } 1860 1861 private class TestCallLogQueryHelper extends CallLogQueryHelper { 1862 1863 private final BiConsumer<String, Event> mEventConsumer; 1864 TestCallLogQueryHelper(Context context, BiConsumer<String, Event> eventConsumer)1865 TestCallLogQueryHelper(Context context, BiConsumer<String, Event> eventConsumer) { 1866 super(context, eventConsumer); 1867 mEventConsumer = eventConsumer; 1868 } 1869 1870 @Override querySince(long sinceTime)1871 boolean querySince(long sinceTime) { 1872 return true; 1873 } 1874 1875 @Override getLastCallTimestamp()1876 long getLastCallTimestamp() { 1877 return 100L; 1878 } 1879 } 1880 1881 private class TestSmsQueryHelper extends SmsQueryHelper { 1882 1883 private final BiConsumer<String, Event> mEventConsumer; 1884 TestSmsQueryHelper(Context context, BiConsumer<String, Event> eventConsumer)1885 TestSmsQueryHelper(Context context, BiConsumer<String, Event> eventConsumer) { 1886 super(context, eventConsumer); 1887 mEventConsumer = eventConsumer; 1888 } 1889 1890 @Override querySince(long sinceTime)1891 boolean querySince(long sinceTime) { 1892 return true; 1893 } 1894 1895 @Override getLastMessageTimestamp()1896 long getLastMessageTimestamp() { 1897 return 100L; 1898 } 1899 } 1900 1901 private class TestMmsQueryHelper extends MmsQueryHelper { 1902 1903 private final BiConsumer<String, Event> mEventConsumer; 1904 TestMmsQueryHelper(Context context, BiConsumer<String, Event> eventConsumer)1905 TestMmsQueryHelper(Context context, BiConsumer<String, Event> eventConsumer) { 1906 super(context, eventConsumer); 1907 mEventConsumer = eventConsumer; 1908 } 1909 1910 @Override querySince(long sinceTime)1911 boolean querySince(long sinceTime) { 1912 return true; 1913 } 1914 1915 @Override getLastMessageTimestamp()1916 long getLastMessageTimestamp() { 1917 return 100L; 1918 } 1919 } 1920 1921 private class TestUsageStatsQueryHelper extends UsageStatsQueryHelper { 1922 1923 private final EventListener mEventListener; 1924 TestUsageStatsQueryHelper(int userId, Function<String, PackageData> packageDataGetter, EventListener eventListener)1925 TestUsageStatsQueryHelper(int userId, 1926 Function<String, PackageData> packageDataGetter, 1927 EventListener eventListener) { 1928 super(userId, packageDataGetter, eventListener); 1929 mEventListener = eventListener; 1930 } 1931 } 1932 1933 private class TestInjector extends DataManager.Injector { 1934 1935 private final TestContactsQueryHelper mContactsQueryHelper = 1936 new TestContactsQueryHelper(mContext); 1937 private TestCallLogQueryHelper mCallLogQueryHelper; 1938 private TestMmsQueryHelper mMmsQueryHelper; 1939 private TestSmsQueryHelper mSmsQueryHelper; 1940 private TestUsageStatsQueryHelper mUsageStatsQueryHelper; 1941 1942 @Override createScheduledExecutor()1943 ScheduledExecutorService createScheduledExecutor() { 1944 return mExecutorService; 1945 } 1946 1947 @Override getBackgroundExecutor()1948 Executor getBackgroundExecutor() { 1949 return Runnable::run; 1950 } 1951 1952 @Override createContactsQueryHelper(Context context)1953 ContactsQueryHelper createContactsQueryHelper(Context context) { 1954 return mContactsQueryHelper; 1955 } 1956 1957 @Override createCallLogQueryHelper(Context context, BiConsumer<String, Event> eventConsumer)1958 CallLogQueryHelper createCallLogQueryHelper(Context context, 1959 BiConsumer<String, Event> eventConsumer) { 1960 mCallLogQueryHelper = new TestCallLogQueryHelper(context, eventConsumer); 1961 return mCallLogQueryHelper; 1962 } 1963 1964 @Override createMmsQueryHelper(Context context, BiConsumer<String, Event> eventConsumer)1965 MmsQueryHelper createMmsQueryHelper(Context context, 1966 BiConsumer<String, Event> eventConsumer) { 1967 mMmsQueryHelper = new TestMmsQueryHelper(context, eventConsumer); 1968 return mMmsQueryHelper; 1969 } 1970 1971 @Override createSmsQueryHelper(Context context, BiConsumer<String, Event> eventConsumer)1972 SmsQueryHelper createSmsQueryHelper(Context context, 1973 BiConsumer<String, Event> eventConsumer) { 1974 mSmsQueryHelper = new TestSmsQueryHelper(context, eventConsumer); 1975 return mSmsQueryHelper; 1976 } 1977 1978 @Override createUsageStatsQueryHelper(@serIdInt int userId, Function<String, PackageData> packageDataGetter, UsageStatsQueryHelper.EventListener eventListener)1979 UsageStatsQueryHelper createUsageStatsQueryHelper(@UserIdInt int userId, 1980 Function<String, PackageData> packageDataGetter, 1981 UsageStatsQueryHelper.EventListener eventListener) { 1982 mUsageStatsQueryHelper = 1983 new TestUsageStatsQueryHelper(userId, packageDataGetter, eventListener); 1984 return mUsageStatsQueryHelper; 1985 } 1986 } 1987 } 1988