Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b20088f2 authored by Beverly Tai's avatar Beverly Tai Committed by Android (Google) Code Review
Browse files

Merge "Ensure alt bouncer view is removed" into main

parents 2d71ada1 73ca0f6c
Loading
Loading
Loading
Loading
+3 −13
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ import com.android.systemui.biometrics.data.repository.fingerprintPropertyReposi
import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
@@ -223,23 +222,14 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
    }

    private fun givenAlternateBouncerSupported() {
        if (DeviceEntryUdfpsRefactor.isEnabled) {
            kosmos.fingerprintPropertyRepository.supportsUdfps()
        } else {
            kosmos.keyguardBouncerRepository.setAlternateBouncerUIAvailable(true)
        }
        kosmos.givenAlternateBouncerSupported()
    }

    private fun givenCanShowAlternateBouncer() {
        givenAlternateBouncerSupported()
        kosmos.keyguardBouncerRepository.setPrimaryShow(false)
        kosmos.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
        kosmos.biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
        whenever(kosmos.keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false)
        whenever(kosmos.keyguardStateController.isUnlocked).thenReturn(false)
        kosmos.givenCanShowAlternateBouncer()
    }

    private fun givenCannotShowAlternateBouncer() {
        kosmos.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
        kosmos.givenCannotShowAlternateBouncer()
    }
}
+23 −7
Original line number Diff line number Diff line
@@ -115,13 +115,28 @@ constructor(
    }

    private fun removeViewFromWindowManager() {
        if (alternateBouncerView == null || !alternateBouncerView!!.isAttachedToWindow) {
            return
        alternateBouncerView?.let {
            alternateBouncerView = null
            if (it.isAttachedToWindow) {
                it.removeOnAttachStateChangeListener(onAttachAddBackGestureHandler)
                Log.d(TAG, "Removing alternate bouncer view immediately")
                windowManager.get().removeView(it)
            } else {
                // once the view is attached, remove it
                it.addOnAttachStateChangeListener(
                    object : View.OnAttachStateChangeListener {
                        override fun onViewAttachedToWindow(view: View) {
                            it.removeOnAttachStateChangeListener(this)
                            it.removeOnAttachStateChangeListener(onAttachAddBackGestureHandler)
                            Log.d(TAG, "Removing alternate bouncer view on attached")
                            windowManager.get().removeView(it)
                        }

        windowManager.get().removeView(alternateBouncerView)
        alternateBouncerView!!.removeOnAttachStateChangeListener(onAttachAddBackGestureHandler)
        alternateBouncerView = null
                        override fun onViewDetachedFromWindow(view: View) {}
                    }
                )
            }
        }
    }

    private val onAttachAddBackGestureHandler =
@@ -151,7 +166,7 @@ constructor(
        }

    private fun addViewToWindowManager() {
        if (alternateBouncerView?.isAttachedToWindow == true) {
        if (alternateBouncerView != null) {
            return
        }

@@ -159,6 +174,7 @@ constructor(
            layoutInflater.get().inflate(R.layout.alternate_bouncer, null, false)
                as ConstraintLayout

        Log.d(TAG, "Adding alternate bouncer view")
        windowManager.get().addView(alternateBouncerView, layoutParams)
        alternateBouncerView!!.addOnAttachStateChangeListener(onAttachAddBackGestureHandler)
    }
+142 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.keyguard.ui.binder

import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper
import android.view.View
import android.view.layoutInflater
import android.view.mockedLayoutInflater
import android.view.windowManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.domain.interactor.givenCanShowAlternateBouncer
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mockito.any
import org.mockito.Mockito.anyBoolean
import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.kotlin.isNull

@SmallTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
class AlternateBouncerViewBinderTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope

    private val mockedAltBouncerView =
        spy(kosmos.layoutInflater.inflate(R.layout.alternate_bouncer, null, false))

    @Before
    fun setup() {
        whenever(
                kosmos.mockedLayoutInflater.inflate(
                    eq(R.layout.alternate_bouncer),
                    isNull(),
                    anyBoolean()
                )
            )
            .thenReturn(mockedAltBouncerView)
        kosmos.alternateBouncerViewBinder.start()
    }

    @Test
    @EnableFlags(FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
    fun addViewToWindowManager() {
        testScope.runTest {
            kosmos.givenCanShowAlternateBouncer()
            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.ALTERNATE_BOUNCER,
                testScope,
            )
            verify(kosmos.windowManager).addView(any(), any())
        }
    }

    @Test
    @EnableFlags(FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
    fun viewRemovedImmediatelyIfAlreadyAttachedToWindow() {
        testScope.runTest {
            kosmos.givenCanShowAlternateBouncer()
            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.ALTERNATE_BOUNCER,
                testScope,
            )
            verify(kosmos.windowManager).addView(any(), any())
            whenever(mockedAltBouncerView.isAttachedToWindow).thenReturn(true)

            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.ALTERNATE_BOUNCER,
                to = KeyguardState.LOCKSCREEN,
                testScope,
            )
            verify(kosmos.windowManager).removeView(any())
        }
    }

    @Test
    @EnableFlags(FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
    fun viewNotRemovedUntilAttachedToWindow() {
        testScope.runTest {
            kosmos.givenCanShowAlternateBouncer()
            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.ALTERNATE_BOUNCER,
                testScope,
            )
            verify(kosmos.windowManager).addView(any(), any())

            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.ALTERNATE_BOUNCER,
                to = KeyguardState.LOCKSCREEN,
                testScope,
            )

            verify(kosmos.windowManager, never()).removeView(any())
            givenAltBouncerViewAttachedToWindow()
            verify(kosmos.windowManager).removeView(any())
        }
    }

    private fun givenAltBouncerViewAttachedToWindow() {
        val attachStateChangeListenerCaptor =
            ArgumentCaptor.forClass(View.OnAttachStateChangeListener::class.java)
        verify(mockedAltBouncerView, atLeastOnce())
            .addOnAttachStateChangeListener(attachStateChangeListenerCaptor.capture())
        attachStateChangeListenerCaptor.allValues.onEach {
            it.onViewAttachedToWindow(mockedAltBouncerView)
        }
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package android.view

import android.content.applicationContext
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.util.mockito.mock

var Kosmos.layoutInflater: LayoutInflater by
    Kosmos.Fixture { LayoutInflater.from(applicationContext) }
var Kosmos.mockedLayoutInflater: LayoutInflater by Kosmos.Fixture { mock<LayoutInflater>() }
+23 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import com.android.keyguard.keyguardUpdateMonitor
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
import com.android.systemui.deviceentry.domain.interactor.deviceEntryFingerprintAuthInteractor
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
@@ -28,6 +29,7 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.statusbar.statusBarStateController
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.statusbar.policy.keyguardStateController
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.systemClock

val Kosmos.alternateBouncerInteractor: AlternateBouncerInteractor by
@@ -47,3 +49,24 @@ val Kosmos.alternateBouncerInteractor: AlternateBouncerInteractor by
            sceneInteractor = { sceneInteractor },
        )
    }

fun Kosmos.givenCanShowAlternateBouncer() {
    this.givenAlternateBouncerSupported()
    this.keyguardBouncerRepository.setPrimaryShow(false)
    this.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
    this.biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
    whenever(this.keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false)
    whenever(this.keyguardStateController.isUnlocked).thenReturn(false)
}

fun Kosmos.givenAlternateBouncerSupported() {
    if (DeviceEntryUdfpsRefactor.isEnabled) {
        this.fingerprintPropertyRepository.supportsUdfps()
    } else {
        this.keyguardBouncerRepository.setAlternateBouncerUIAvailable(true)
    }
}

fun Kosmos.givenCannotShowAlternateBouncer() {
    this.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
}
Loading