1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui; 16 17 import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM; 18 import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT; 19 import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT; 20 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP; 21 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; 22 23 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 24 import static com.android.systemui.dump.LogBufferHelperKt.logcatLogBuffer; 25 26 import static com.google.common.truth.Truth.assertThat; 27 28 import static org.hamcrest.Matchers.is; 29 import static org.junit.Assert.assertEquals; 30 import static org.junit.Assert.assertFalse; 31 import static org.junit.Assert.assertNotNull; 32 import static org.junit.Assert.assertNull; 33 import static org.junit.Assert.assertThat; 34 import static org.junit.Assert.assertTrue; 35 import static org.junit.Assert.fail; 36 import static org.mockito.ArgumentMatchers.any; 37 import static org.mockito.ArgumentMatchers.anyInt; 38 import static org.mockito.ArgumentMatchers.eq; 39 import static org.mockito.ArgumentMatchers.isA; 40 import static org.mockito.Mockito.clearInvocations; 41 import static org.mockito.Mockito.doAnswer; 42 import static org.mockito.Mockito.doNothing; 43 import static org.mockito.Mockito.doReturn; 44 import static org.mockito.Mockito.mock; 45 import static org.mockito.Mockito.never; 46 import static org.mockito.Mockito.spy; 47 import static org.mockito.Mockito.times; 48 import static org.mockito.Mockito.verify; 49 import static org.mockito.Mockito.when; 50 51 import android.annotation.IdRes; 52 import android.content.pm.PackageManager; 53 import android.content.res.Configuration; 54 import android.content.res.TypedArray; 55 import android.graphics.Path; 56 import android.graphics.PixelFormat; 57 import android.graphics.Rect; 58 import android.graphics.drawable.Drawable; 59 import android.hardware.display.DisplayManager; 60 import android.hardware.graphics.common.DisplayDecorationSupport; 61 import android.os.Handler; 62 import android.testing.AndroidTestingRunner; 63 import android.testing.TestableLooper; 64 import android.testing.TestableLooper.RunWithLooper; 65 import android.util.PathParser; 66 import android.util.Size; 67 import android.view.Display; 68 import android.view.DisplayCutout; 69 import android.view.DisplayInfo; 70 import android.view.Surface; 71 import android.view.View; 72 import android.view.ViewGroup; 73 import android.view.WindowManager; 74 import android.view.WindowMetrics; 75 76 import androidx.annotation.DrawableRes; 77 import androidx.annotation.NonNull; 78 import androidx.annotation.Nullable; 79 import androidx.test.filters.SmallTest; 80 81 import com.android.keyguard.KeyguardUpdateMonitor; 82 import com.android.systemui.biometrics.AuthController; 83 import com.android.systemui.decor.CornerDecorProvider; 84 import com.android.systemui.decor.CutoutDecorProviderFactory; 85 import com.android.systemui.decor.CutoutDecorProviderImpl; 86 import com.android.systemui.decor.DebugRoundedCornerModel; 87 import com.android.systemui.decor.DecorProvider; 88 import com.android.systemui.decor.DecorProviderFactory; 89 import com.android.systemui.decor.FaceScanningOverlayProviderImpl; 90 import com.android.systemui.decor.FaceScanningProviderFactory; 91 import com.android.systemui.decor.OverlayWindow; 92 import com.android.systemui.decor.PrivacyDotCornerDecorProviderImpl; 93 import com.android.systemui.decor.PrivacyDotDecorProviderFactory; 94 import com.android.systemui.decor.RoundedCornerResDelegate; 95 import com.android.systemui.flags.FakeFeatureFlags; 96 import com.android.systemui.flags.Flags; 97 import com.android.systemui.log.ScreenDecorationsLogger; 98 import com.android.systemui.plugins.statusbar.StatusBarStateController; 99 import com.android.systemui.settings.FakeDisplayTracker; 100 import com.android.systemui.settings.UserTracker; 101 import com.android.systemui.statusbar.commandline.CommandRegistry; 102 import com.android.systemui.statusbar.events.PrivacyDotViewController; 103 import com.android.systemui.util.concurrency.FakeExecutor; 104 import com.android.systemui.util.concurrency.FakeThreadFactory; 105 import com.android.systemui.util.settings.FakeSettings; 106 import com.android.systemui.util.settings.SecureSettings; 107 import com.android.systemui.util.time.FakeSystemClock; 108 109 import org.junit.Before; 110 import org.junit.Test; 111 import org.junit.runner.RunWith; 112 import org.mockito.ArgumentCaptor; 113 import org.mockito.Captor; 114 import org.mockito.Mock; 115 import org.mockito.MockitoAnnotations; 116 import org.mockito.invocation.InvocationOnMock; 117 import org.mockito.stubbing.Answer; 118 119 import java.util.ArrayList; 120 import java.util.List; 121 122 @RunWithLooper 123 @RunWith(AndroidTestingRunner.class) 124 @SmallTest 125 public class ScreenDecorationsTest extends SysuiTestCase { 126 127 private ScreenDecorations mScreenDecorations; 128 private WindowManager mWindowManager; 129 private DisplayManager mDisplayManager; 130 private SecureSettings mSecureSettings; 131 private FakeExecutor mExecutor; 132 private final FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext); 133 private FakeThreadFactory mThreadFactory; 134 private ArrayList<DecorProvider> mPrivacyDecorProviders; 135 private ArrayList<DecorProvider> mFaceScanningProviders; 136 @Mock 137 private KeyguardUpdateMonitor mKeyguardUpdateMonitor; 138 @Mock 139 private StatusBarStateController mStatusBarStateController; 140 @Mock 141 private AuthController mAuthController; 142 @Mock 143 private Display mDisplay; 144 @Mock 145 private CommandRegistry mCommandRegistry; 146 @Mock 147 private UserTracker mUserTracker; 148 @Mock 149 private PrivacyDotViewController mDotViewController; 150 @Mock 151 private TypedArray mMockTypedArray; 152 @Mock 153 private PrivacyDotDecorProviderFactory mPrivacyDotDecorProviderFactory; 154 @Mock 155 private FaceScanningProviderFactory mFaceScanningProviderFactory; 156 @Mock 157 private FaceScanningOverlayProviderImpl mFaceScanningDecorProvider; 158 @Mock 159 private CornerDecorProvider mPrivacyDotTopLeftDecorProvider; 160 @Mock 161 private CornerDecorProvider mPrivacyDotTopRightDecorProvider; 162 @Mock 163 private CornerDecorProvider mPrivacyDotBottomLeftDecorProvider; 164 @Mock 165 private CornerDecorProvider mPrivacyDotBottomRightDecorProvider; 166 @Mock 167 private Display.Mode mDisplayMode; 168 @Mock 169 private DisplayInfo mDisplayInfo; 170 private PrivacyDotViewController.ShowingListener mPrivacyDotShowingListener; 171 @Mock 172 private CutoutDecorProviderFactory mCutoutFactory; 173 @Captor 174 private ArgumentCaptor<AuthController.Callback> mAuthControllerCallback; 175 private List<DecorProvider> mMockCutoutList; 176 177 @Before setup()178 public void setup() { 179 MockitoAnnotations.initMocks(this); 180 181 Handler mainHandler = new Handler(TestableLooper.get(this).getLooper()); 182 mSecureSettings = new FakeSettings(); 183 mExecutor = new FakeExecutor(new FakeSystemClock()); 184 mThreadFactory = new FakeThreadFactory(mExecutor); 185 mThreadFactory.setHandler(mainHandler); 186 187 mWindowManager = mock(WindowManager.class); 188 WindowMetrics metrics = mContext.getSystemService(WindowManager.class) 189 .getMaximumWindowMetrics(); 190 when(mWindowManager.getMaximumWindowMetrics()).thenReturn(metrics); 191 mContext.addMockSystemService(WindowManager.class, mWindowManager); 192 mDisplayManager = mock(DisplayManager.class); 193 mContext.addMockSystemService(DisplayManager.class, mDisplayManager); 194 195 spyOn(mContext); 196 when(mContext.getDisplay()).thenReturn(mDisplay); 197 // Not support hwc layer by default 198 doReturn(null).when(mDisplay).getDisplayDecorationSupport(); 199 doReturn(mDisplayMode).when(mDisplayInfo).getMode(); 200 201 when(mMockTypedArray.length()).thenReturn(0); 202 mPrivacyDotTopLeftDecorProvider = spy(new PrivacyDotCornerDecorProviderImpl( 203 R.id.privacy_dot_top_left_container, 204 DisplayCutout.BOUNDS_POSITION_TOP, 205 DisplayCutout.BOUNDS_POSITION_LEFT, 206 R.layout.privacy_dot_top_left)); 207 208 mPrivacyDotTopRightDecorProvider = spy(new PrivacyDotCornerDecorProviderImpl( 209 R.id.privacy_dot_top_right_container, 210 DisplayCutout.BOUNDS_POSITION_TOP, 211 DisplayCutout.BOUNDS_POSITION_RIGHT, 212 R.layout.privacy_dot_top_right)); 213 214 mPrivacyDotBottomLeftDecorProvider = spy(new PrivacyDotCornerDecorProviderImpl( 215 R.id.privacy_dot_bottom_left_container, 216 DisplayCutout.BOUNDS_POSITION_BOTTOM, 217 DisplayCutout.BOUNDS_POSITION_LEFT, 218 R.layout.privacy_dot_bottom_left)); 219 220 mPrivacyDotBottomRightDecorProvider = spy(new PrivacyDotCornerDecorProviderImpl( 221 R.id.privacy_dot_bottom_right_container, 222 DisplayCutout.BOUNDS_POSITION_BOTTOM, 223 DisplayCutout.BOUNDS_POSITION_RIGHT, 224 R.layout.privacy_dot_bottom_right)); 225 226 // Default no cutout 227 mMockCutoutList = new ArrayList<>(); 228 doAnswer(it -> !(mMockCutoutList.isEmpty())).when(mCutoutFactory).getHasProviders(); 229 doReturn(mMockCutoutList).when(mCutoutFactory).getProviders(); 230 231 FakeFeatureFlags featureFlags = new FakeFeatureFlags(); 232 featureFlags.set(Flags.STOP_PULSING_FACE_SCANNING_ANIMATION, true); 233 mFaceScanningDecorProvider = spy(new FaceScanningOverlayProviderImpl( 234 BOUNDS_POSITION_TOP, 235 mAuthController, 236 mStatusBarStateController, 237 mKeyguardUpdateMonitor, 238 mExecutor, 239 new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer")), 240 featureFlags)); 241 242 mScreenDecorations = spy(new ScreenDecorations(mContext, mSecureSettings, 243 mCommandRegistry, mUserTracker, mDisplayTracker, mDotViewController, 244 mThreadFactory, 245 mPrivacyDotDecorProviderFactory, mFaceScanningProviderFactory, 246 new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer")), 247 mAuthController) { 248 @Override 249 public void start() { 250 super.start(); 251 mExecutor.runAllReady(); 252 } 253 254 @Override 255 public void onConfigurationChanged(Configuration newConfig) { 256 super.onConfigurationChanged(newConfig); 257 mExecutor.runAllReady(); 258 } 259 260 @Override 261 protected void updateOverlayWindowVisibilityIfViewExists(@Nullable View view) { 262 super.updateOverlayWindowVisibilityIfViewExists(view); 263 mExecutor.runAllReady(); 264 } 265 266 @Override 267 protected CutoutDecorProviderFactory getCutoutFactory() { 268 return ScreenDecorationsTest.this.mCutoutFactory; 269 } 270 }); 271 mScreenDecorations.mDisplayInfo = mDisplayInfo; 272 // Make sure tests are never run starting in debug mode 273 mScreenDecorations.setDebug(false); 274 doReturn(1f).when(mScreenDecorations).getPhysicalPixelDisplaySizeRatio(); 275 doNothing().when(mScreenDecorations).updateOverlayProviderViews(any()); 276 277 try { 278 mPrivacyDotShowingListener = mScreenDecorations.mPrivacyDotShowingListener.getClass() 279 .getDeclaredConstructor(ScreenDecorations.class) 280 .newInstance(mScreenDecorations); 281 } catch (Exception e) { 282 fail(e.getMessage()); 283 } 284 } 285 286 @NonNull getRoundCornerIdsFromOverlayId(@isplayCutout.BoundsPosition int overlayId)287 private int[] getRoundCornerIdsFromOverlayId(@DisplayCutout.BoundsPosition int overlayId) { 288 switch (overlayId) { 289 case BOUNDS_POSITION_LEFT: 290 return new int[] { 291 R.id.rounded_corner_top_left, 292 R.id.rounded_corner_top_left }; 293 case BOUNDS_POSITION_TOP: 294 return new int[] { 295 R.id.rounded_corner_top_left, 296 R.id.rounded_corner_top_right }; 297 case BOUNDS_POSITION_RIGHT: 298 return new int[] { 299 R.id.rounded_corner_top_right, 300 R.id.rounded_corner_bottom_right }; 301 case BOUNDS_POSITION_BOTTOM: 302 return new int[] { 303 R.id.rounded_corner_bottom_left, 304 R.id.rounded_corner_bottom_right }; 305 default: 306 throw new IllegalArgumentException("unknown overlayId: " + overlayId); 307 } 308 } 309 verifyRoundedCornerViewsExist( @isplayCutout.BoundsPosition final int overlayId, @View.Visibility final boolean isExist)310 private void verifyRoundedCornerViewsExist( 311 @DisplayCutout.BoundsPosition final int overlayId, 312 @View.Visibility final boolean isExist) { 313 final View overlay = mScreenDecorations.mOverlays[overlayId].getRootView(); 314 for (int id: getRoundCornerIdsFromOverlayId(overlayId)) { 315 final View view = overlay.findViewById(id); 316 if (isExist) { 317 assertNotNull(view); 318 assertThat(view.getVisibility()).isEqualTo(View.VISIBLE); 319 } else { 320 assertNull(view); 321 } 322 } 323 } 324 verifyFaceScanningViewExists(final boolean exists)325 private void verifyFaceScanningViewExists(final boolean exists) { 326 final View overlay = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView(); 327 final View view = overlay.findViewById(mFaceScanningDecorProvider.getViewId()); 328 if (exists) { 329 assertNotNull(view); 330 } else { 331 assertNull(view); 332 } 333 } 334 335 @Nullable findViewFromOverlays(@dRes int id)336 private View findViewFromOverlays(@IdRes int id) { 337 for (OverlayWindow overlay: mScreenDecorations.mOverlays) { 338 if (overlay == null) { 339 continue; 340 } 341 342 View view = overlay.getRootView().findViewById(id); 343 if (view != null) { 344 return view; 345 } 346 } 347 return null; 348 } 349 verifyTopDotViewsNullable(final boolean isAssertNull)350 private void verifyTopDotViewsNullable(final boolean isAssertNull) { 351 View tl = findViewFromOverlays(R.id.privacy_dot_top_left_container); 352 View tr = findViewFromOverlays(R.id.privacy_dot_top_right_container); 353 if (isAssertNull) { 354 assertNull(tl); 355 assertNull(tr); 356 } else { 357 assertNotNull(tl); 358 assertNotNull(tr); 359 } 360 } 361 verifyBottomDotViewsNullable(final boolean isAssertNull)362 private void verifyBottomDotViewsNullable(final boolean isAssertNull) { 363 View bl = findViewFromOverlays(R.id.privacy_dot_bottom_left_container); 364 View br = findViewFromOverlays(R.id.privacy_dot_bottom_right_container); 365 if (isAssertNull) { 366 assertNull(bl); 367 assertNull(br); 368 } else { 369 assertNotNull(bl); 370 assertNotNull(br); 371 } 372 } 373 verifyDotViewsNullable(final boolean isAssertNull)374 private void verifyDotViewsNullable(final boolean isAssertNull) { 375 verifyTopDotViewsNullable(isAssertNull); 376 verifyBottomDotViewsNullable(isAssertNull); 377 } 378 verifyTopDotViewsVisibility(@iew.Visibility final int visibility)379 private void verifyTopDotViewsVisibility(@View.Visibility final int visibility) { 380 verifyTopDotViewsNullable(false); 381 View tl = findViewFromOverlays(R.id.privacy_dot_top_left_container); 382 View tr = findViewFromOverlays(R.id.privacy_dot_top_right_container); 383 assertThat(tl.getVisibility()).isEqualTo(visibility); 384 assertThat(tr.getVisibility()).isEqualTo(visibility); 385 } 386 verifyBottomDotViewsVisibility(@iew.Visibility final int visibility)387 private void verifyBottomDotViewsVisibility(@View.Visibility final int visibility) { 388 verifyBottomDotViewsNullable(false); 389 View bl = findViewFromOverlays(R.id.privacy_dot_bottom_left_container); 390 View br = findViewFromOverlays(R.id.privacy_dot_bottom_right_container); 391 assertThat(bl.getVisibility()).isEqualTo(visibility); 392 assertThat(br.getVisibility()).isEqualTo(visibility); 393 } 394 verifyDotViewsVisibility(@iew.Visibility final int visibility)395 private void verifyDotViewsVisibility(@View.Visibility final int visibility) { 396 verifyTopDotViewsVisibility(visibility); 397 verifyBottomDotViewsVisibility(visibility); 398 } 399 verifyOverlaysExistAndAdded(boolean left, boolean top, boolean right, boolean bottom, @Nullable Integer visibilityIfExist)400 private void verifyOverlaysExistAndAdded(boolean left, boolean top, boolean right, 401 boolean bottom, @Nullable Integer visibilityIfExist) { 402 if (left || top || right || bottom) { 403 assertNotNull(mScreenDecorations.mOverlays); 404 } else { 405 assertNull(mScreenDecorations.mOverlays); 406 return; 407 } 408 409 if (left) { 410 final OverlayWindow overlay = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT]; 411 assertNotNull(overlay); 412 verify(mWindowManager, times(1)).addView( 413 eq(overlay.getRootView()), any()); 414 if (visibilityIfExist != null) { 415 assertEquals(visibilityIfExist.intValue(), overlay.getRootView().getVisibility()); 416 } 417 } else { 418 assertNull(mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT]); 419 } 420 421 if (top) { 422 final OverlayWindow overlay = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP]; 423 assertNotNull(overlay); 424 verify(mWindowManager, times(1)).addView( 425 eq(overlay.getRootView()), any()); 426 if (visibilityIfExist != null) { 427 assertEquals(visibilityIfExist.intValue(), overlay.getRootView().getVisibility()); 428 } 429 } else { 430 assertNull(mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP]); 431 } 432 433 if (right) { 434 final OverlayWindow overlay = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT]; 435 assertNotNull(overlay); 436 verify(mWindowManager, times(1)).addView( 437 eq(overlay.getRootView()), any()); 438 if (visibilityIfExist != null) { 439 assertEquals(visibilityIfExist.intValue(), overlay.getRootView().getVisibility()); 440 } 441 } else { 442 assertNull(mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT]); 443 } 444 445 if (bottom) { 446 final OverlayWindow overlay = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM]; 447 assertNotNull(overlay); 448 verify(mWindowManager, times(1)).addView( 449 eq(overlay.getRootView()), any()); 450 if (visibilityIfExist != null) { 451 assertEquals(visibilityIfExist.intValue(), overlay.getRootView().getVisibility()); 452 } 453 } else { 454 assertNull(mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM]); 455 } 456 } 457 458 @Test testNoRounding_NoCutout_NoPrivacyDot_NoFaceScanning()459 public void testNoRounding_NoCutout_NoPrivacyDot_NoFaceScanning() { 460 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 461 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 462 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 463 464 // no cutout (default) 465 466 mScreenDecorations.start(); 467 // No views added. 468 verifyOverlaysExistAndAdded(false, false, false, false, null); 469 // No dot controller init 470 verify(mDotViewController, never()).initialize(any(), any(), any(), any()); 471 } 472 473 @Test testNoRounding_NoCutout_PrivacyDot_NoFaceScanning()474 public void testNoRounding_NoCutout_PrivacyDot_NoFaceScanning() { 475 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 476 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 477 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 478 479 // no cutout (default) 480 481 mScreenDecorations.start(); 482 483 // Top and bottom windows are created with INVISIBLE because of privacy dot only 484 // Left and right window should be null. 485 verifyOverlaysExistAndAdded(false, true, false, true, View.INVISIBLE); 486 verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); 487 verify(mDotViewController, times(1)).setShowingListener( 488 mScreenDecorations.mPrivacyDotShowingListener); 489 490 // Rounded corner views shall not exist 491 verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false); 492 verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false); 493 494 // Privacy dots shall exist but invisible 495 verifyDotViewsVisibility(View.INVISIBLE); 496 497 // Face scanning doesn't exist 498 verifyFaceScanningViewExists(false); 499 500 // Dot controller init 501 verify(mDotViewController, times(1)).initialize( 502 isA(View.class), isA(View.class), isA(View.class), isA(View.class)); 503 } 504 505 @Test testRounding_NoCutout_NoPrivacyDot_NoFaceScanning()506 public void testRounding_NoCutout_NoPrivacyDot_NoFaceScanning() { 507 setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 508 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 509 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 510 511 // no cutout (default) 512 513 mScreenDecorations.start(); 514 515 // Top and bottom windows are created for rounded corners. 516 // Left and right window should be null. 517 verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); 518 519 // Rounded corner views shall exist 520 verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true); 521 verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true); 522 523 // Privacy dots shall not exist 524 verifyDotViewsNullable(true); 525 526 // Face scanning doesn't exist 527 verifyFaceScanningViewExists(false); 528 529 // No dot controller init 530 verify(mDotViewController, never()).initialize(any(), any(), any(), any()); 531 } 532 533 @Test testRounding_NoCutout_PrivacyDot_NoFaceScanning()534 public void testRounding_NoCutout_PrivacyDot_NoFaceScanning() { 535 setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 536 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 537 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 538 539 // no cutout (default) 540 541 mScreenDecorations.start(); 542 543 // Top and bottom windows are created for rounded corners. 544 // Left and right window should be null. 545 verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); 546 verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); 547 verify(mDotViewController, times(1)).setShowingListener(null); 548 549 // Rounded corner views shall exist 550 verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true); 551 verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true); 552 553 // Privacy dots shall exist but invisible 554 verifyDotViewsVisibility(View.INVISIBLE); 555 556 // Face scanning doesn't exist 557 verifyFaceScanningViewExists(false); 558 559 // Dot controller init 560 verify(mDotViewController, times(1)).initialize( 561 isA(View.class), isA(View.class), isA(View.class), isA(View.class)); 562 } 563 564 @Test testRoundingRadius_NoCutout()565 public void testRoundingRadius_NoCutout() { 566 final Size testRadiusPoint = new Size(3, 3); 567 setupResources(1 /* radius */, 1 /* radiusTop */, 1 /* radiusBottom */, 568 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px) 569 /* roundedTopDrawable */, 570 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px) 571 /* roundedBottomDrawable */, 572 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 573 574 // no cutout (default) 575 576 mScreenDecorations.start(); 577 // Size of corner view should same as rounded_corner_radius{_top|_bottom} 578 final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate; 579 assertThat(resDelegate.getTopRoundedSize()).isEqualTo(testRadiusPoint); 580 assertThat(resDelegate.getBottomRoundedSize()).isEqualTo(testRadiusPoint); 581 } 582 583 @Test testRoundingTopBottomRadius_OnTopBottomOverlay()584 public void testRoundingTopBottomRadius_OnTopBottomOverlay() { 585 setupResources(1 /* radius */, 1 /* radiusTop */, 1 /* radiusBottom */, 586 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px) 587 /* roundedTopDrawable */, 588 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px) 589 /* roundedBottomDrawable */, 590 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 591 592 // no cutout (default) 593 594 mScreenDecorations.start(); 595 View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView() 596 .findViewById(R.id.rounded_corner_top_left); 597 View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView() 598 .findViewById(R.id.rounded_corner_top_right); 599 ViewGroup.LayoutParams leftParams = leftRoundedCorner.getLayoutParams(); 600 ViewGroup.LayoutParams rightParams = rightRoundedCorner.getLayoutParams(); 601 assertEquals(4, leftParams.width); 602 assertEquals(4, leftParams.height); 603 assertEquals(4, rightParams.width); 604 assertEquals(4, rightParams.height); 605 606 leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView() 607 .findViewById(R.id.rounded_corner_bottom_left); 608 rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView() 609 .findViewById(R.id.rounded_corner_bottom_right); 610 leftParams = leftRoundedCorner.getLayoutParams(); 611 rightParams = rightRoundedCorner.getLayoutParams(); 612 assertEquals(3, leftParams.width); 613 assertEquals(3, leftParams.height); 614 assertEquals(3, rightParams.width); 615 assertEquals(3, rightParams.height); 616 } 617 618 @Test testRoundingTopBottomRadius_OnLeftRightOverlay()619 public void testRoundingTopBottomRadius_OnLeftRightOverlay() { 620 setupResources(1 /* radius */, 1 /* radiusTop */, 1 /* radiusBottom */, 621 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px) 622 /* roundedTopDrawable */, 623 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px) 624 /* roundedBottomDrawable */, 625 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 626 627 // left cutout 628 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT)); 629 630 mScreenDecorations.start(); 631 View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView() 632 .findViewById(R.id.rounded_corner_top_left); 633 View bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView() 634 .findViewById(R.id.rounded_corner_bottom_left); 635 ViewGroup.LayoutParams topParams = topRoundedCorner.getLayoutParams(); 636 ViewGroup.LayoutParams bottomParams = bottomRoundedCorner.getLayoutParams(); 637 assertEquals(3, topParams.width); 638 assertEquals(3, topParams.height); 639 assertEquals(5, bottomParams.width); 640 assertEquals(5, bottomParams.height); 641 642 topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView() 643 .findViewById(R.id.rounded_corner_top_right); 644 bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView() 645 .findViewById(R.id.rounded_corner_bottom_right); 646 topParams = topRoundedCorner.getLayoutParams(); 647 bottomParams = bottomRoundedCorner.getLayoutParams(); 648 assertEquals(3, topParams.width); 649 assertEquals(3, topParams.height); 650 assertEquals(5, bottomParams.width); 651 assertEquals(5, bottomParams.height); 652 } 653 654 @Test testNoRounding_CutoutShortEdge_NoPrivacyDot()655 public void testNoRounding_CutoutShortEdge_NoPrivacyDot() { 656 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 657 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 658 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 659 660 // top cutout 661 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 662 663 mScreenDecorations.start(); 664 // Top window is created for top cutout. 665 // Bottom, left, or right window should be null. 666 verifyOverlaysExistAndAdded(false, true, false, false, View.VISIBLE); 667 668 // Privacy dots shall not exist because of no privacy 669 verifyDotViewsNullable(true); 670 671 // No dot controller init 672 verify(mDotViewController, never()).initialize(any(), any(), any(), any()); 673 } 674 675 @Test testNoRounding_CutoutShortEdge_PrivacyDot()676 public void testNoRounding_CutoutShortEdge_PrivacyDot() { 677 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 678 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 679 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 680 681 // top cutout 682 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 683 684 mScreenDecorations.start(); 685 // Top window is created for top cutout. 686 // Bottom window is created for privacy dot. 687 // Left or right window should be null. 688 verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); 689 verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); 690 verify(mDotViewController, times(1)).setShowingListener(null); 691 692 // Top rounded corner views shall exist because of cutout 693 // but be gone because of no rounded corner 694 verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false); 695 // Bottom rounded corner views shall exist because of privacy dot 696 // but be gone because of no rounded corner 697 verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false); 698 699 // Privacy dots shall exist but invisible 700 verifyDotViewsVisibility(View.INVISIBLE); 701 702 // Dot controller init 703 verify(mDotViewController, times(1)).initialize( 704 isA(View.class), isA(View.class), isA(View.class), isA(View.class)); 705 } 706 707 @Test testNoRounding_CutoutLongEdge_NoPrivacyDot()708 public void testNoRounding_CutoutLongEdge_NoPrivacyDot() { 709 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 710 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 711 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 712 713 // left cutout 714 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT)); 715 716 mScreenDecorations.start(); 717 // Left window is created for left cutout. 718 // Bottom, top, or right window should be null. 719 verifyOverlaysExistAndAdded(true, false, false, false, View.VISIBLE); 720 721 // Left rounded corner views shall exist because of cutout 722 // but be gone because of no rounded corner 723 verifyRoundedCornerViewsExist(BOUNDS_POSITION_LEFT, false); 724 725 // Top privacy dots shall not exist because of no privacy 726 verifyDotViewsNullable(true); 727 728 // No dot controller init 729 verify(mDotViewController, never()).initialize(any(), any(), any(), any()); 730 } 731 732 @Test testNoRounding_CutoutLongEdge_PrivacyDot()733 public void testNoRounding_CutoutLongEdge_PrivacyDot() { 734 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 735 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 736 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 737 738 // left cutout 739 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT)); 740 741 mScreenDecorations.start(); 742 // Left window is created for left cutout. 743 // Right window is created for privacy. 744 // Bottom, or top window should be null. 745 verifyOverlaysExistAndAdded(true, false, true, false, View.VISIBLE); 746 verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); 747 verify(mDotViewController, times(1)).setShowingListener(null); 748 749 // Privacy dots shall exist but invisible 750 verifyDotViewsVisibility(View.INVISIBLE); 751 752 // Dot controller init 753 verify(mDotViewController, times(1)).initialize( 754 isA(View.class), isA(View.class), isA(View.class), isA(View.class)); 755 } 756 757 @Test testRounding_CutoutShortEdge_NoPrivacyDot()758 public void testRounding_CutoutShortEdge_NoPrivacyDot() { 759 setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 760 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 761 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 762 763 // top cutout 764 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 765 766 mScreenDecorations.start(); 767 // Top window is created for rounded corner and top cutout. 768 // Bottom window is created for rounded corner. 769 // Left, or right window should be null. 770 verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); 771 772 // Rounded corner views shall exist 773 verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true); 774 verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true); 775 776 // Top privacy dots shall not exist because of no privacy dot 777 verifyDotViewsNullable(true); 778 779 // No dot controller init 780 verify(mDotViewController, never()).initialize(any(), any(), any(), any()); 781 } 782 783 @Test testRounding_CutoutShortEdge_PrivacyDot()784 public void testRounding_CutoutShortEdge_PrivacyDot() { 785 setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 786 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 787 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 788 789 // top cutout 790 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 791 792 mScreenDecorations.start(); 793 // Top window is created for rounded corner and top cutout. 794 // Bottom window is created for rounded corner. 795 // Left, or right window should be null. 796 verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); 797 verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); 798 verify(mDotViewController, times(1)).setShowingListener(null); 799 800 // Rounded corner views shall exist 801 verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true); 802 verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true); 803 804 // Top privacy dots shall exist but invisible 805 verifyDotViewsVisibility(View.INVISIBLE); 806 807 // Dot controller init 808 verify(mDotViewController, times(1)).initialize( 809 isA(View.class), isA(View.class), isA(View.class), isA(View.class)); 810 } 811 812 @Test testRounding_CutoutLongEdge_NoPrivacyDot()813 public void testRounding_CutoutLongEdge_NoPrivacyDot() { 814 setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 815 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 816 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 817 818 // left cutout 819 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT)); 820 821 mScreenDecorations.start(); 822 // Left window is created for rounded corner and left cutout. 823 // Right window is created for rounded corner. 824 // Top, or bottom window should be null. 825 verifyOverlaysExistAndAdded(true, false, true, false, View.VISIBLE); 826 } 827 828 @Test testRounding_CutoutLongEdge_PrivacyDot()829 public void testRounding_CutoutLongEdge_PrivacyDot() { 830 setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 831 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 832 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 833 834 // left cutout 835 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT)); 836 837 mScreenDecorations.start(); 838 // Left window is created for rounded corner, left cutout, and privacy. 839 // Right window is created for rounded corner and privacy dot. 840 // Top, or bottom window should be null. 841 verifyOverlaysExistAndAdded(true, false, true, false, View.VISIBLE); 842 verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); 843 verify(mDotViewController, times(1)).setShowingListener(null); 844 } 845 846 @Test testRounding_CutoutShortAndLongEdge_NoPrivacyDot()847 public void testRounding_CutoutShortAndLongEdge_NoPrivacyDot() { 848 setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 849 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 850 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 851 852 // top and left cutout 853 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT)); 854 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 855 856 mScreenDecorations.start(); 857 // Top window is created for rounded corner and top cutout. 858 // Bottom window is created for rounded corner. 859 // Left window is created for left cutout. 860 // Right window should be null. 861 verifyOverlaysExistAndAdded(true, true, false, true, View.VISIBLE); 862 } 863 864 @Test testRounding_CutoutShortAndLongEdge_PrivacyDot()865 public void testRounding_CutoutShortAndLongEdge_PrivacyDot() { 866 setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 867 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 868 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 869 870 // top and left cutout 871 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT)); 872 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 873 874 mScreenDecorations.start(); 875 // Top window is created for rounded corner and top cutout. 876 // Bottom window is created for rounded corner. 877 // Left window is created for left cutout. 878 // Right window should be null. 879 verifyOverlaysExistAndAdded(true, true, false, true, View.VISIBLE); 880 verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); 881 verify(mDotViewController, times(1)).setShowingListener(null); 882 } 883 884 @Test testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_NoPrivacyDot()885 public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_NoPrivacyDot() { 886 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 887 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 888 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 889 890 // Set to short edge cutout(top). 891 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 892 893 mScreenDecorations.start(); 894 verifyOverlaysExistAndAdded(false, true, false, false, View.VISIBLE); 895 896 // Switch to long edge cutout(left). 897 mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT)); 898 899 mScreenDecorations.onConfigurationChanged(new Configuration()); 900 verifyOverlaysExistAndAdded(true, false, false, false, View.VISIBLE); 901 } 902 903 @Test testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_PrivacyDot()904 public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_PrivacyDot() { 905 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 906 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 907 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 908 909 // Set to short edge cutout(top). 910 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 911 912 mScreenDecorations.start(); 913 verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); 914 verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); 915 verify(mDotViewController, times(1)).setShowingListener(null); 916 917 // Switch to long edge cutout(left). 918 mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT)); 919 920 mScreenDecorations.onConfigurationChanged(new Configuration()); 921 verifyOverlaysExistAndAdded(true, false, true, false, View.VISIBLE); 922 verify(mDotViewController, times(2)).initialize(any(), any(), any(), any()); 923 verify(mDotViewController, times(2)).setShowingListener(null); 924 925 // Verify each privacy dot id appears only once 926 mPrivacyDecorProviders.stream().map(DecorProvider::getViewId).forEach(viewId -> { 927 int findCount = 0; 928 for (OverlayWindow overlay: mScreenDecorations.mOverlays) { 929 if (overlay == null) { 930 continue; 931 } 932 final View view = overlay.getRootView().findViewById(viewId); 933 if (view != null) { 934 findCount++; 935 } 936 } 937 assertEquals(1, findCount); 938 }); 939 940 } 941 942 @Test testDelayedCutout_NoPrivacyDot()943 public void testDelayedCutout_NoPrivacyDot() { 944 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 945 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 946 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 947 948 // No cutout (default) 949 950 mScreenDecorations.start(); 951 verifyOverlaysExistAndAdded(false, false, false, false, null); 952 953 // top cutout 954 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 955 956 mScreenDecorations.onConfigurationChanged(new Configuration()); 957 958 // Only top windows should be added. 959 verifyOverlaysExistAndAdded(false, true, false, false, View.VISIBLE); 960 } 961 962 @Test testDelayedCutout_PrivacyDot()963 public void testDelayedCutout_PrivacyDot() { 964 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 965 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 966 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 967 968 // no cutout (default) 969 970 mScreenDecorations.start(); 971 // Both top and bottom windows should be added with INVISIBLE because of only privacy dot, 972 // but rounded corners visibility shall be gone because of no rounding. 973 verifyOverlaysExistAndAdded(false, true, false, true, View.INVISIBLE); 974 verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false); 975 verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false); 976 verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); 977 verify(mDotViewController, times(1)).setShowingListener( 978 mScreenDecorations.mPrivacyDotShowingListener); 979 980 // top cutout 981 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 982 983 mScreenDecorations.onConfigurationChanged(new Configuration()); 984 985 // Both top and bottom windows should be added with VISIBLE because of privacy dot and 986 // cutout, but rounded corners visibility shall be gone because of no rounding. 987 verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); 988 verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false); 989 verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false); 990 verify(mDotViewController, times(2)).initialize(any(), any(), any(), any()); 991 verify(mDotViewController, times(1)).setShowingListener(null); 992 } 993 994 @Test hasRoundedCornerOverlayFlagSet()995 public void hasRoundedCornerOverlayFlagSet() { 996 assertThat(mScreenDecorations.getWindowLayoutParams(1).privateFlags 997 & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, 998 is(PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY)); 999 } 1000 1001 @Test testUpdateRoundedCorners()1002 public void testUpdateRoundedCorners() { 1003 setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 1004 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px) 1005 /* roundedTopDrawable */, 1006 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px) 1007 /* roundedBottomDrawable */, 1008 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/); 1009 mDisplayInfo.rotation = Surface.ROTATION_0; 1010 1011 mScreenDecorations.start(); 1012 1013 final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate; 1014 assertEquals(new Size(3, 3), resDelegate.getTopRoundedSize()); 1015 assertEquals(new Size(4, 4), resDelegate.getBottomRoundedSize()); 1016 1017 doReturn(2f).when(mScreenDecorations).getPhysicalPixelDisplaySizeRatio(); 1018 mDisplayInfo.rotation = Surface.ROTATION_270; 1019 1020 mScreenDecorations.onConfigurationChanged(null); 1021 1022 assertEquals(new Size(6, 6), resDelegate.getTopRoundedSize()); 1023 assertEquals(new Size(8, 8), resDelegate.getBottomRoundedSize()); 1024 } 1025 1026 @Test testOnlyRoundedCornerRadiusTop()1027 public void testOnlyRoundedCornerRadiusTop() { 1028 setupResources(0 /* radius */, 10 /* radiusTop */, 0 /* radiusBottom */, 1029 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 1030 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 1031 1032 mScreenDecorations.start(); 1033 1034 final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate; 1035 assertEquals(true, resDelegate.getHasTop()); 1036 assertEquals(false, resDelegate.getHasBottom()); 1037 assertEquals(getDrawableIntrinsicSize(R.drawable.rounded_corner_top), 1038 resDelegate.getTopRoundedSize()); 1039 1040 final DecorProviderFactory mRoundedCornerFactory = mScreenDecorations.mRoundedCornerFactory; 1041 assertEquals(true, mRoundedCornerFactory.getHasProviders()); 1042 final List<DecorProvider> providers = mRoundedCornerFactory.getProviders(); 1043 assertEquals(2, providers.size()); 1044 assertEquals(true, providers.get(0).getAlignedBounds().contains(BOUNDS_POSITION_TOP)); 1045 assertEquals(true, providers.get(1).getAlignedBounds().contains(BOUNDS_POSITION_TOP)); } 1046 1047 @Test testOnlyRoundedCornerRadiusBottom()1048 public void testOnlyRoundedCornerRadiusBottom() { 1049 setupResources(0 /* radius */, 0 /* radiusTop */, 20 /* radiusBottom */, 1050 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 1051 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 1052 1053 mScreenDecorations.start(); 1054 1055 final RoundedCornerResDelegate resDelegate = mScreenDecorations.mRoundedCornerResDelegate; 1056 assertEquals(false, resDelegate.getHasTop()); 1057 assertEquals(true, resDelegate.getHasBottom()); 1058 assertEquals(getDrawableIntrinsicSize(R.drawable.rounded_corner_bottom), 1059 resDelegate.getBottomRoundedSize()); 1060 1061 final DecorProviderFactory mRoundedCornerFactory = mScreenDecorations.mRoundedCornerFactory; 1062 assertEquals(true, mRoundedCornerFactory.getHasProviders()); 1063 final List<DecorProvider> providers = mRoundedCornerFactory.getProviders(); 1064 assertEquals(2, providers.size()); 1065 assertEquals(true, providers.get(0).getAlignedBounds().contains(BOUNDS_POSITION_BOTTOM)); 1066 assertEquals(true, providers.get(1).getAlignedBounds().contains(BOUNDS_POSITION_BOTTOM)); 1067 } 1068 1069 @Test testDebugRoundedCorners_noDeviceCornersSet()1070 public void testDebugRoundedCorners_noDeviceCornersSet() { 1071 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 1072 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 1073 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 1074 1075 mScreenDecorations.start(); 1076 // No rounded corners exist at this point 1077 verifyOverlaysExistAndAdded(false, false, false, false, View.VISIBLE); 1078 1079 // Path from rounded.xml, scaled by 10x to produce 80x80 corners 1080 Path debugPath = PathParser.createPathFromPathData("M8,0H0v8C0,3.6,3.6,0,8,0z"); 1081 // WHEN debug corners are added to the delegate 1082 DebugRoundedCornerModel debugCorner = new DebugRoundedCornerModel( 1083 debugPath, 1084 80, 1085 80, 1086 10f, 1087 10f 1088 ); 1089 mScreenDecorations.mDebugRoundedCornerDelegate 1090 .applyNewDebugCorners(debugCorner, debugCorner); 1091 1092 // AND debug mode is entered 1093 mScreenDecorations.setDebug(true); 1094 mExecutor.runAllReady(); 1095 1096 // THEN the debug corners provide decor 1097 List<DecorProvider> providers = mScreenDecorations.getProviders(false); 1098 assertEquals(4, providers.size()); 1099 1100 // Top and bottom overlays contain the debug rounded corners 1101 verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); 1102 } 1103 1104 @Test testDebugRoundedCornersRemoved_noDeviceCornersSet()1105 public void testDebugRoundedCornersRemoved_noDeviceCornersSet() { 1106 // GIVEN a device with no rounded corners defined 1107 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 1108 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 1109 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 1110 1111 mScreenDecorations.start(); 1112 // No rounded corners exist at this point 1113 verifyOverlaysExistAndAdded(false, false, false, false, View.VISIBLE); 1114 1115 // Path from rounded.xml, scaled by 10x to produce 80x80 corners 1116 Path debugPath = PathParser.createPathFromPathData("M8,0H0v8C0,3.6,3.6,0,8,0z"); 1117 // WHEN debug corners are added to the delegate 1118 DebugRoundedCornerModel debugCorner = new DebugRoundedCornerModel( 1119 debugPath, 1120 80, 1121 80, 1122 10f, 1123 10f 1124 ); 1125 mScreenDecorations.mDebugRoundedCornerDelegate 1126 .applyNewDebugCorners(debugCorner, debugCorner); 1127 1128 // AND debug mode is entered 1129 mScreenDecorations.setDebug(true); 1130 mExecutor.runAllReady(); 1131 1132 // Top and bottom overlays contain the debug rounded corners 1133 verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); 1134 1135 // WHEN debug is exited 1136 mScreenDecorations.setDebug(false); 1137 mExecutor.runAllReady(); 1138 1139 // THEN the decor is removed 1140 verifyOverlaysExistAndAdded(false, false, false, false, View.VISIBLE); 1141 assertThat(mScreenDecorations.mDebugRoundedCornerDelegate.getHasBottom()).isFalse(); 1142 assertThat(mScreenDecorations.mDebugRoundedCornerDelegate.getHasTop()).isFalse(); 1143 } 1144 1145 @Test testRegistration_From_NoOverlay_To_HasOverlays()1146 public void testRegistration_From_NoOverlay_To_HasOverlays() { 1147 doReturn(false).when(mScreenDecorations).hasOverlays(); 1148 mScreenDecorations.start(); 1149 assertThat(mScreenDecorations.mIsRegistered, is(false)); 1150 1151 doReturn(true).when(mScreenDecorations).hasOverlays(); 1152 mScreenDecorations.onConfigurationChanged(new Configuration()); 1153 assertThat(mScreenDecorations.mIsRegistered, is(true)); 1154 } 1155 1156 @Test testRegistration_From_HasOverlays_To_HasOverlays()1157 public void testRegistration_From_HasOverlays_To_HasOverlays() { 1158 doReturn(true).when(mScreenDecorations).hasOverlays(); 1159 1160 mScreenDecorations.start(); 1161 assertThat(mScreenDecorations.mIsRegistered, is(true)); 1162 1163 mScreenDecorations.onConfigurationChanged(new Configuration()); 1164 assertThat(mScreenDecorations.mIsRegistered, is(true)); 1165 } 1166 1167 @Test testRegistration_From_HasOverlays_To_NoOverlay()1168 public void testRegistration_From_HasOverlays_To_NoOverlay() { 1169 doReturn(true).when(mScreenDecorations).hasOverlays(); 1170 1171 mScreenDecorations.start(); 1172 assertThat(mScreenDecorations.mIsRegistered, is(true)); 1173 1174 doReturn(false).when(mScreenDecorations).hasOverlays(); 1175 mScreenDecorations.onConfigurationChanged(new Configuration()); 1176 assertThat(mScreenDecorations.mIsRegistered, is(false)); 1177 } 1178 1179 @Test testSupportHwcLayer_SwitchFrom_NotSupport()1180 public void testSupportHwcLayer_SwitchFrom_NotSupport() { 1181 setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */, 1182 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 1183 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 1184 1185 // top cutout 1186 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 1187 1188 mScreenDecorations.start(); 1189 // should only inflate mOverlays when the hwc doesn't support screen decoration 1190 assertNull(mScreenDecorations.mScreenDecorHwcWindow); 1191 verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); 1192 1193 final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport(); 1194 decorationSupport.format = PixelFormat.R_8; 1195 doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport(); 1196 // Trigger the support hwc screen decoration change by changing the display unique id 1197 mScreenDecorations.mDisplayUniqueId = "test"; 1198 mScreenDecorations.mDisplayListener.onDisplayChanged(1); 1199 1200 // should only inflate hwc layer when the hwc supports screen decoration 1201 assertNotNull(mScreenDecorations.mScreenDecorHwcWindow); 1202 verifyOverlaysExistAndAdded(false, false, false, false, null); 1203 } 1204 1205 @Test testNotSupportHwcLayer_SwitchFrom_Support()1206 public void testNotSupportHwcLayer_SwitchFrom_Support() { 1207 setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */, 1208 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 1209 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 1210 final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport(); 1211 decorationSupport.format = PixelFormat.R_8; 1212 doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport(); 1213 1214 // top cutout 1215 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 1216 1217 mScreenDecorations.start(); 1218 // should only inflate hwc layer when the hwc supports screen decoration 1219 assertNotNull(mScreenDecorations.mScreenDecorHwcWindow); 1220 verifyOverlaysExistAndAdded(false, false, false, false, null); 1221 1222 doReturn(null).when(mDisplay).getDisplayDecorationSupport(); 1223 // Trigger the support hwc screen decoration change by changing the display unique id 1224 mScreenDecorations.mDisplayUniqueId = "test"; 1225 mScreenDecorations.mDisplayListener.onDisplayChanged(1); 1226 1227 // should only inflate mOverlays when the hwc doesn't support screen decoration 1228 assertNull(mScreenDecorations.mScreenDecorHwcWindow); 1229 verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE); 1230 } 1231 1232 @Test faceSensorLocationChangesReloadsFaceScanningOverlay()1233 public void faceSensorLocationChangesReloadsFaceScanningOverlay() { 1234 mFaceScanningProviders = new ArrayList<>(); 1235 mFaceScanningProviders.add(mFaceScanningDecorProvider); 1236 when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders); 1237 when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(true); 1238 ScreenDecorations screenDecorations = new ScreenDecorations(mContext, 1239 mSecureSettings, mCommandRegistry, mUserTracker, mDisplayTracker, 1240 mDotViewController, 1241 mThreadFactory, mPrivacyDotDecorProviderFactory, mFaceScanningProviderFactory, 1242 new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer")), mAuthController); 1243 screenDecorations.start(); 1244 verify(mAuthController).addCallback(mAuthControllerCallback.capture()); 1245 when(mContext.getDisplay()).thenReturn(mDisplay); 1246 when(mDisplay.getDisplayInfo(any())).thenAnswer(new Answer<Boolean>() { 1247 @Override 1248 public Boolean answer(InvocationOnMock invocation) throws Throwable { 1249 DisplayInfo displayInfo = invocation.getArgument(0); 1250 int modeId = 1; 1251 displayInfo.modeId = modeId; 1252 displayInfo.supportedModes = new Display.Mode[]{new Display.Mode(modeId, 1024, 1024, 1253 90)}; 1254 return false; 1255 } 1256 }); 1257 mExecutor.runAllReady(); 1258 clearInvocations(mFaceScanningDecorProvider); 1259 1260 AuthController.Callback callback = mAuthControllerCallback.getValue(); 1261 callback.onFaceSensorLocationChanged(); 1262 mExecutor.runAllReady(); 1263 1264 verify(mFaceScanningDecorProvider).onReloadResAndMeasure(any(), 1265 anyInt(), 1266 anyInt(), 1267 anyInt(), 1268 any()); 1269 } 1270 1271 @Test testPrivacyDotShowingListenerWorkWellWithNullParameter()1272 public void testPrivacyDotShowingListenerWorkWellWithNullParameter() { 1273 mPrivacyDotShowingListener.onPrivacyDotShown(null); 1274 mPrivacyDotShowingListener.onPrivacyDotHidden(null); 1275 } 1276 1277 @Test testAutoShowHideOverlayWindowWhenSupportHwcLayer()1278 public void testAutoShowHideOverlayWindowWhenSupportHwcLayer() { 1279 setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */, 1280 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px) 1281 /* roundedTopDrawable */, 1282 getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px) 1283 /* roundedBottomDrawable */, 1284 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */); 1285 final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport(); 1286 decorationSupport.format = PixelFormat.R_8; 1287 doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport(); 1288 1289 // top cutout 1290 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 1291 1292 mScreenDecorations.start(); 1293 // Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer 1294 verifyOverlaysExistAndAdded(false, true, false, true, View.INVISIBLE); 1295 1296 // Make sure view found and window visibility changed as well 1297 final View view = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView() 1298 .findViewById(R.id.privacy_dot_bottom_right_container); 1299 view.setVisibility(View.VISIBLE); 1300 mPrivacyDotShowingListener.onPrivacyDotShown(view); 1301 assertEquals(View.VISIBLE, 1302 mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView().getVisibility()); 1303 view.setVisibility(View.INVISIBLE); 1304 mPrivacyDotShowingListener.onPrivacyDotHidden(view); 1305 assertEquals(View.INVISIBLE, 1306 mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView().getVisibility()); 1307 1308 // Make sure face scanning view found and window visibility updates on camera protection 1309 // update 1310 final View faceScanView = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView() 1311 .findViewById(mFaceScanningDecorProvider.getViewId()); 1312 when(mFaceScanningProviderFactory.shouldShowFaceScanningAnim()).thenReturn(true); 1313 faceScanView.setVisibility(View.VISIBLE); 1314 mScreenDecorations.showCameraProtection(new Path(), new Rect()); 1315 mExecutor.runAllReady(); 1316 assertEquals(View.VISIBLE, 1317 mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView().getVisibility()); 1318 } 1319 1320 @Test testAutoShowHideOverlayWindowWhenNoRoundedAndNoCutout()1321 public void testAutoShowHideOverlayWindowWhenNoRoundedAndNoCutout() { 1322 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 1323 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 1324 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */); 1325 1326 // no cutout (default) 1327 1328 mScreenDecorations.start(); 1329 // Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer 1330 verifyOverlaysExistAndAdded(false, true, false, true, View.INVISIBLE); 1331 1332 // Make sure view found and window visibility changed as well 1333 final View view = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView() 1334 .findViewById(R.id.privacy_dot_bottom_right_container); 1335 view.setVisibility(View.VISIBLE); 1336 mPrivacyDotShowingListener.onPrivacyDotShown(view); 1337 assertEquals(View.VISIBLE, 1338 mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView().getVisibility()); 1339 view.setVisibility(View.INVISIBLE); 1340 mPrivacyDotShowingListener.onPrivacyDotHidden(view); 1341 assertEquals(View.INVISIBLE, 1342 mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView().getVisibility()); 1343 1344 // Make sure face scanning view found and window visibility updates on camera protection 1345 // update 1346 final View faceScanView = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView() 1347 .findViewById(mFaceScanningDecorProvider.getViewId()); 1348 faceScanView.setVisibility(View.VISIBLE); 1349 when(mFaceScanningProviderFactory.shouldShowFaceScanningAnim()).thenReturn(true); 1350 mScreenDecorations.showCameraProtection(new Path(), new Rect()); 1351 mExecutor.runAllReady(); 1352 assertEquals(View.VISIBLE, 1353 mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView().getVisibility()); 1354 } 1355 1356 @Test testHwcLayer_noPrivacyDot_noFaceScanning()1357 public void testHwcLayer_noPrivacyDot_noFaceScanning() { 1358 setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */, 1359 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 1360 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 1361 final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport(); 1362 decorationSupport.format = PixelFormat.R_8; 1363 doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport(); 1364 1365 // top cutout 1366 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 1367 1368 mScreenDecorations.start(); 1369 1370 // Should only inflate hwc layer. 1371 assertNotNull(mScreenDecorations.mScreenDecorHwcWindow); 1372 verifyOverlaysExistAndAdded(false, false, false, false, null); 1373 } 1374 1375 @Test testHwcLayer_PrivacyDot_FaceScanning()1376 public void testHwcLayer_PrivacyDot_FaceScanning() { 1377 setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */, 1378 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 1379 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */); 1380 final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport(); 1381 decorationSupport.format = PixelFormat.R_8; 1382 doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport(); 1383 1384 // top cutout 1385 mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP)); 1386 1387 mScreenDecorations.start(); 1388 1389 assertNotNull(mScreenDecorations.mScreenDecorHwcWindow); 1390 // mOverlays are inflated but the visibility should be INVISIBLE. 1391 verifyOverlaysExistAndAdded(false, true, false, true, View.INVISIBLE); 1392 verify(mDotViewController, times(1)).initialize(any(), any(), any(), any()); 1393 verify(mDotViewController, times(1)).setShowingListener( 1394 mScreenDecorations.mPrivacyDotShowingListener); 1395 1396 verifyFaceScanningViewExists(true); 1397 } 1398 1399 @Test testHasSameProvidersWithNullOverlays()1400 public void testHasSameProvidersWithNullOverlays() { 1401 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 1402 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 1403 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */); 1404 1405 mScreenDecorations.start(); 1406 1407 final ArrayList<DecorProvider> newProviders = new ArrayList<>(); 1408 assertTrue(mScreenDecorations.hasSameProviders(newProviders)); 1409 1410 newProviders.add(mPrivacyDotTopLeftDecorProvider); 1411 assertFalse(mScreenDecorations.hasSameProviders(newProviders)); 1412 1413 newProviders.add(mPrivacyDotTopRightDecorProvider); 1414 assertFalse(mScreenDecorations.hasSameProviders(newProviders)); 1415 } 1416 1417 @Test testHasSameProvidersWithPrivacyDots()1418 public void testHasSameProvidersWithPrivacyDots() { 1419 setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */, 1420 null /* roundedTopDrawable */, null /* roundedBottomDrawable */, 1421 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */); 1422 1423 mScreenDecorations.start(); 1424 1425 final ArrayList<DecorProvider> newProviders = new ArrayList<>(); 1426 assertFalse(mScreenDecorations.hasSameProviders(newProviders)); 1427 1428 newProviders.add(mPrivacyDotTopLeftDecorProvider); 1429 assertFalse(mScreenDecorations.hasSameProviders(newProviders)); 1430 1431 newProviders.add(mPrivacyDotTopRightDecorProvider); 1432 assertFalse(mScreenDecorations.hasSameProviders(newProviders)); 1433 1434 newProviders.add(mPrivacyDotBottomLeftDecorProvider); 1435 assertFalse(mScreenDecorations.hasSameProviders(newProviders)); 1436 1437 newProviders.add(mPrivacyDotBottomRightDecorProvider); 1438 assertTrue(mScreenDecorations.hasSameProviders(newProviders)); 1439 } 1440 getDrawableIntrinsicSize(@rawableRes int drawableResId)1441 private Size getDrawableIntrinsicSize(@DrawableRes int drawableResId) { 1442 final Drawable d = mContext.getDrawable(drawableResId); 1443 return new Size(d.getIntrinsicWidth(), d.getIntrinsicHeight()); 1444 } 1445 1446 @Nullable getTestsDrawable(@rawableRes int drawableId)1447 private Drawable getTestsDrawable(@DrawableRes int drawableId) { 1448 try { 1449 return mContext.createPackageContext("com.android.systemui.tests", 0) 1450 .getDrawable(drawableId); 1451 } catch (PackageManager.NameNotFoundException exception) { 1452 return null; 1453 } 1454 } 1455 setupResources(int radius, int radiusTop, int radiusBottom, @Nullable Drawable roundedTopDrawable, @Nullable Drawable roundedBottomDrawable, int roundedPadding, boolean privacyDot, boolean faceScanning)1456 private void setupResources(int radius, int radiusTop, int radiusBottom, 1457 @Nullable Drawable roundedTopDrawable, @Nullable Drawable roundedBottomDrawable, 1458 int roundedPadding, boolean privacyDot, boolean faceScanning) { 1459 mContext.getOrCreateTestableResources().addOverride( 1460 com.android.internal.R.array.config_displayUniqueIdArray, 1461 new String[]{}); 1462 mContext.getOrCreateTestableResources().addOverride( 1463 com.android.internal.R.array.config_roundedCornerRadiusArray, 1464 mMockTypedArray); 1465 mContext.getOrCreateTestableResources().addOverride( 1466 com.android.internal.R.array.config_roundedCornerTopRadiusArray, 1467 mMockTypedArray); 1468 mContext.getOrCreateTestableResources().addOverride( 1469 com.android.internal.R.array.config_roundedCornerBottomRadiusArray, 1470 mMockTypedArray); 1471 mContext.getOrCreateTestableResources().addOverride( 1472 R.array.config_roundedCornerDrawableArray, 1473 mMockTypedArray); 1474 mContext.getOrCreateTestableResources().addOverride( 1475 R.array.config_roundedCornerTopDrawableArray, 1476 mMockTypedArray); 1477 mContext.getOrCreateTestableResources().addOverride( 1478 R.array.config_roundedCornerBottomDrawableArray, 1479 mMockTypedArray); 1480 mContext.getOrCreateTestableResources().addOverride( 1481 com.android.internal.R.dimen.rounded_corner_radius, radius); 1482 mContext.getOrCreateTestableResources().addOverride( 1483 com.android.internal.R.dimen.rounded_corner_radius_top, radiusTop); 1484 mContext.getOrCreateTestableResources().addOverride( 1485 com.android.internal.R.dimen.rounded_corner_radius_bottom, radiusBottom); 1486 if (roundedTopDrawable != null) { 1487 mContext.getOrCreateTestableResources().addOverride( 1488 R.drawable.rounded_corner_top, 1489 roundedTopDrawable); 1490 } 1491 if (roundedBottomDrawable != null) { 1492 mContext.getOrCreateTestableResources().addOverride( 1493 R.drawable.rounded_corner_bottom, 1494 roundedBottomDrawable); 1495 } 1496 mContext.getOrCreateTestableResources().addOverride( 1497 R.dimen.rounded_corner_content_padding, roundedPadding); 1498 1499 mPrivacyDecorProviders = new ArrayList<>(); 1500 if (privacyDot) { 1501 mPrivacyDecorProviders.add(mPrivacyDotTopLeftDecorProvider); 1502 mPrivacyDecorProviders.add(mPrivacyDotTopRightDecorProvider); 1503 mPrivacyDecorProviders.add(mPrivacyDotBottomLeftDecorProvider); 1504 mPrivacyDecorProviders.add(mPrivacyDotBottomRightDecorProvider); 1505 } 1506 when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mPrivacyDecorProviders); 1507 when(mPrivacyDotDecorProviderFactory.getHasProviders()).thenReturn(privacyDot); 1508 1509 mFaceScanningProviders = new ArrayList<>(); 1510 if (faceScanning) { 1511 mFaceScanningProviders.add(mFaceScanningDecorProvider); 1512 } 1513 when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders); 1514 when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(faceScanning); 1515 } 1516 } 1517