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

Commit 41c0a596 authored by Chandru S's avatar Chandru S
Browse files

Use color for face scanning animation that matches other UI elements on screen

On lockscreen, color of the animation matches the clock color
On shade/bouncer, color matches the color of other UI elements (a11y contrast compliant as well)
On biometric prompt or alternate bouncer with SFPS indicator, color matches the sfps indicator color.

Flag: EXEMPT bugfix
Test: verified manually,
 1. animation on lockscreen
 2. animation on locked shade (pull down to full QS shade)
 3. animation on alt bouncer on lockscreen with SFPS
 4. animation on biometric prompt with SFPS
Fixes: 414540877
Fixes: 374036233
Change-Id: Id6215a0d9b8a5111db070081a52bd09eefb8e5be
parent 7f7e21ef
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -28,9 +28,11 @@ import com.android.systemui.biometrics.AuthController
import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository
import com.android.systemui.decor.FaceScanningProviderFactory
import com.android.systemui.decor.FaceScanningProviderFactoryImpl
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.log.ScreenDecorationsLogger
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.Executor
@@ -46,6 +48,7 @@ import org.mockito.MockitoAnnotations
@RunWith(AndroidJUnit4::class)
@SmallTest
class FaceScanningProviderFactoryTest : SysuiTestCase() {
    private val kosmos = testKosmos()

    private lateinit var underTest: FaceScanningProviderFactory

@@ -91,6 +94,8 @@ class FaceScanningProviderFactoryTest : SysuiTestCase() {
                mock(Executor::class.java),
                ScreenDecorationsLogger(logcatLogBuffer("FaceScanningProviderFactoryTest")),
                facePropertyRepository,
                kosmos.keyguardInteractor,
                kosmos.shadeInteractor,
            )

        facePropertyRepository.setSensorLocation(Point(10, 10))
+35 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.TimeInterpolator
import android.animation.ValueAnimator
import android.annotation.ColorInt
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
@@ -32,9 +33,13 @@ import android.view.View
import androidx.core.graphics.ColorUtils
import com.android.app.animation.Interpolators
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.settingslib.Utils
import com.android.systemui.biometrics.AuthController
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.log.ScreenDecorationsLogger
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.util.asIndenting
import java.io.PrintWriter
import java.util.concurrent.Executor
@@ -48,6 +53,8 @@ class FaceScanningOverlay(
    pos: Int,
    val statusBarStateController: StatusBarStateController,
    val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    val keyguardInteractor: KeyguardInteractor,
    val shadeInteractor: ShadeInteractor,
    val mainExecutor: Executor,
    val logger: ScreenDecorationsLogger,
    val authController: AuthController,
@@ -59,12 +66,31 @@ class FaceScanningOverlay(
    private val rimRect = RectF()
    private var cameraProtectionColor = Color.BLACK

    var faceScanningAnimColor =
        context.getColor(com.android.internal.R.color.materialColorPrimaryFixed)
    @ColorInt private var lockscreenAnimationColor: Int = 0
    @ColorInt private var onScrimColor: Int = 0

    @ColorInt
    private fun getFaceScanningAnimationColor(): Int {
        val behindScrimVisible =
            shadeInteractor.isAnyFullyExpanded.value ||
                keyguardInteractor.primaryBouncerShowing.value
        val sideFpsIndicatorMightBeVisible =
            (keyguardInteractor.alternateBouncerShowing.value || authController.isShowing) &&
                authController.isSfpsSupported
        return if (behindScrimVisible || sideFpsIndicatorMightBeVisible) {
            // Use this color to comply with a11y color contrast or match SFPS indicator's color.
            onScrimColor
        } else {
            // This is used only when face scanning is happening on the lockscreen.
            lockscreenAnimationColor
        }
    }

    private var cameraProtectionAnimator: ValueAnimator? = null
    var hideOverlayRunnable: Runnable? = null

    init {
        updateColors()
        visibility = View.INVISIBLE // only show this view when face scanning is happening
    }

@@ -241,7 +267,7 @@ class FaceScanningOverlay(
        val rimPaintAlpha = rimPaint.alpha
        rimPaint.color =
            ColorUtils.blendARGB(
                faceScanningAnimColor,
                getFaceScanningAnimationColor(),
                Color.WHITE,
                statusBarStateController.dozeAmount,
            )
@@ -399,4 +425,10 @@ class FaceScanningOverlay(
        ipw.println("this=$this")
        ipw.decreaseIndent()
    }

    fun updateColors() {
        lockscreenAnimationColor =
            Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColorAccent)
        onScrimColor = context.getColor(com.android.internal.R.color.materialColorPrimary)
    }
}
+9 −4
Original line number Diff line number Diff line
@@ -67,7 +67,6 @@ import android.widget.FrameLayout;
import androidx.annotation.VisibleForTesting;

import com.android.internal.util.Preconditions;
import com.android.settingslib.Utils;
import com.android.systemui.biometrics.data.repository.FacePropertyRepository;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.decor.CutoutDecorProviderFactory;
@@ -82,11 +81,13 @@ import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
import com.android.systemui.decor.RoundedCornerDecorProviderFactory;
import com.android.systemui.decor.RoundedCornerResDelegateImpl;
import com.android.systemui.decor.ScreenDecorCommand;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.log.ScreenDecorationsLogger;
import com.android.systemui.qs.UserSettingObserver;
import com.android.systemui.res.R;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.statusbar.commandline.CommandRegistry;
import com.android.systemui.statusbar.events.PrivacyDotViewController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -148,6 +149,8 @@ public class ScreenDecorations implements
    private final DecorProviderFactory mDotFactory;
    private final FaceScanningProviderFactory mFaceScanningFactory;
    private final CameraProtectionLoader mCameraProtectionLoader;
    private final ShadeInteractor mShadeInteractor;
    private final KeyguardInteractor mKeyguardInteractor;
    public final int mFaceScanningViewId;

    @VisibleForTesting
@@ -337,6 +340,8 @@ public class ScreenDecorations implements
            JavaAdapter javaAdapter,
            CameraProtectionLoader cameraProtectionLoader,
            WindowManager windowManager,
            ShadeInteractor shadeInteractor,
            KeyguardInteractor keyguardInteractor,
            @ScreenDecorationsThread Handler handler,
            @ScreenDecorationsThread DelayableExecutor executor) {
        mContext = context;
@@ -348,6 +353,8 @@ public class ScreenDecorations implements
        mDotFactory = dotFactory;
        mFaceScanningFactory = faceScanningFactory;
        mCameraProtectionLoader = cameraProtectionLoader;
        mShadeInteractor = shadeInteractor;
        mKeyguardInteractor = keyguardInteractor;
        mFaceScanningViewId = com.android.systemui.res.R.id.face_scanning_anim;
        mLogger = logger;
        mFacePropertyRepository = facePropertyRepository;
@@ -1241,9 +1248,7 @@ public class ScreenDecorations implements
        FaceScanningOverlay faceScanningOverlay =
                (FaceScanningOverlay) getOverlayView(mFaceScanningViewId);
        if (faceScanningOverlay != null) {
            faceScanningOverlay.setFaceScanningAnimColor(
                    Utils.getColorAttrDefaultColor(faceScanningOverlay.getContext(),
                            com.android.systemui.res.R.attr.wallpaperTextColorAccent));
            faceScanningOverlay.updateColors();
        }
    }

+10 −0
Original line number Diff line number Diff line
@@ -34,8 +34,10 @@ import com.android.systemui.FaceScanningOverlay
import com.android.systemui.biometrics.AuthController
import com.android.systemui.biometrics.data.repository.FacePropertyRepository
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.log.ScreenDecorationsLogger
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -58,6 +60,8 @@ constructor(
    @Main private val mainExecutor: Executor,
    private val logger: ScreenDecorationsLogger,
    private val facePropertyRepository: FacePropertyRepository,
    private val keyguardInteractor: KeyguardInteractor,
    private val shadeInteractor: ShadeInteractor,
) : FaceScanningProviderFactory {
    private val display = context.display
    private val displayInfo = DisplayInfo()
@@ -99,6 +103,8 @@ constructor(
                                mainExecutor,
                                logger,
                                facePropertyRepository,
                                keyguardInteractor,
                                shadeInteractor,
                            )
                        )
                    }
@@ -130,6 +136,8 @@ class FaceScanningOverlayProviderImpl(
    private val mainExecutor: Executor,
    private val logger: ScreenDecorationsLogger,
    private val facePropertyRepository: FacePropertyRepository,
    private val keyguardInteractor: KeyguardInteractor,
    private val shadeInteractor: ShadeInteractor,
) : BoundDecorProvider() {
    override val viewId: Int = com.android.systemui.res.R.id.face_scanning_anim

@@ -162,6 +170,8 @@ class FaceScanningOverlayProviderImpl(
                alignedBound,
                statusBarStateController,
                keyguardUpdateMonitor,
                keyguardInteractor,
                shadeInteractor,
                mainExecutor,
                logger,
                authController,
+1 −1
Original line number Diff line number Diff line
@@ -270,7 +270,7 @@ constructor(
    @JvmField val primaryBouncerShowing: StateFlow<Boolean> = bouncerRepository.primaryBouncerShow

    /** Whether the alternate bouncer is showing or not. */
    val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
    val alternateBouncerShowing: StateFlow<Boolean> = bouncerRepository.alternateBouncerVisible

    /** Observable for the [StatusBarState] */
    val statusBarState: StateFlow<StatusBarState> = repository.statusBarState
Loading