Loading packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +7 −2 Original line number Diff line number Diff line Loading @@ -65,7 +65,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.CoreStartable; import com.android.systemui.assist.ui.DisplayUtils; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; Loading Loading @@ -600,8 +599,14 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class); } private int getDisplayWidth() { DisplayInfo displayInfo = new DisplayInfo(); mContext.getDisplay().getDisplayInfo(displayInfo); return displayInfo.getNaturalWidth(); } private void updateFingerprintLocation() { int xLocation = DisplayUtils.getWidth(mContext) / 2; int xLocation = getDisplayWidth() / 2; try { xLocation = mContext.getResources().getDimensionPixelSize( com.android.systemui.R.dimen Loading packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt +40 −48 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal import android.hardware.fingerprint.ISidefpsController import android.os.Handler import android.util.Log import android.util.RotationUtils import android.view.View.AccessibilityDelegate import android.view.accessibility.AccessibilityEvent import android.view.Display Loading Loading @@ -116,7 +117,8 @@ class SidefpsController @Inject constructor( orientationListener.enable() } } private var overlayOffsets: SensorLocationInternal = SensorLocationInternal.DEFAULT @VisibleForTesting internal var overlayOffsets: SensorLocationInternal = SensorLocationInternal.DEFAULT private val overlayViewParams = WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, Loading @@ -141,7 +143,7 @@ class SidefpsController @Inject constructor( private fun doShow() = mainExecutor.execute { if (overlayView == null) { overlayView = createOverlayForDisplay() createOverlayForDisplay() } else { Log.v(TAG, "overlay already shown") } Loading @@ -154,14 +156,14 @@ class SidefpsController @Inject constructor( private fun onOrientationChanged() { if (overlayView != null) { overlayView = createOverlayForDisplay() createOverlayForDisplay() } } private fun createOverlayForDisplay(): View { private fun createOverlayForDisplay() { val view = layoutInflater.inflate(R.layout.sidefps_view, null, false) overlayView = view val display = context.display!! val offsets = sensorProps.getLocation(display.uniqueId).let { location -> if (location == null) { Log.w(TAG, "No location specified for display: ${display.uniqueId}") Loading @@ -172,13 +174,11 @@ class SidefpsController @Inject constructor( val lottie = view.findViewById(R.id.sidefps_animation) as LottieAnimationView view.rotation = display.asSideFpsAnimationRotation(offsets.isYAligned()) updateOverlayParams(display, lottie.composition?.bounds ?: Rect()) lottie.setAnimation(display.asSideFpsAnimation(offsets.isYAligned())) lottie.addLottieOnCompositionLoadedListener { if (overlayView == view) { // Check that view is not stale, and that overlayView has not been hidden/removed if (overlayView != null && overlayView == view) { updateOverlayParams(display, it.bounds) windowManager.updateViewLayout(overlayView, overlayViewParams) } } lottie.addOverlayDynamicColor(context) Loading @@ -200,55 +200,47 @@ class SidefpsController @Inject constructor( } } }) return view } private fun updateOverlayParams(display: Display, bounds: Rect) { val isPortrait = display.isPortrait() @VisibleForTesting internal fun updateOverlayParams(display: Display, bounds: Rect) { val isNaturalOrientation = display.isNaturalOrientation() val size = windowManager.maximumWindowMetrics.bounds val displayWidth = if (isPortrait) size.width() else size.height() val displayHeight = if (isPortrait) size.height() else size.width() // ignore sensorRadius since it's assumed that the sensor is on the side and centered at // either sensorLocationX or sensorLocationY (both should not be set) val (x, y) = if (overlayOffsets.isYAligned()) { when (display.rotation) { Surface.ROTATION_90 -> Pair(overlayOffsets.sensorLocationY, 0) Surface.ROTATION_270 -> Pair( displayHeight - overlayOffsets.sensorLocationY - bounds.width(), displayWidth + bounds.height() val displayWidth = if (isNaturalOrientation) size.width() else size.height() val displayHeight = if (isNaturalOrientation) size.height() else size.width() val boundsWidth = if (isNaturalOrientation) bounds.width() else bounds.height() val boundsHeight = if (isNaturalOrientation) bounds.height() else bounds.width() val sensorBounds = if (overlayOffsets.isYAligned()) { Rect( displayWidth - boundsWidth, overlayOffsets.sensorLocationY, displayWidth, overlayOffsets.sensorLocationY + boundsHeight ) Surface.ROTATION_180 -> Pair(0, displayHeight - overlayOffsets.sensorLocationY - bounds.height()) else -> Pair(displayWidth, overlayOffsets.sensorLocationY) } } else { when (display.rotation) { Surface.ROTATION_90 -> Pair(0, displayWidth - overlayOffsets.sensorLocationX - bounds.height()) Surface.ROTATION_270 -> Pair(displayWidth, overlayOffsets.sensorLocationX - bounds.height()) Surface.ROTATION_180 -> Pair( displayWidth - overlayOffsets.sensorLocationX - bounds.width(), displayHeight Rect( overlayOffsets.sensorLocationX, 0, overlayOffsets.sensorLocationX + boundsWidth, boundsHeight ) else -> Pair(overlayOffsets.sensorLocationX, 0) } } overlayViewParams.x = x overlayViewParams.y = y RotationUtils.rotateBounds( sensorBounds, Rect(0, 0, displayWidth, displayHeight), display.rotation ) overlayViewParams.x = sensorBounds.left overlayViewParams.y = sensorBounds.top windowManager.updateViewLayout(overlayView, overlayViewParams) } private fun updateOverlayVisibility(view: View) { if (view != overlayView) { return } // hide after a few seconds if the sensor is oriented down and there are // large overlapping system bars val rotation = context.display?.rotation Loading Loading @@ -304,7 +296,7 @@ private fun Display.asSideFpsAnimationRotation(yAligned: Boolean): Float = when private fun SensorLocationInternal.isYAligned(): Boolean = sensorLocationY != 0 private fun Display.isPortrait(): Boolean = private fun Display.isNaturalOrientation(): Boolean = rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 private fun WindowInsets.hasBigNavigationBar(): Boolean = Loading packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt +91 −33 Original line number Diff line number Diff line Loading @@ -77,12 +77,6 @@ import org.mockito.junit.MockitoJUnit private const val DISPLAY_ID = 2 private const val SENSOR_ID = 1 private const val DISPLAY_SIZE_X = 800 private const val DISPLAY_SIZE_Y = 900 private val X_LOCATION = SensorLocationInternal("", 540, 0, 20) private val Y_LOCATION = SensorLocationInternal("", 0, 1500, 22) @SmallTest @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper Loading Loading @@ -116,6 +110,17 @@ class SidefpsControllerTest : SysuiTestCase() { private lateinit var overlayController: ISidefpsController private lateinit var sideFpsController: SidefpsController enum class DeviceConfig { X_ALIGNED, Y_ALIGNED_UNFOLDED, Y_ALIGNED_FOLDED } private lateinit var deviceConfig: DeviceConfig private lateinit var indicatorBounds: Rect private lateinit var displayBounds: Rect private lateinit var sensorLocation: SensorLocationInternal private var displayWidth: Int = 0 private var displayHeight: Int = 0 private var boundsWidth: Int = 0 private var boundsHeight: Int = 0 @Before fun setup() { context.addMockSystemService(DisplayManager::class.java, displayManager) Loading @@ -135,17 +140,43 @@ class SidefpsControllerTest : SysuiTestCase() { this } } `when`(windowManager.maximumWindowMetrics).thenReturn( WindowMetrics(Rect(0, 0, DISPLAY_SIZE_X, DISPLAY_SIZE_Y), WindowInsets.CONSUMED) ) } private fun testWithDisplay( deviceConfig: DeviceConfig = DeviceConfig.X_ALIGNED, initInfo: DisplayInfo.() -> Unit = {}, locations: List<SensorLocationInternal> = listOf(X_LOCATION), windowInsets: WindowInsets = insetsForSmallNavbar(), block: () -> Unit ) { this.deviceConfig = deviceConfig when (deviceConfig) { DeviceConfig.X_ALIGNED -> { displayWidth = 2560 displayHeight = 1600 sensorLocation = SensorLocationInternal("", 2325, 0, 0) boundsWidth = 160 boundsHeight = 84 } DeviceConfig.Y_ALIGNED_UNFOLDED -> { displayWidth = 2208 displayHeight = 1840 sensorLocation = SensorLocationInternal("", 0, 510, 0) boundsWidth = 110 boundsHeight = 210 } DeviceConfig.Y_ALIGNED_FOLDED -> { displayWidth = 1080 displayHeight = 2100 sensorLocation = SensorLocationInternal("", 0, 590, 0) boundsWidth = 110 boundsHeight = 210 } } indicatorBounds = Rect(0, 0, boundsWidth, boundsHeight) displayBounds = Rect(0, 0, displayWidth, displayHeight) var locations = listOf(sensorLocation) `when`(fingerprintManager.sensorPropertiesInternal).thenReturn( listOf( FingerprintSensorPropertiesInternal( Loading @@ -166,8 +197,11 @@ class SidefpsControllerTest : SysuiTestCase() { val display = Display(dmGlobal, DISPLAY_ID, displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS) `when`(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo) `when`(windowManager.defaultDisplay).thenReturn(display) `when`(windowManager.maximumWindowMetrics).thenReturn( WindowMetrics(displayBounds, WindowInsets.CONSUMED) ) `when`(windowManager.currentWindowMetrics).thenReturn( WindowMetrics(Rect(0, 0, DISPLAY_SIZE_X, DISPLAY_SIZE_Y), windowInsets) WindowMetrics(displayBounds, windowInsets) ) sideFpsController = SidefpsController( Loading Loading @@ -260,46 +294,56 @@ class SidefpsControllerTest : SysuiTestCase() { } @Test fun showsWithTaskbar() = testWithDisplay({ rotation = Surface.ROTATION_0 }) { fun showsWithTaskbar() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_0 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbarOnY() = testWithDisplay( { rotation = Surface.ROTATION_0 }, locations = listOf(Y_LOCATION) deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, { rotation = Surface.ROTATION_0 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbar90() = testWithDisplay({ rotation = Surface.ROTATION_90 }) { fun showsWithTaskbar90() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_90 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbar90OnY() = testWithDisplay( { rotation = Surface.ROTATION_90 }, locations = listOf(Y_LOCATION) deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, { rotation = Surface.ROTATION_90 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbar180() = testWithDisplay({ rotation = Surface.ROTATION_180 }) { fun showsWithTaskbar180() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_180 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbar270OnY() = testWithDisplay( { rotation = Surface.ROTATION_270 }, locations = listOf(Y_LOCATION) deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, { rotation = Surface.ROTATION_270 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbarCollapsedDown() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_270 }, windowInsets = insetsForSmallNavbar() ) { Loading @@ -308,8 +352,8 @@ class SidefpsControllerTest : SysuiTestCase() { @Test fun showsWithTaskbarCollapsedDownOnY() = testWithDisplay( deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, { rotation = Surface.ROTATION_180 }, locations = listOf(Y_LOCATION), windowInsets = insetsForSmallNavbar() ) { hidesWithTaskbar(visible = true) Loading @@ -317,8 +361,8 @@ class SidefpsControllerTest : SysuiTestCase() { @Test fun hidesWithTaskbarDown() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_180 }, locations = listOf(X_LOCATION), windowInsets = insetsForLargeNavbar() ) { hidesWithTaskbar(visible = false) Loading @@ -326,18 +370,18 @@ class SidefpsControllerTest : SysuiTestCase() { @Test fun hidesWithTaskbarDownOnY() = testWithDisplay( deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, { rotation = Surface.ROTATION_270 }, locations = listOf(Y_LOCATION), windowInsets = insetsForLargeNavbar() ) { hidesWithTaskbar(visible = false) hidesWithTaskbar(visible = true) } private fun hidesWithTaskbar(visible: Boolean) { overlayController.show(SENSOR_ID, REASON_UNKNOWN) executor.runAllReady() sideFpsController.overviewProxyListener.onTaskbarStatusUpdated(true, false) sideFpsController.overviewProxyListener.onTaskbarStatusUpdated(visible, false) executor.runAllReady() verify(windowManager).addView(any(), any()) Loading @@ -346,25 +390,38 @@ class SidefpsControllerTest : SysuiTestCase() { } @Test fun setsXAlign() = testWithDisplay { fun testIndicatorPlacementForXAlignedSensor() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED ) { overlayController.show(SENSOR_ID, REASON_UNKNOWN) sideFpsController.overlayOffsets = sensorLocation sideFpsController.updateOverlayParams( windowManager.defaultDisplay, indicatorBounds ) executor.runAllReady() verify(windowManager).addView(any(), overlayViewParamsCaptor.capture()) verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture()) assertThat(overlayViewParamsCaptor.value.x).isEqualTo(X_LOCATION.sensorLocationX) assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX) assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0) } @Test fun setYAlign() = testWithDisplay(locations = listOf(Y_LOCATION)) { fun testIndicatorPlacementForYAlignedSensor() = testWithDisplay( deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED ) { sideFpsController.overlayOffsets = sensorLocation sideFpsController.updateOverlayParams( windowManager.defaultDisplay, indicatorBounds ) overlayController.show(SENSOR_ID, REASON_UNKNOWN) executor.runAllReady() verify(windowManager).addView(any(), overlayViewParamsCaptor.capture()) assertThat(overlayViewParamsCaptor.value.x).isEqualTo(DISPLAY_SIZE_X) assertThat(overlayViewParamsCaptor.value.y).isEqualTo(Y_LOCATION.sensorLocationY) verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture()) assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth) assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY) } } Loading @@ -373,6 +430,7 @@ private fun insetsForLargeNavbar() = insetsWithBottom(100) private fun insetsWithBottom(bottom: Int) = WindowInsets.Builder() .setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, bottom)) .build() private fun fpEnrollTask() = settingsTask(".biometrics.fingerprint.FingerprintEnrollEnrolling") private fun fpSettingsTask() = settingsTask(".biometrics.fingerprint.FingerprintSettings") private fun settingsTask(cls: String) = ActivityManager.RunningTaskInfo().apply { Loading Loading
packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +7 −2 Original line number Diff line number Diff line Loading @@ -65,7 +65,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.CoreStartable; import com.android.systemui.assist.ui.DisplayUtils; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; Loading Loading @@ -600,8 +599,14 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class); } private int getDisplayWidth() { DisplayInfo displayInfo = new DisplayInfo(); mContext.getDisplay().getDisplayInfo(displayInfo); return displayInfo.getNaturalWidth(); } private void updateFingerprintLocation() { int xLocation = DisplayUtils.getWidth(mContext) / 2; int xLocation = getDisplayWidth() / 2; try { xLocation = mContext.getResources().getDimensionPixelSize( com.android.systemui.R.dimen Loading
packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt +40 −48 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal import android.hardware.fingerprint.ISidefpsController import android.os.Handler import android.util.Log import android.util.RotationUtils import android.view.View.AccessibilityDelegate import android.view.accessibility.AccessibilityEvent import android.view.Display Loading Loading @@ -116,7 +117,8 @@ class SidefpsController @Inject constructor( orientationListener.enable() } } private var overlayOffsets: SensorLocationInternal = SensorLocationInternal.DEFAULT @VisibleForTesting internal var overlayOffsets: SensorLocationInternal = SensorLocationInternal.DEFAULT private val overlayViewParams = WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, Loading @@ -141,7 +143,7 @@ class SidefpsController @Inject constructor( private fun doShow() = mainExecutor.execute { if (overlayView == null) { overlayView = createOverlayForDisplay() createOverlayForDisplay() } else { Log.v(TAG, "overlay already shown") } Loading @@ -154,14 +156,14 @@ class SidefpsController @Inject constructor( private fun onOrientationChanged() { if (overlayView != null) { overlayView = createOverlayForDisplay() createOverlayForDisplay() } } private fun createOverlayForDisplay(): View { private fun createOverlayForDisplay() { val view = layoutInflater.inflate(R.layout.sidefps_view, null, false) overlayView = view val display = context.display!! val offsets = sensorProps.getLocation(display.uniqueId).let { location -> if (location == null) { Log.w(TAG, "No location specified for display: ${display.uniqueId}") Loading @@ -172,13 +174,11 @@ class SidefpsController @Inject constructor( val lottie = view.findViewById(R.id.sidefps_animation) as LottieAnimationView view.rotation = display.asSideFpsAnimationRotation(offsets.isYAligned()) updateOverlayParams(display, lottie.composition?.bounds ?: Rect()) lottie.setAnimation(display.asSideFpsAnimation(offsets.isYAligned())) lottie.addLottieOnCompositionLoadedListener { if (overlayView == view) { // Check that view is not stale, and that overlayView has not been hidden/removed if (overlayView != null && overlayView == view) { updateOverlayParams(display, it.bounds) windowManager.updateViewLayout(overlayView, overlayViewParams) } } lottie.addOverlayDynamicColor(context) Loading @@ -200,55 +200,47 @@ class SidefpsController @Inject constructor( } } }) return view } private fun updateOverlayParams(display: Display, bounds: Rect) { val isPortrait = display.isPortrait() @VisibleForTesting internal fun updateOverlayParams(display: Display, bounds: Rect) { val isNaturalOrientation = display.isNaturalOrientation() val size = windowManager.maximumWindowMetrics.bounds val displayWidth = if (isPortrait) size.width() else size.height() val displayHeight = if (isPortrait) size.height() else size.width() // ignore sensorRadius since it's assumed that the sensor is on the side and centered at // either sensorLocationX or sensorLocationY (both should not be set) val (x, y) = if (overlayOffsets.isYAligned()) { when (display.rotation) { Surface.ROTATION_90 -> Pair(overlayOffsets.sensorLocationY, 0) Surface.ROTATION_270 -> Pair( displayHeight - overlayOffsets.sensorLocationY - bounds.width(), displayWidth + bounds.height() val displayWidth = if (isNaturalOrientation) size.width() else size.height() val displayHeight = if (isNaturalOrientation) size.height() else size.width() val boundsWidth = if (isNaturalOrientation) bounds.width() else bounds.height() val boundsHeight = if (isNaturalOrientation) bounds.height() else bounds.width() val sensorBounds = if (overlayOffsets.isYAligned()) { Rect( displayWidth - boundsWidth, overlayOffsets.sensorLocationY, displayWidth, overlayOffsets.sensorLocationY + boundsHeight ) Surface.ROTATION_180 -> Pair(0, displayHeight - overlayOffsets.sensorLocationY - bounds.height()) else -> Pair(displayWidth, overlayOffsets.sensorLocationY) } } else { when (display.rotation) { Surface.ROTATION_90 -> Pair(0, displayWidth - overlayOffsets.sensorLocationX - bounds.height()) Surface.ROTATION_270 -> Pair(displayWidth, overlayOffsets.sensorLocationX - bounds.height()) Surface.ROTATION_180 -> Pair( displayWidth - overlayOffsets.sensorLocationX - bounds.width(), displayHeight Rect( overlayOffsets.sensorLocationX, 0, overlayOffsets.sensorLocationX + boundsWidth, boundsHeight ) else -> Pair(overlayOffsets.sensorLocationX, 0) } } overlayViewParams.x = x overlayViewParams.y = y RotationUtils.rotateBounds( sensorBounds, Rect(0, 0, displayWidth, displayHeight), display.rotation ) overlayViewParams.x = sensorBounds.left overlayViewParams.y = sensorBounds.top windowManager.updateViewLayout(overlayView, overlayViewParams) } private fun updateOverlayVisibility(view: View) { if (view != overlayView) { return } // hide after a few seconds if the sensor is oriented down and there are // large overlapping system bars val rotation = context.display?.rotation Loading Loading @@ -304,7 +296,7 @@ private fun Display.asSideFpsAnimationRotation(yAligned: Boolean): Float = when private fun SensorLocationInternal.isYAligned(): Boolean = sensorLocationY != 0 private fun Display.isPortrait(): Boolean = private fun Display.isNaturalOrientation(): Boolean = rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 private fun WindowInsets.hasBigNavigationBar(): Boolean = Loading
packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt +91 −33 Original line number Diff line number Diff line Loading @@ -77,12 +77,6 @@ import org.mockito.junit.MockitoJUnit private const val DISPLAY_ID = 2 private const val SENSOR_ID = 1 private const val DISPLAY_SIZE_X = 800 private const val DISPLAY_SIZE_Y = 900 private val X_LOCATION = SensorLocationInternal("", 540, 0, 20) private val Y_LOCATION = SensorLocationInternal("", 0, 1500, 22) @SmallTest @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper Loading Loading @@ -116,6 +110,17 @@ class SidefpsControllerTest : SysuiTestCase() { private lateinit var overlayController: ISidefpsController private lateinit var sideFpsController: SidefpsController enum class DeviceConfig { X_ALIGNED, Y_ALIGNED_UNFOLDED, Y_ALIGNED_FOLDED } private lateinit var deviceConfig: DeviceConfig private lateinit var indicatorBounds: Rect private lateinit var displayBounds: Rect private lateinit var sensorLocation: SensorLocationInternal private var displayWidth: Int = 0 private var displayHeight: Int = 0 private var boundsWidth: Int = 0 private var boundsHeight: Int = 0 @Before fun setup() { context.addMockSystemService(DisplayManager::class.java, displayManager) Loading @@ -135,17 +140,43 @@ class SidefpsControllerTest : SysuiTestCase() { this } } `when`(windowManager.maximumWindowMetrics).thenReturn( WindowMetrics(Rect(0, 0, DISPLAY_SIZE_X, DISPLAY_SIZE_Y), WindowInsets.CONSUMED) ) } private fun testWithDisplay( deviceConfig: DeviceConfig = DeviceConfig.X_ALIGNED, initInfo: DisplayInfo.() -> Unit = {}, locations: List<SensorLocationInternal> = listOf(X_LOCATION), windowInsets: WindowInsets = insetsForSmallNavbar(), block: () -> Unit ) { this.deviceConfig = deviceConfig when (deviceConfig) { DeviceConfig.X_ALIGNED -> { displayWidth = 2560 displayHeight = 1600 sensorLocation = SensorLocationInternal("", 2325, 0, 0) boundsWidth = 160 boundsHeight = 84 } DeviceConfig.Y_ALIGNED_UNFOLDED -> { displayWidth = 2208 displayHeight = 1840 sensorLocation = SensorLocationInternal("", 0, 510, 0) boundsWidth = 110 boundsHeight = 210 } DeviceConfig.Y_ALIGNED_FOLDED -> { displayWidth = 1080 displayHeight = 2100 sensorLocation = SensorLocationInternal("", 0, 590, 0) boundsWidth = 110 boundsHeight = 210 } } indicatorBounds = Rect(0, 0, boundsWidth, boundsHeight) displayBounds = Rect(0, 0, displayWidth, displayHeight) var locations = listOf(sensorLocation) `when`(fingerprintManager.sensorPropertiesInternal).thenReturn( listOf( FingerprintSensorPropertiesInternal( Loading @@ -166,8 +197,11 @@ class SidefpsControllerTest : SysuiTestCase() { val display = Display(dmGlobal, DISPLAY_ID, displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS) `when`(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo) `when`(windowManager.defaultDisplay).thenReturn(display) `when`(windowManager.maximumWindowMetrics).thenReturn( WindowMetrics(displayBounds, WindowInsets.CONSUMED) ) `when`(windowManager.currentWindowMetrics).thenReturn( WindowMetrics(Rect(0, 0, DISPLAY_SIZE_X, DISPLAY_SIZE_Y), windowInsets) WindowMetrics(displayBounds, windowInsets) ) sideFpsController = SidefpsController( Loading Loading @@ -260,46 +294,56 @@ class SidefpsControllerTest : SysuiTestCase() { } @Test fun showsWithTaskbar() = testWithDisplay({ rotation = Surface.ROTATION_0 }) { fun showsWithTaskbar() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_0 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbarOnY() = testWithDisplay( { rotation = Surface.ROTATION_0 }, locations = listOf(Y_LOCATION) deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, { rotation = Surface.ROTATION_0 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbar90() = testWithDisplay({ rotation = Surface.ROTATION_90 }) { fun showsWithTaskbar90() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_90 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbar90OnY() = testWithDisplay( { rotation = Surface.ROTATION_90 }, locations = listOf(Y_LOCATION) deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, { rotation = Surface.ROTATION_90 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbar180() = testWithDisplay({ rotation = Surface.ROTATION_180 }) { fun showsWithTaskbar180() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_180 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbar270OnY() = testWithDisplay( { rotation = Surface.ROTATION_270 }, locations = listOf(Y_LOCATION) deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, { rotation = Surface.ROTATION_270 } ) { hidesWithTaskbar(visible = true) } @Test fun showsWithTaskbarCollapsedDown() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_270 }, windowInsets = insetsForSmallNavbar() ) { Loading @@ -308,8 +352,8 @@ class SidefpsControllerTest : SysuiTestCase() { @Test fun showsWithTaskbarCollapsedDownOnY() = testWithDisplay( deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, { rotation = Surface.ROTATION_180 }, locations = listOf(Y_LOCATION), windowInsets = insetsForSmallNavbar() ) { hidesWithTaskbar(visible = true) Loading @@ -317,8 +361,8 @@ class SidefpsControllerTest : SysuiTestCase() { @Test fun hidesWithTaskbarDown() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_180 }, locations = listOf(X_LOCATION), windowInsets = insetsForLargeNavbar() ) { hidesWithTaskbar(visible = false) Loading @@ -326,18 +370,18 @@ class SidefpsControllerTest : SysuiTestCase() { @Test fun hidesWithTaskbarDownOnY() = testWithDisplay( deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED, { rotation = Surface.ROTATION_270 }, locations = listOf(Y_LOCATION), windowInsets = insetsForLargeNavbar() ) { hidesWithTaskbar(visible = false) hidesWithTaskbar(visible = true) } private fun hidesWithTaskbar(visible: Boolean) { overlayController.show(SENSOR_ID, REASON_UNKNOWN) executor.runAllReady() sideFpsController.overviewProxyListener.onTaskbarStatusUpdated(true, false) sideFpsController.overviewProxyListener.onTaskbarStatusUpdated(visible, false) executor.runAllReady() verify(windowManager).addView(any(), any()) Loading @@ -346,25 +390,38 @@ class SidefpsControllerTest : SysuiTestCase() { } @Test fun setsXAlign() = testWithDisplay { fun testIndicatorPlacementForXAlignedSensor() = testWithDisplay( deviceConfig = DeviceConfig.X_ALIGNED ) { overlayController.show(SENSOR_ID, REASON_UNKNOWN) sideFpsController.overlayOffsets = sensorLocation sideFpsController.updateOverlayParams( windowManager.defaultDisplay, indicatorBounds ) executor.runAllReady() verify(windowManager).addView(any(), overlayViewParamsCaptor.capture()) verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture()) assertThat(overlayViewParamsCaptor.value.x).isEqualTo(X_LOCATION.sensorLocationX) assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX) assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0) } @Test fun setYAlign() = testWithDisplay(locations = listOf(Y_LOCATION)) { fun testIndicatorPlacementForYAlignedSensor() = testWithDisplay( deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED ) { sideFpsController.overlayOffsets = sensorLocation sideFpsController.updateOverlayParams( windowManager.defaultDisplay, indicatorBounds ) overlayController.show(SENSOR_ID, REASON_UNKNOWN) executor.runAllReady() verify(windowManager).addView(any(), overlayViewParamsCaptor.capture()) assertThat(overlayViewParamsCaptor.value.x).isEqualTo(DISPLAY_SIZE_X) assertThat(overlayViewParamsCaptor.value.y).isEqualTo(Y_LOCATION.sensorLocationY) verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture()) assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth) assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY) } } Loading @@ -373,6 +430,7 @@ private fun insetsForLargeNavbar() = insetsWithBottom(100) private fun insetsWithBottom(bottom: Int) = WindowInsets.Builder() .setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, bottom)) .build() private fun fpEnrollTask() = settingsTask(".biometrics.fingerprint.FingerprintEnrollEnrolling") private fun fpSettingsTask() = settingsTask(".biometrics.fingerprint.FingerprintSettings") private fun settingsTask(cls: String) = ActivityManager.RunningTaskInfo().apply { Loading