1 /* 2 * Copyright (C) 2023 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; 18 19 import static android.permission.flags.Flags.FLAG_SENSITIVE_CONTENT_METRICS_BUGFIX; 20 import static android.permission.flags.Flags.FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION; 21 22 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 23 24 import static org.mockito.ArgumentMatchers.any; 25 import static org.mockito.ArgumentMatchers.anyLong; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.Mockito.doCallRealMethod; 28 import static org.mockito.Mockito.doReturn; 29 import static org.mockito.Mockito.doThrow; 30 import static org.mockito.Mockito.never; 31 import static org.mockito.Mockito.spy; 32 import static org.mockito.Mockito.verify; 33 import static org.mockito.Mockito.when; 34 35 import android.content.pm.PackageManagerInternal; 36 import android.media.projection.MediaProjectionInfo; 37 import android.media.projection.MediaProjectionManager; 38 import android.os.Process; 39 import android.platform.test.annotations.RequiresFlagsDisabled; 40 import android.platform.test.annotations.RequiresFlagsEnabled; 41 import android.platform.test.flag.junit.CheckFlagsRule; 42 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 43 import android.provider.Settings; 44 import android.service.notification.NotificationListenerService.Ranking; 45 import android.service.notification.NotificationListenerService.RankingMap; 46 import android.service.notification.StatusBarNotification; 47 import android.testing.AndroidTestingRunner; 48 import android.testing.TestableContext; 49 import android.testing.TestableLooper.RunWithLooper; 50 import android.util.ArraySet; 51 52 import androidx.test.filters.SmallTest; 53 54 import com.android.server.wm.SensitiveContentPackages.PackageInfo; 55 import com.android.server.wm.WindowManagerInternal; 56 57 import org.junit.After; 58 import org.junit.Before; 59 import org.junit.Rule; 60 import org.junit.Test; 61 import org.junit.runner.RunWith; 62 import org.mockito.ArgumentCaptor; 63 import org.mockito.Captor; 64 import org.mockito.Mock; 65 import org.mockito.Mockito; 66 import org.mockito.MockitoAnnotations; 67 68 import java.util.Set; 69 70 @SmallTest 71 @RunWith(AndroidTestingRunner.class) 72 @RunWithLooper 73 @RequiresFlagsEnabled(FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION) 74 /** 75 * Test {@link SensitiveContentProtectionManagerService} for sensitive notification protection, 76 * the service protects sensitive content during screen share. 77 */ 78 public class SensitiveContentProtectionManagerServiceNotificationTest { 79 private static final String NOTIFICATION_KEY_1 = "com.android.server.notification.TEST_KEY_1"; 80 private static final String NOTIFICATION_KEY_2 = "com.android.server.notification.TEST_KEY_2"; 81 82 private static final String NOTIFICATION_PKG_1 = "com.android.server.notification.one"; 83 private static final String NOTIFICATION_PKG_2 = "com.android.server.notification.two"; 84 85 private static final String SCREEN_RECORDER_PACKAGE = "test.screen.recorder.package"; 86 private static final String EXEMPTED_SCREEN_RECORDER_PACKAGE = "exempt.screen.recorder.package"; 87 88 private static final int NOTIFICATION_UID_1 = 5; 89 private static final int NOTIFICATION_UID_2 = 6; 90 91 private static final ArraySet<PackageInfo> EMPTY_SET = new ArraySet<>(); 92 93 @Rule 94 public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); 95 96 @Rule 97 public final TestableContext mContext = 98 new TestableContext(getInstrumentation().getTargetContext(), null); 99 100 private SensitiveContentProtectionManagerService mSensitiveContentProtectionManagerService; 101 102 @Captor 103 ArgumentCaptor<MediaProjectionManager.Callback> mMediaProjectionCallbackCaptor; 104 @Captor 105 private ArgumentCaptor<ArraySet<PackageInfo>> mPackageInfoCaptor; 106 107 @Mock 108 private MediaProjectionManager mProjectionManager; 109 110 @Mock 111 private WindowManagerInternal mWindowManager; 112 113 @Mock 114 private PackageManagerInternal mPackageManagerInternal; 115 116 @Mock 117 private StatusBarNotification mNotification1; 118 119 @Mock 120 private StatusBarNotification mNotification2; 121 122 @Mock 123 private RankingMap mRankingMap; 124 125 @Mock 126 private Ranking mSensitiveRanking; 127 128 @Mock 129 private Ranking mNonSensitiveRanking; 130 131 @Before setUp()132 public void setUp() { 133 MockitoAnnotations.initMocks(this); 134 135 mSensitiveContentProtectionManagerService = 136 new SensitiveContentProtectionManagerService(mContext); 137 138 mSensitiveContentProtectionManagerService.mNotificationListener = 139 spy(mSensitiveContentProtectionManagerService.mNotificationListener); 140 doCallRealMethod() 141 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 142 .onListenerConnected(); 143 144 // Setup RankingMap and two possilbe rankings 145 when(mSensitiveRanking.hasSensitiveContent()).thenReturn(true); 146 when(mNonSensitiveRanking.hasSensitiveContent()).thenReturn(false); 147 doReturn(mRankingMap) 148 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 149 .getCurrentRanking(); 150 151 setupSensitiveNotification(); 152 153 mSensitiveContentProtectionManagerService.init(mProjectionManager, mWindowManager, 154 mPackageManagerInternal, new ArraySet<>(Set.of(EXEMPTED_SCREEN_RECORDER_PACKAGE))); 155 156 // Obtain useful mMediaProjectionCallback 157 verify(mProjectionManager).addCallback(mMediaProjectionCallbackCaptor.capture(), any()); 158 } 159 160 @After tearDown()161 public void tearDown() { 162 mSensitiveContentProtectionManagerService.onDestroy(); 163 } 164 setupSensitiveNotification()165 private ArraySet<PackageInfo> setupSensitiveNotification() { 166 // Setup Notification Values 167 when(mNotification1.getKey()).thenReturn(NOTIFICATION_KEY_1); 168 when(mNotification1.getPackageName()).thenReturn(NOTIFICATION_PKG_1); 169 when(mNotification1.getUid()).thenReturn(NOTIFICATION_UID_1); 170 171 when(mNotification2.getKey()).thenReturn(NOTIFICATION_KEY_2); 172 when(mNotification2.getPackageName()).thenReturn(NOTIFICATION_PKG_2); 173 when(mNotification2.getUid()).thenReturn(NOTIFICATION_UID_1); 174 175 StatusBarNotification[] mNotifications = 176 new StatusBarNotification[] {mNotification1, mNotification2}; 177 doReturn(mNotifications) 178 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 179 .getActiveNotifications(); 180 181 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))) 182 .thenReturn(mSensitiveRanking); 183 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_2))) 184 .thenReturn(mNonSensitiveRanking); 185 186 return new ArraySet<>( 187 Set.of(new PackageInfo(NOTIFICATION_PKG_1, NOTIFICATION_UID_1))); 188 } 189 setupMultipleSensitiveNotificationsFromSamePackageAndUid()190 private ArraySet<PackageInfo> setupMultipleSensitiveNotificationsFromSamePackageAndUid() { 191 // Setup Notification Values 192 when(mNotification1.getKey()).thenReturn(NOTIFICATION_KEY_1); 193 when(mNotification1.getPackageName()).thenReturn(NOTIFICATION_PKG_1); 194 when(mNotification1.getUid()).thenReturn(NOTIFICATION_UID_1); 195 196 when(mNotification2.getKey()).thenReturn(NOTIFICATION_KEY_2); 197 when(mNotification2.getPackageName()).thenReturn(NOTIFICATION_PKG_1); 198 when(mNotification2.getUid()).thenReturn(NOTIFICATION_UID_1); 199 200 StatusBarNotification[] mNotifications = 201 new StatusBarNotification[] {mNotification1, mNotification2}; 202 doReturn(mNotifications) 203 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 204 .getActiveNotifications(); 205 206 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))) 207 .thenReturn(mSensitiveRanking); 208 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_2))) 209 .thenReturn(mSensitiveRanking); 210 211 return new ArraySet<>( 212 Set.of(new PackageInfo(NOTIFICATION_PKG_1, NOTIFICATION_UID_1))); 213 } 214 setupMultipleSensitiveNotificationsFromDifferentPackage()215 private ArraySet<PackageInfo> setupMultipleSensitiveNotificationsFromDifferentPackage() { 216 // Setup Notification Values 217 when(mNotification1.getKey()).thenReturn(NOTIFICATION_KEY_1); 218 when(mNotification1.getPackageName()).thenReturn(NOTIFICATION_PKG_1); 219 when(mNotification1.getUid()).thenReturn(NOTIFICATION_UID_1); 220 221 when(mNotification2.getKey()).thenReturn(NOTIFICATION_KEY_2); 222 when(mNotification2.getPackageName()).thenReturn(NOTIFICATION_PKG_2); 223 when(mNotification2.getUid()).thenReturn(NOTIFICATION_UID_1); 224 225 StatusBarNotification[] mNotifications = 226 new StatusBarNotification[] {mNotification1, mNotification2}; 227 doReturn(mNotifications) 228 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 229 .getActiveNotifications(); 230 231 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))) 232 .thenReturn(mSensitiveRanking); 233 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_2))) 234 .thenReturn(mSensitiveRanking); 235 236 return new ArraySet<>( 237 Set.of(new PackageInfo(NOTIFICATION_PKG_1, NOTIFICATION_UID_1), 238 new PackageInfo(NOTIFICATION_PKG_2, NOTIFICATION_UID_1))); 239 } 240 setupMultipleSensitiveNotificationsFromDifferentUid()241 private ArraySet<PackageInfo> setupMultipleSensitiveNotificationsFromDifferentUid() { 242 // Setup Notification Values 243 when(mNotification1.getKey()).thenReturn(NOTIFICATION_KEY_1); 244 when(mNotification1.getPackageName()).thenReturn(NOTIFICATION_PKG_1); 245 when(mNotification1.getUid()).thenReturn(NOTIFICATION_UID_1); 246 247 when(mNotification2.getKey()).thenReturn(NOTIFICATION_KEY_2); 248 when(mNotification2.getPackageName()).thenReturn(NOTIFICATION_PKG_1); 249 when(mNotification2.getUid()).thenReturn(NOTIFICATION_UID_2); 250 251 StatusBarNotification[] mNotifications = 252 new StatusBarNotification[] {mNotification1, mNotification2}; 253 doReturn(mNotifications) 254 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 255 .getActiveNotifications(); 256 257 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))) 258 .thenReturn(mSensitiveRanking); 259 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_2))) 260 .thenReturn(mSensitiveRanking); 261 262 return new ArraySet<>( 263 Set.of(new PackageInfo(NOTIFICATION_PKG_1, NOTIFICATION_UID_1), 264 new PackageInfo(NOTIFICATION_PKG_1, NOTIFICATION_UID_2))); 265 } 266 setupNoSensitiveNotifications()267 private void setupNoSensitiveNotifications() { 268 // Setup Notification Values 269 when(mNotification1.getKey()).thenReturn(NOTIFICATION_KEY_1); 270 when(mNotification1.getPackageName()).thenReturn(NOTIFICATION_PKG_1); 271 when(mNotification1.getUid()).thenReturn(NOTIFICATION_UID_1); 272 273 StatusBarNotification[] mNotifications = new StatusBarNotification[] {mNotification1}; 274 doReturn(mNotifications) 275 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 276 .getActiveNotifications(); 277 278 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))) 279 .thenReturn(mNonSensitiveRanking); 280 } 281 setupNoNotifications()282 private void setupNoNotifications() { 283 // Setup Notification Values 284 StatusBarNotification[] mNotifications = new StatusBarNotification[] {}; 285 doReturn(mNotifications) 286 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 287 .getActiveNotifications(); 288 } 289 setupNullNotifications()290 private void setupNullNotifications() { 291 // Setup Notification Values 292 StatusBarNotification[] mNotifications = new StatusBarNotification[] { null, null}; 293 doReturn(mNotifications) 294 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 295 .getActiveNotifications(); 296 } 297 createMediaProjectionInfo()298 private MediaProjectionInfo createMediaProjectionInfo() { 299 return new MediaProjectionInfo(SCREEN_RECORDER_PACKAGE, Process.myUserHandle(), null); 300 } 301 createExemptMediaProjectionInfo()302 private MediaProjectionInfo createExemptMediaProjectionInfo() { 303 return new MediaProjectionInfo( 304 EXEMPTED_SCREEN_RECORDER_PACKAGE, Process.myUserHandle(), null); 305 } 306 307 @Test mediaProjectionOnStart_verifyExemptedRecorderPackage()308 public void mediaProjectionOnStart_verifyExemptedRecorderPackage() { 309 MediaProjectionInfo mediaProjectionInfo = createExemptMediaProjectionInfo(); 310 311 mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo); 312 313 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 314 } 315 316 @Test 317 @RequiresFlagsDisabled(FLAG_SENSITIVE_CONTENT_METRICS_BUGFIX) mediaProjectionOnStart_flagDisabled_neverSetBlockScreenCaptureForAppsSessionId()318 public void mediaProjectionOnStart_flagDisabled_neverSetBlockScreenCaptureForAppsSessionId() { 319 setupSensitiveNotification(); 320 321 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 322 323 verify(mWindowManager, never()).setBlockScreenCaptureForAppsSessionId(anyLong()); 324 } 325 326 @Test 327 @RequiresFlagsEnabled(FLAG_SENSITIVE_CONTENT_METRICS_BUGFIX) mediaProjectionOnStart_setBlockScreenCaptureForAppsSessionId()328 public void mediaProjectionOnStart_setBlockScreenCaptureForAppsSessionId() { 329 setupSensitiveNotification(); 330 331 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 332 333 verify(mWindowManager).setBlockScreenCaptureForAppsSessionId(anyLong()); 334 } 335 336 @Test mediaProjectionOnStart_onProjectionStart_setWmBlockedPackages()337 public void mediaProjectionOnStart_onProjectionStart_setWmBlockedPackages() { 338 ArraySet<PackageInfo> expectedBlockedPackages = setupSensitiveNotification(); 339 340 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 341 342 verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages); 343 } 344 345 @Test mediaProjectionOnStart_noSensitiveNotifications_noBlockedPackages()346 public void mediaProjectionOnStart_noSensitiveNotifications_noBlockedPackages() { 347 setupNoSensitiveNotifications(); 348 349 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 350 351 verify(mWindowManager, never()).addBlockScreenCaptureForApps(any()); 352 } 353 354 @Test mediaProjectionOnStart_noNotifications_noBlockedPackages()355 public void mediaProjectionOnStart_noNotifications_noBlockedPackages() { 356 setupNoNotifications(); 357 358 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 359 360 verify(mWindowManager, never()).addBlockScreenCaptureForApps(any()); 361 } 362 363 @Test mediaProjectionOnStart_multipleNotifications_setWmBlockedPackages()364 public void mediaProjectionOnStart_multipleNotifications_setWmBlockedPackages() { 365 ArraySet<PackageInfo> expectedBlockedPackages = 366 setupMultipleSensitiveNotificationsFromSamePackageAndUid(); 367 368 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 369 370 verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages); 371 } 372 373 @Test mediaProjectionOnStart_multiplePackages_setWmBlockedPackages()374 public void mediaProjectionOnStart_multiplePackages_setWmBlockedPackages() { 375 ArraySet<PackageInfo> expectedBlockedPackages = 376 setupMultipleSensitiveNotificationsFromDifferentPackage(); 377 378 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 379 380 verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages); 381 } 382 383 @Test mediaProjectionOnStart_multipleUid_setWmBlockedPackages()384 public void mediaProjectionOnStart_multipleUid_setWmBlockedPackages() { 385 ArraySet<PackageInfo> expectedBlockedPackages = 386 setupMultipleSensitiveNotificationsFromDifferentUid(); 387 388 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 389 390 verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages); 391 } 392 393 @Test mediaProjectionOnStop_onProjectionEnd_clearWmBlockedPackages()394 public void mediaProjectionOnStop_onProjectionEnd_clearWmBlockedPackages() { 395 setupSensitiveNotification(); 396 397 MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo(); 398 mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo); 399 Mockito.reset(mWindowManager); 400 401 mMediaProjectionCallbackCaptor.getValue().onStop(mediaProjectionInfo); 402 403 verify(mWindowManager).clearBlockedApps(); 404 } 405 406 @Test mediaProjectionOnStart_afterOnStop_onProjectionStart_setWmBlockedPackages()407 public void mediaProjectionOnStart_afterOnStop_onProjectionStart_setWmBlockedPackages() { 408 ArraySet<PackageInfo> expectedBlockedPackages = setupSensitiveNotification(); 409 410 MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo(); 411 mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo); 412 mMediaProjectionCallbackCaptor.getValue().onStop(mediaProjectionInfo); 413 Mockito.reset(mWindowManager); 414 415 mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo); 416 417 verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages); 418 } 419 420 @Test mediaProjectionOnStart_getActiveNotificationsThrows_noBlockedPackages()421 public void mediaProjectionOnStart_getActiveNotificationsThrows_noBlockedPackages() { 422 doThrow(SecurityException.class) 423 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 424 .getActiveNotifications(); 425 426 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 427 428 verify(mWindowManager, never()).addBlockScreenCaptureForApps(any()); 429 } 430 431 @Test mediaProjectionOnStart_getCurrentRankingThrows_noBlockedPackages()432 public void mediaProjectionOnStart_getCurrentRankingThrows_noBlockedPackages() { 433 doThrow(SecurityException.class) 434 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 435 .getCurrentRanking(); 436 437 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 438 439 verify(mWindowManager, never()).addBlockScreenCaptureForApps(any()); 440 } 441 442 @Test mediaProjectionOnStart_getCurrentRanking_nullRankingMap_noBlockedPackages()443 public void mediaProjectionOnStart_getCurrentRanking_nullRankingMap_noBlockedPackages() { 444 doReturn(null) 445 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 446 .getCurrentRanking(); 447 448 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 449 450 verify(mWindowManager, never()).addBlockScreenCaptureForApps(any()); 451 } 452 453 @Test mediaProjectionOnStart_getCurrentRanking_missingRanking_noBlockedPackages()454 public void mediaProjectionOnStart_getCurrentRanking_missingRanking_noBlockedPackages() { 455 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))).thenReturn(null); 456 457 doReturn(mRankingMap) 458 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 459 .getCurrentRanking(); 460 461 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 462 463 verify(mWindowManager, never()).addBlockScreenCaptureForApps(any()); 464 } 465 466 @Test mediaProjectionOnStart_disabledViaDevOption_noBlockedPackages()467 public void mediaProjectionOnStart_disabledViaDevOption_noBlockedPackages() { 468 mockDisabledViaDevelopOption(); 469 setupSensitiveNotification(); 470 471 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 472 473 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 474 } 475 476 @Test nlsOnListenerConnected_projectionNotStarted_noop()477 public void nlsOnListenerConnected_projectionNotStarted_noop() { 478 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 479 // as non-sensitive 480 setupSensitiveNotification(); 481 482 mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); 483 484 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 485 } 486 487 @Test nlsOnListenerConnected_projectionStopped_noop()488 public void nlsOnListenerConnected_projectionStopped_noop() { 489 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 490 // as non-sensitive 491 setupSensitiveNotification(); 492 MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo(); 493 mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo); 494 mMediaProjectionCallbackCaptor.getValue().onStop(mediaProjectionInfo); 495 Mockito.reset(mWindowManager); 496 497 mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); 498 499 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 500 } 501 502 @Test nlsOnListenerConnected_projectionStarted_setWmBlockedPackages()503 public void nlsOnListenerConnected_projectionStarted_setWmBlockedPackages() { 504 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 505 // as non-sensitive 506 ArraySet<PackageInfo> expectedBlockedPackages = setupSensitiveNotification(); 507 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 508 Mockito.reset(mWindowManager); 509 510 mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); 511 512 verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages); 513 } 514 515 @Test nlsOnListenerConnected_noSensitiveNotifications_noBlockedPackages()516 public void nlsOnListenerConnected_noSensitiveNotifications_noBlockedPackages() { 517 setupNoSensitiveNotifications(); 518 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 519 Mockito.reset(mWindowManager); 520 521 mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); 522 523 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 524 } 525 526 @Test nlsOnListenerConnected_noNotifications_noBlockedPackages()527 public void nlsOnListenerConnected_noNotifications_noBlockedPackages() { 528 setupNoNotifications(); 529 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 530 Mockito.reset(mWindowManager); 531 532 mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); 533 534 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 535 } 536 537 @Test nlsOnListenerConnected_nullNotifications_noBlockedPackages()538 public void nlsOnListenerConnected_nullNotifications_noBlockedPackages() { 539 setupNullNotifications(); 540 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 541 Mockito.reset(mWindowManager); 542 543 mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); 544 545 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 546 } 547 548 @Test nlsOnListenerConnected_nullRankingMap_noBlockedPackages()549 public void nlsOnListenerConnected_nullRankingMap_noBlockedPackages() { 550 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 551 // as non-sensitive 552 setupSensitiveNotification(); 553 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 554 Mockito.reset(mWindowManager); 555 doReturn(null) 556 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 557 .getCurrentRanking(); 558 559 mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); 560 561 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 562 } 563 564 @Test nlsOnListenerConnected_missingRanking_noBlockedPackages()565 public void nlsOnListenerConnected_missingRanking_noBlockedPackages() { 566 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 567 // as non-sensitive 568 setupSensitiveNotification(); 569 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 570 Mockito.reset(mWindowManager); 571 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))).thenReturn(null); 572 doReturn(mRankingMap) 573 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 574 .getCurrentRanking(); 575 576 mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); 577 578 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 579 } 580 581 @Test nlsOnListenerConnected_disabledViaDevOption_noBlockedPackages()582 public void nlsOnListenerConnected_disabledViaDevOption_noBlockedPackages() { 583 mockDisabledViaDevelopOption(); 584 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 585 // as non-sensitive 586 setupSensitiveNotification(); 587 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 588 mSensitiveContentProtectionManagerService.mNotificationListener.onListenerConnected(); 589 590 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 591 } 592 593 @Test nlsOnNotificationRankingUpdate_projectionNotStarted_noop()594 public void nlsOnNotificationRankingUpdate_projectionNotStarted_noop() { 595 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 596 // as non-sensitive 597 setupSensitiveNotification(); 598 599 mSensitiveContentProtectionManagerService.mNotificationListener 600 .onNotificationRankingUpdate(mRankingMap); 601 602 verifyNoBlockOrClearInteractionWithWindowManager(); 603 } 604 605 @Test nlsOnNotificationRankingUpdate_projectionStopped_noop()606 public void nlsOnNotificationRankingUpdate_projectionStopped_noop() { 607 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 608 // as non-sensitive 609 setupSensitiveNotification(); 610 MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo(); 611 mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo); 612 mMediaProjectionCallbackCaptor.getValue().onStop(mediaProjectionInfo); 613 Mockito.reset(mWindowManager); 614 615 mSensitiveContentProtectionManagerService.mNotificationListener 616 .onNotificationRankingUpdate(mRankingMap); 617 618 verifyNoBlockOrClearInteractionWithWindowManager(); 619 } 620 621 @Test nlsOnNotificationRankingUpdate_projectionStarted_setWmBlockedPackages()622 public void nlsOnNotificationRankingUpdate_projectionStarted_setWmBlockedPackages() { 623 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 624 // as non-sensitive 625 ArraySet<PackageInfo> expectedBlockedPackages = setupSensitiveNotification(); 626 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 627 Mockito.reset(mWindowManager); 628 629 mSensitiveContentProtectionManagerService.mNotificationListener 630 .onNotificationRankingUpdate(mRankingMap); 631 632 verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages); 633 } 634 635 @Test nlsOnNotificationRankingUpdate_noSensitiveNotifications_noBlockedPackages()636 public void nlsOnNotificationRankingUpdate_noSensitiveNotifications_noBlockedPackages() { 637 setupNoSensitiveNotifications(); 638 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 639 Mockito.reset(mWindowManager); 640 641 mSensitiveContentProtectionManagerService.mNotificationListener 642 .onNotificationRankingUpdate(mRankingMap); 643 644 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 645 } 646 647 @Test nlsOnNotificationRankingUpdate_noNotifications_noBlockedPackages()648 public void nlsOnNotificationRankingUpdate_noNotifications_noBlockedPackages() { 649 setupNoNotifications(); 650 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 651 Mockito.reset(mWindowManager); 652 653 mSensitiveContentProtectionManagerService.mNotificationListener 654 .onNotificationRankingUpdate(mRankingMap); 655 656 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 657 } 658 659 @Test nlsOnNotificationRankingUpdate_nullRankingMap_noBlockedPackages()660 public void nlsOnNotificationRankingUpdate_nullRankingMap_noBlockedPackages() { 661 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 662 // as non-sensitive 663 setupSensitiveNotification(); 664 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 665 Mockito.reset(mWindowManager); 666 667 mSensitiveContentProtectionManagerService.mNotificationListener 668 .onNotificationRankingUpdate(null); 669 670 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 671 } 672 673 @Test nlsOnNotificationRankingUpdate_missingRanking_noBlockedPackages()674 public void nlsOnNotificationRankingUpdate_missingRanking_noBlockedPackages() { 675 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 676 // as non-sensitive 677 setupSensitiveNotification(); 678 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 679 Mockito.reset(mWindowManager); 680 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))).thenReturn(null); 681 doReturn(mRankingMap) 682 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 683 .getCurrentRanking(); 684 685 mSensitiveContentProtectionManagerService.mNotificationListener 686 .onNotificationRankingUpdate(mRankingMap); 687 688 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 689 } 690 691 @Test nlsOnNotificationRankingUpdate_getActiveNotificationsThrows_noBlockedPackages()692 public void nlsOnNotificationRankingUpdate_getActiveNotificationsThrows_noBlockedPackages() { 693 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 694 // as non-sensitive 695 setupSensitiveNotification(); 696 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 697 Mockito.reset(mWindowManager); 698 699 doThrow(SecurityException.class) 700 .when(mSensitiveContentProtectionManagerService.mNotificationListener) 701 .getActiveNotifications(); 702 703 mSensitiveContentProtectionManagerService.mNotificationListener 704 .onNotificationRankingUpdate(mRankingMap); 705 706 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 707 } 708 709 @Test nlsOnNotificationRankingUpdate_disabledViaDevOption_noBlockedPackages()710 public void nlsOnNotificationRankingUpdate_disabledViaDevOption_noBlockedPackages() { 711 mockDisabledViaDevelopOption(); 712 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 713 // as non-sensitive 714 setupSensitiveNotification(); 715 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 716 mSensitiveContentProtectionManagerService.mNotificationListener 717 .onNotificationRankingUpdate(mRankingMap); 718 719 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 720 } 721 722 @Test nlsOnNotificationPosted_projectionNotStarted_noop()723 public void nlsOnNotificationPosted_projectionNotStarted_noop() { 724 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 725 // as non-sensitive 726 setupSensitiveNotification(); 727 728 mSensitiveContentProtectionManagerService.mNotificationListener 729 .onNotificationPosted(mNotification1, mRankingMap); 730 731 verifyNoBlockOrClearInteractionWithWindowManager(); 732 } 733 734 @Test nlsOnNotificationPosted_projectionStopped_noop()735 public void nlsOnNotificationPosted_projectionStopped_noop() { 736 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 737 // as non-sensitive 738 setupSensitiveNotification(); 739 MediaProjectionInfo mediaProjectionInfo = createMediaProjectionInfo(); 740 mMediaProjectionCallbackCaptor.getValue().onStart(mediaProjectionInfo); 741 mMediaProjectionCallbackCaptor.getValue().onStop(mediaProjectionInfo); 742 Mockito.reset(mWindowManager); 743 744 mSensitiveContentProtectionManagerService.mNotificationListener 745 .onNotificationPosted(mNotification1, mRankingMap); 746 747 verifyNoBlockOrClearInteractionWithWindowManager(); 748 } 749 750 @Test nlsOnNotificationPosted_projectionStarted_setWmBlockedPackages()751 public void nlsOnNotificationPosted_projectionStarted_setWmBlockedPackages() { 752 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 753 // as non-sensitive 754 setupSensitiveNotification(); 755 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 756 Mockito.reset(mWindowManager); 757 758 mSensitiveContentProtectionManagerService.mNotificationListener 759 .onNotificationPosted(mNotification1, mRankingMap); 760 761 ArraySet<PackageInfo> expectedBlockedPackages = new ArraySet<>( 762 Set.of(new PackageInfo(NOTIFICATION_PKG_1, NOTIFICATION_UID_1))); 763 verify(mWindowManager).addBlockScreenCaptureForApps(expectedBlockedPackages); 764 } 765 766 @Test nlsOnNotificationPosted_noSensitiveNotifications_noBlockedPackages()767 public void nlsOnNotificationPosted_noSensitiveNotifications_noBlockedPackages() { 768 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 769 // as non-sensitive 770 setupSensitiveNotification(); 771 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 772 Mockito.reset(mWindowManager); 773 774 mSensitiveContentProtectionManagerService.mNotificationListener 775 .onNotificationPosted(mNotification2, mRankingMap); 776 777 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 778 } 779 780 @Test nlsOnNotificationPosted_noNotifications_noBlockedPackages()781 public void nlsOnNotificationPosted_noNotifications_noBlockedPackages() { 782 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 783 // as non-sensitive 784 setupSensitiveNotification(); 785 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 786 Mockito.reset(mWindowManager); 787 788 mSensitiveContentProtectionManagerService.mNotificationListener 789 .onNotificationPosted(null, mRankingMap); 790 791 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 792 } 793 794 @Test nlsOnNotificationPosted_nullRankingMap_noBlockedPackages()795 public void nlsOnNotificationPosted_nullRankingMap_noBlockedPackages() { 796 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 797 // as non-sensitive 798 setupSensitiveNotification(); 799 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 800 Mockito.reset(mWindowManager); 801 802 mSensitiveContentProtectionManagerService.mNotificationListener 803 .onNotificationPosted(mNotification1, null); 804 805 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 806 } 807 808 @Test nlsOnNotificationPosted_missingRanking_noBlockedPackages()809 public void nlsOnNotificationPosted_missingRanking_noBlockedPackages() { 810 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 811 // as non-sensitive 812 setupSensitiveNotification(); 813 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 814 Mockito.reset(mWindowManager); 815 when(mRankingMap.getRawRankingObject(eq(NOTIFICATION_KEY_1))).thenReturn(null); 816 817 mSensitiveContentProtectionManagerService.mNotificationListener 818 .onNotificationPosted(mNotification1, mRankingMap); 819 820 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 821 } 822 823 @Test nlsOnNotificationPosted_disabledViaDevOption_noBlockedPackages()824 public void nlsOnNotificationPosted_disabledViaDevOption_noBlockedPackages() { 825 mockDisabledViaDevelopOption(); 826 // Sets up mNotification1 & mRankingMap to be a sensitive notification, and mNotification2 827 // as non-sensitive 828 setupSensitiveNotification(); 829 mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo()); 830 mSensitiveContentProtectionManagerService.mNotificationListener 831 .onNotificationPosted(mNotification1, mRankingMap); 832 833 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 834 } 835 verifyNoBlockOrClearInteractionWithWindowManager()836 private void verifyNoBlockOrClearInteractionWithWindowManager() { 837 verify(mWindowManager, never()).addBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 838 verify(mWindowManager, never()).clearBlockedApps(); 839 verify(mWindowManager, never()) 840 .removeBlockScreenCaptureForApps(mPackageInfoCaptor.capture()); 841 } 842 mockDisabledViaDevelopOption()843 private void mockDisabledViaDevelopOption() { 844 // mContext (TestableContext) uses [TestableSettingsProvider] and it will be cleared after 845 // the test 846 Settings.Global.putInt( 847 mContext.getContentResolver(), 848 Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 849 1); 850 } 851 } 852