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

Commit 7a0ccd8b authored by Chandru S's avatar Chandru S Committed by Android (Google) Code Review
Browse files

Merge "UI fixes for the progress bar and handle display density changes" into main

parents b323a663 9e3ed4f7
Loading
Loading
Loading
Loading
+7 −7
Original line number Original line Diff line number Diff line
@@ -15,18 +15,18 @@
  ~
  ~
  -->
  -->


<LinearLayout android:layout_height="match_parent"
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    android:layoutDirection="ltr"
    android:gravity="left|top"
    android:gravity="center"
    android:background="@android:color/transparent"
    xmlns:android="http://schemas.android.com/apk/res/android">
    xmlns:android="http://schemas.android.com/apk/res/android">
    <ProgressBar
    <ProgressBar
        android:id="@+id/side_fps_progress_bar"
        android:id="@+id/side_fps_progress_bar"
        android:layout_width="55dp"
        android:layout_width="0dp"
        android:layout_height="10dp"
        android:layout_height="@dimen/sfps_progress_bar_thickness"
        android:indeterminateOnly="false"
        android:indeterminateOnly="false"
        android:min="0"
        android:min="0"
        android:max="100"
        android:max="100"
        android:progressDrawable="@drawable/progress_bar" />
        android:progressDrawable="@drawable/progress_bar" />
</LinearLayout>
</RelativeLayout>
+7 −0
Original line number Original line Diff line number Diff line
@@ -157,4 +157,11 @@
    <dimen name="weather_clock_smartspace_translateX">0dp</dimen>
    <dimen name="weather_clock_smartspace_translateX">0dp</dimen>
    <dimen name="weather_clock_smartspace_translateY">0dp</dimen>
    <dimen name="weather_clock_smartspace_translateY">0dp</dimen>


    <!-- Additional length to add to the SFPS sensor length we get from framework so that the length
     of the progress bar matches the length of the power button  -->
    <dimen name="sfps_progress_bar_length_extra_padding">12dp</dimen>
    <!-- Thickness of the progress bar we show for the SFPS based authentication. -->
    <dimen name="sfps_progress_bar_thickness">6dp</dimen>
    <!-- Padding from the edge of the screen for the progress bar -->
    <dimen name="sfps_progress_bar_padding_from_edge">7dp</dimen>
</resources>
</resources>
+78 −64
Original line number Original line Diff line number Diff line
@@ -34,9 +34,11 @@ import java.util.Optional
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach


@SysUISingleton
@SysUISingleton
class SideFpsSensorInteractor
class SideFpsSensorInteractor
@@ -51,7 +53,7 @@ constructor(
    private val logger: SideFpsLogger,
    private val logger: SideFpsLogger,
) {
) {


    private val sensorForCurrentDisplay =
    private val sensorLocationForCurrentDisplay =
        combine(
        combine(
                displayStateInteractor.displayChanges,
                displayStateInteractor.displayChanges,
                fingerprintPropertyRepository.sensorLocations,
                fingerprintPropertyRepository.sensorLocations,
@@ -77,23 +79,23 @@ constructor(
                isAvailable,
                isAvailable,
                fingerprintInteractiveToAuthProvider.get().enabledForCurrentUser
                fingerprintInteractiveToAuthProvider.get().enabledForCurrentUser
            ) { sfpsAvailable, isSettingEnabled ->
            ) { sfpsAvailable, isSettingEnabled ->
                logger.logStateChange(sfpsAvailable, isSettingEnabled)
                sfpsAvailable && isSettingEnabled
                sfpsAvailable && isSettingEnabled
            }
            }
        }
        }


    val sensorLocation: Flow<SideFpsSensorLocation> =
    val sensorLocation: Flow<SideFpsSensorLocation> =
        combine(displayStateInteractor.currentRotation, sensorForCurrentDisplay, ::Pair).map {
        combine(displayStateInteractor.currentRotation, sensorLocationForCurrentDisplay, ::Pair)
            (rotation, sensorLocation: SensorLocationInternal) ->
            .map { (rotation, sensorLocation: SensorLocationInternal) ->
                val isSensorVerticalInDefaultOrientation = sensorLocation.sensorLocationY != 0
                val isSensorVerticalInDefaultOrientation = sensorLocation.sensorLocationY != 0
                // device dimensions in the current rotation
                // device dimensions in the current rotation
            val size = windowManager.maximumWindowMetrics.bounds
                val windowMetrics = windowManager.maximumWindowMetrics
                val size = windowMetrics.bounds
                val isDefaultOrientation = rotation.isDefaultOrientation()
                val isDefaultOrientation = rotation.isDefaultOrientation()
                // Width and height are flipped is device is not in rotation_0 or rotation_180
                // Width and height are flipped is device is not in rotation_0 or rotation_180
                // Flipping it to the width and height of the device in default orientation.
                // Flipping it to the width and height of the device in default orientation.
                val displayWidth = if (isDefaultOrientation) size.width() else size.height()
                val displayWidth = if (isDefaultOrientation) size.width() else size.height()
                val displayHeight = if (isDefaultOrientation) size.height() else size.width()
                val displayHeight = if (isDefaultOrientation) size.height() else size.width()
            val sensorWidth = context.resources?.getInteger(R.integer.config_sfpsSensorWidth) ?: 0
                val sensorLengthInPx = sensorLocation.sensorRadius * 2


                val (sensorLeft, sensorTop) =
                val (sensorLeft, sensorTop) =
                    if (isSensorVerticalInDefaultOrientation) {
                    if (isSensorVerticalInDefaultOrientation) {
@@ -105,11 +107,18 @@ constructor(
                                Pair(sensorLocation.sensorLocationY, 0)
                                Pair(sensorLocation.sensorLocationY, 0)
                            }
                            }
                            DisplayRotation.ROTATION_180 -> {
                            DisplayRotation.ROTATION_180 -> {
                            Pair(0, displayHeight - sensorLocation.sensorLocationY - sensorWidth)
                                Pair(
                                    0,
                                    displayHeight -
                                        sensorLocation.sensorLocationY -
                                        sensorLengthInPx
                                )
                            }
                            }
                            DisplayRotation.ROTATION_270 -> {
                            DisplayRotation.ROTATION_270 -> {
                                Pair(
                                Pair(
                                displayHeight - sensorLocation.sensorLocationY - sensorWidth,
                                    displayHeight -
                                        sensorLocation.sensorLocationY -
                                        sensorLengthInPx,
                                    displayWidth
                                    displayWidth
                                )
                                )
                            }
                            }
@@ -120,11 +129,16 @@ constructor(
                                Pair(sensorLocation.sensorLocationX, 0)
                                Pair(sensorLocation.sensorLocationX, 0)
                            }
                            }
                            DisplayRotation.ROTATION_90 -> {
                            DisplayRotation.ROTATION_90 -> {
                            Pair(0, displayWidth - sensorLocation.sensorLocationX - sensorWidth)
                                Pair(
                                    0,
                                    displayWidth - sensorLocation.sensorLocationX - sensorLengthInPx
                                )
                            }
                            }
                            DisplayRotation.ROTATION_180 -> {
                            DisplayRotation.ROTATION_180 -> {
                                Pair(
                                Pair(
                                displayWidth - sensorLocation.sensorLocationX - sensorWidth,
                                    displayWidth -
                                        sensorLocation.sensorLocationX -
                                        sensorLengthInPx,
                                    displayHeight
                                    displayHeight
                                )
                                )
                            }
                            }
@@ -134,20 +148,20 @@ constructor(
                        }
                        }
                    }
                    }


            logger.sensorLocationStateChanged(
                size,
                rotation,
                displayWidth,
                displayHeight,
                sensorWidth,
                isSensorVerticalInDefaultOrientation
            )

                SideFpsSensorLocation(
                SideFpsSensorLocation(
                    left = sensorLeft,
                    left = sensorLeft,
                    top = sensorTop,
                    top = sensorTop,
                width = sensorWidth,
                    length = sensorLengthInPx,
                    isSensorVerticalInDefaultOrientation = isSensorVerticalInDefaultOrientation
                    isSensorVerticalInDefaultOrientation = isSensorVerticalInDefaultOrientation
                )
                )
            }
            }
            .distinctUntilChanged()
            .onEach {
                logger.sensorLocationStateChanged(
                    it.left,
                    it.top,
                    it.length,
                    it.isSensorVerticalInDefaultOrientation
                )
            }
}
}
+2 −2
Original line number Original line Diff line number Diff line
@@ -21,8 +21,8 @@ data class SideFpsSensorLocation(
    val left: Int,
    val left: Int,
    /** Pixel offset from the top of the screen */
    /** Pixel offset from the top of the screen */
    val top: Int,
    val top: Int,
    /** Width in pixels of the SFPS sensor */
    /** Length of the SFPS sensor in pixels in current display density */
    val width: Int,
    val length: Int,
    /**
    /**
     * Whether the sensor is vertical when the device is in its default orientation (Rotation_0 or
     * Whether the sensor is vertical when the device is in its default orientation (Rotation_0 or
     * Rotation_180)
     * Rotation_180)
+96 −14
Original line number Original line Diff line number Diff line
@@ -16,19 +16,27 @@


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


import android.animation.ValueAnimator
import android.graphics.Point
import com.android.systemui.CoreStartable
import com.android.systemui.CoreStartable
import com.android.systemui.biometrics.SideFpsController
import com.android.systemui.biometrics.SideFpsController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.ui.view.SideFpsProgressBar
import com.android.systemui.keyguard.ui.view.SideFpsProgressBar
import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
import com.android.systemui.log.SideFpsLogger
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.util.kotlin.Quint
import com.android.systemui.util.kotlin.Quint
import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import kotlinx.coroutines.launch


private const val spfsProgressBarCommand = "sfps-progress-bar"

@SysUISingleton
@SysUISingleton
class SideFpsProgressBarViewBinder
class SideFpsProgressBarViewBinder
@Inject
@Inject
@@ -37,38 +45,112 @@ constructor(
    private val view: SideFpsProgressBar,
    private val view: SideFpsProgressBar,
    @Application private val applicationScope: CoroutineScope,
    @Application private val applicationScope: CoroutineScope,
    private val sfpsController: dagger.Lazy<SideFpsController>,
    private val sfpsController: dagger.Lazy<SideFpsController>,
    private val logger: SideFpsLogger,
    private val commandRegistry: CommandRegistry,
) : CoreStartable {
) : CoreStartable {


    override fun start() {
    override fun start() {
        commandRegistry.registerCommand(spfsProgressBarCommand) { SfpsProgressBarCommand() }
        applicationScope.launch {
        applicationScope.launch {
            viewModel.isProlongedTouchRequiredForAuthentication.collectLatest { enabled ->
            viewModel.isProlongedTouchRequiredForAuthentication.collectLatest { enabled ->
                logger.isProlongedTouchRequiredForAuthenticationChanged(enabled)
                if (enabled) {
                if (enabled) {
                    launch {
                    launch {
                        combine(
                        combine(
                                viewModel.isVisible,
                                viewModel.isVisible,
                                viewModel.sensorLocation,
                                viewModel.progressBarLocation,
                                viewModel.shouldRotate90Degrees,
                                viewModel.rotation,
                                viewModel.isFingerprintAuthRunning,
                                viewModel.isFingerprintAuthRunning,
                                viewModel.sensorWidth,
                                viewModel.progressBarLength,
                                ::Quint
                                ::Quint
                            )
                            )
                            .collectLatest {
                            .collectLatest { (visible, location, rotation, fpDetectRunning, length)
                                (visible, location, shouldRotate, fpDetectRunning, sensorWidth) ->
                                ->
                                view.updateView(visible, location, shouldRotate, sensorWidth)
                                updateView(
                                    visible,
                                    location,
                                    fpDetectRunning,
                                    length,
                                    viewModel.progressBarThickness,
                                    rotation,
                                )
                            }
                    }
                    launch { viewModel.progress.collectLatest { view.setProgress(it) } }
                } else {
                    view.hide()
                }
            }
        }
    }

    private fun updateView(
        visible: Boolean,
        location: Point,
        fpDetectRunning: Boolean,
        length: Int,
        thickness: Int,
        rotation: Float,
    ) {
        logger.sfpsProgressBarStateChanged(visible, location, fpDetectRunning, length, rotation)
        view.updateView(visible, location, length, thickness, rotation)
        // We have to hide the SFPS indicator as the progress bar will
        // We have to hide the SFPS indicator as the progress bar will
        // be shown at the same location
        // be shown at the same location
        if (visible) {
        if (visible) {
            logger.hidingSfpsIndicator()
            sfpsController.get().hideIndicator()
            sfpsController.get().hideIndicator()
        } else if (fpDetectRunning) {
        } else if (fpDetectRunning) {
            logger.showingSfpsIndicator()
            sfpsController.get().showIndicator()
            sfpsController.get().showIndicator()
        }
        }
    }
    }
                    }

                    launch { viewModel.progress.collectLatest { view.setProgress(it) } }
    inner class SfpsProgressBarCommand : Command {
        private var animator: ValueAnimator? = null
        override fun execute(pw: PrintWriter, args: List<String>) {
            if (args.isEmpty() || args[0] == "show" && args.size != 6) {
                pw.println("invalid command")
                help(pw)
            } else {
            } else {
                    view.hideOverlay()
                when (args[0]) {
                    "show" -> {
                        animator?.cancel()
                        updateView(
                            visible = true,
                            location = Point(Integer.parseInt(args[1]), Integer.parseInt(args[2])),
                            fpDetectRunning = true,
                            length = Integer.parseInt(args[3]),
                            thickness = Integer.parseInt(args[4]),
                            rotation = Integer.parseInt(args[5]).toFloat(),
                        )
                        animator =
                            ValueAnimator.ofFloat(0.0f, 1.0f).apply {
                                repeatMode = ValueAnimator.REVERSE
                                repeatCount = ValueAnimator.INFINITE
                                addUpdateListener { view.setProgress(it.animatedValue as Float) }
                            }
                        animator?.start()
                    }
                    "hide" -> {
                        animator?.cancel()
                        updateView(
                            visible = false,
                            location = Point(0, 0),
                            fpDetectRunning = false,
                            length = 0,
                            thickness = 0,
                            rotation = 0.0f,
                        )
                    }
                }
                }
            }
            }
        }
        }

        override fun help(pw: PrintWriter) {
            pw.println("Usage: adb shell cmd statusbar $spfsProgressBarCommand <command>")
            pw.println("Available commands:")
            pw.println("  show x y width height rotation")
            pw.println("  hide")
        }
    }
    }
}
}
Loading