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

Commit 391f8136 authored by Matt Pietal's avatar Matt Pietal Committed by Android (Google) Code Review
Browse files

Merge "Add tracing to quick affordance binder" into main

parents cc398839 40989679
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard.ui.composable

import com.android.systemui.keyguard.ui.composable.blueprint.CommunalBlueprintModule
import com.android.systemui.keyguard.ui.composable.blueprint.ShortcutsBesideUdfpsBlueprintModule
import com.android.systemui.keyguard.ui.composable.section.OptionalSectionModule
import dagger.Module

@@ -26,7 +25,6 @@ import dagger.Module
        [
            CommunalBlueprintModule::class,
            OptionalSectionModule::class,
            ShortcutsBesideUdfpsBlueprintModule::class,
        ],
)
interface LockscreenSceneBlueprintModule
+0 −259
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.composable.blueprint

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.unit.IntRect
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.SceneScope
import com.android.compose.modifiers.padding
import com.android.systemui.keyguard.ui.composable.LockscreenLongPress
import com.android.systemui.keyguard.ui.composable.section.AmbientIndicationSection
import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection
import com.android.systemui.keyguard.ui.composable.section.LockSection
import com.android.systemui.keyguard.ui.composable.section.NotificationSection
import com.android.systemui.keyguard.ui.composable.section.SettingsMenuSection
import com.android.systemui.keyguard.ui.composable.section.StatusBarSection
import com.android.systemui.keyguard.ui.composable.section.TopAreaSection
import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel
import dagger.Binds
import dagger.Module
import dagger.multibindings.IntoSet
import java.util.Optional
import javax.inject.Inject
import kotlin.math.roundToInt

/**
 * Renders the lockscreen scene when showing with the default layout (e.g. vertical phone form
 * factor).
 */
class ShortcutsBesideUdfpsBlueprint
@Inject
constructor(
    private val statusBarSection: StatusBarSection,
    private val lockSection: LockSection,
    private val ambientIndicationSectionOptional: Optional<AmbientIndicationSection>,
    private val bottomAreaSection: BottomAreaSection,
    private val settingsMenuSection: SettingsMenuSection,
    private val topAreaSection: TopAreaSection,
    private val notificationSection: NotificationSection,
) : ComposableLockscreenSceneBlueprint {

    override val id: String = "shortcuts-besides-udfps"

    @Composable
    override fun SceneScope.Content(
        viewModel: LockscreenContentViewModel,
        modifier: Modifier,
    ) {
        val isUdfpsVisible = viewModel.isUdfpsVisible
        val isShadeLayoutWide by viewModel.isShadeLayoutWide.collectAsStateWithLifecycle()
        val unfoldTranslations by viewModel.unfoldTranslations.collectAsStateWithLifecycle()
        val areNotificationsVisible by
            viewModel
                .areNotificationsVisible(contentKey)
                .collectAsStateWithLifecycle(initialValue = false)

        LockscreenLongPress(
            viewModel = viewModel.touchHandling,
            modifier = modifier,
        ) { onSettingsMenuPlaced ->
            Layout(
                content = {
                    // Constrained to above the lock icon.
                    Column(
                        modifier = Modifier.fillMaxSize(),
                    ) {
                        with(statusBarSection) {
                            StatusBar(
                                modifier =
                                    Modifier.fillMaxWidth()
                                        .padding(
                                            horizontal = { unfoldTranslations.start.roundToInt() },
                                        )
                            )
                        }

                        Box {
                            with(topAreaSection) {
                                DefaultClockLayout(
                                    smartSpacePaddingTop = viewModel::getSmartSpacePaddingTop,
                                    modifier =
                                        Modifier.graphicsLayer {
                                            translationX = unfoldTranslations.start
                                        },
                                )
                            }
                            if (isShadeLayoutWide) {
                                with(notificationSection) {
                                    Notifications(
                                        areNotificationsVisible = areNotificationsVisible,
                                        isShadeLayoutWide = isShadeLayoutWide,
                                        burnInParams = null,
                                        modifier =
                                            Modifier.fillMaxWidth(0.5f)
                                                .fillMaxHeight()
                                                .align(alignment = Alignment.TopEnd)
                                    )
                                }
                            }
                        }
                        if (!isShadeLayoutWide) {
                            with(notificationSection) {
                                Notifications(
                                    areNotificationsVisible = areNotificationsVisible,
                                    isShadeLayoutWide = isShadeLayoutWide,
                                    burnInParams = null,
                                    modifier = Modifier.weight(weight = 1f)
                                )
                            }
                        }
                        if (!isUdfpsVisible && ambientIndicationSectionOptional.isPresent) {
                            with(ambientIndicationSectionOptional.get()) {
                                AmbientIndication(modifier = Modifier.fillMaxWidth())
                            }
                        }
                    }

                    // Constrained to the left of the lock icon (in left-to-right layouts).
                    with(bottomAreaSection) {
                        Shortcut(
                            isStart = true,
                            applyPadding = false,
                            modifier =
                                Modifier.graphicsLayer { translationX = unfoldTranslations.start },
                        )
                    }

                    with(lockSection) { LockIcon() }

                    // Constrained to the right of the lock icon (in left-to-right layouts).
                    with(bottomAreaSection) {
                        Shortcut(
                            isStart = false,
                            applyPadding = false,
                            modifier =
                                Modifier.graphicsLayer { translationX = unfoldTranslations.end },
                        )
                    }

                    // Aligned to bottom and constrained to below the lock icon.
                    Column(modifier = Modifier.fillMaxWidth()) {
                        if (isUdfpsVisible && ambientIndicationSectionOptional.isPresent) {
                            with(ambientIndicationSectionOptional.get()) {
                                AmbientIndication(modifier = Modifier.fillMaxWidth())
                            }
                        }

                        with(bottomAreaSection) {
                            IndicationArea(modifier = Modifier.fillMaxWidth())
                        }
                    }

                    // Aligned to bottom and NOT constrained by the lock icon.
                    with(settingsMenuSection) { SettingsMenu(onSettingsMenuPlaced) }
                },
                modifier = Modifier.fillMaxSize(),
            ) { measurables, constraints ->
                check(measurables.size == 6)
                val aboveLockIconMeasurable = measurables[0]
                val startSideShortcutMeasurable = measurables[1]
                val lockIconMeasurable = measurables[2]
                val endSideShortcutMeasurable = measurables[3]
                val belowLockIconMeasurable = measurables[4]
                val settingsMenuMeasurable = measurables[5]

                val noMinConstraints =
                    constraints.copy(
                        minWidth = 0,
                        minHeight = 0,
                    )

                val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints)
                val lockIconBounds =
                    IntRect(
                        left = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Left],
                        top = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Top],
                        right = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Right],
                        bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom],
                    )

                val aboveLockIconPlaceable =
                    aboveLockIconMeasurable.measure(
                        noMinConstraints.copy(maxHeight = lockIconBounds.top)
                    )
                val startSideShortcutPlaceable =
                    startSideShortcutMeasurable.measure(noMinConstraints)
                val endSideShortcutPlaceable = endSideShortcutMeasurable.measure(noMinConstraints)
                val belowLockIconPlaceable =
                    belowLockIconMeasurable.measure(
                        noMinConstraints.copy(
                            maxHeight = constraints.maxHeight - lockIconBounds.bottom
                        )
                    )
                val settingsMenuPlaceable = settingsMenuMeasurable.measure(noMinConstraints)

                layout(constraints.maxWidth, constraints.maxHeight) {
                    aboveLockIconPlaceable.place(
                        x = 0,
                        y = 0,
                    )
                    startSideShortcutPlaceable.placeRelative(
                        x = lockIconBounds.left / 2 - startSideShortcutPlaceable.width / 2,
                        y = lockIconBounds.center.y - startSideShortcutPlaceable.height / 2,
                    )
                    lockIconPlaceable.place(
                        x = lockIconBounds.left,
                        y = lockIconBounds.top,
                    )
                    endSideShortcutPlaceable.placeRelative(
                        x =
                            lockIconBounds.right +
                                (constraints.maxWidth - lockIconBounds.right) / 2 -
                                endSideShortcutPlaceable.width / 2,
                        y = lockIconBounds.center.y - endSideShortcutPlaceable.height / 2,
                    )
                    belowLockIconPlaceable.place(
                        x = 0,
                        y = constraints.maxHeight - belowLockIconPlaceable.height,
                    )
                    settingsMenuPlaceable.place(
                        x = (constraints.maxWidth - settingsMenuPlaceable.width) / 2,
                        y = constraints.maxHeight - settingsMenuPlaceable.height,
                    )
                }
            }
        }
    }
}

@Module
interface ShortcutsBesideUdfpsBlueprintModule {
    @Binds
    @IntoSet
    fun blueprint(blueprint: ShortcutsBesideUdfpsBlueprint): ComposableLockscreenSceneBlueprint
}
+4 −14
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.res.ResourcesCompat
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.SceneScope
import com.android.keyguard.logging.KeyguardQuickAffordancesLogger
import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder
import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
@@ -40,10 +39,8 @@ import com.android.systemui.keyguard.ui.view.KeyguardIndicationArea
import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModel
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
import com.android.systemui.statusbar.KeyguardIndicationController
import com.android.systemui.statusbar.VibratorHelper
import javax.inject.Inject
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.flow.Flow
@@ -52,11 +49,9 @@ class BottomAreaSection
@Inject
constructor(
    private val viewModel: KeyguardQuickAffordancesCombinedViewModel,
    private val falsingManager: FalsingManager,
    private val vibratorHelper: VibratorHelper,
    private val indicationController: KeyguardIndicationController,
    private val indicationAreaViewModel: KeyguardIndicationAreaViewModel,
    private val shortcutsLogger: KeyguardQuickAffordancesLogger,
    private val keyguardQuickAffordanceViewBinder: KeyguardQuickAffordanceViewBinder,
) {
    /**
     * Renders a single lockscreen shortcut.
@@ -80,9 +75,8 @@ constructor(
                    viewId = if (isStart) R.id.start_button else R.id.end_button,
                    viewModel = if (isStart) viewModel.startButton else viewModel.endButton,
                    transitionAlpha = viewModel.transitionAlpha,
                    falsingManager = falsingManager,
                    vibratorHelper = vibratorHelper,
                    indicationController = indicationController,
                    binder = keyguardQuickAffordanceViewBinder,
                    modifier =
                        if (applyPadding) {
                            Modifier.shortcutPadding()
@@ -124,9 +118,8 @@ constructor(
        @IdRes viewId: Int,
        viewModel: Flow<KeyguardQuickAffordanceViewModel>,
        transitionAlpha: Flow<Float>,
        falsingManager: FalsingManager,
        vibratorHelper: VibratorHelper,
        indicationController: KeyguardIndicationController,
        binder: KeyguardQuickAffordanceViewBinder,
        modifier: Modifier = Modifier,
    ) {
        val (binding, setBinding) = mutableStateOf<KeyguardQuickAffordanceViewBinder.Binding?>(null)
@@ -158,13 +151,10 @@ constructor(
                    }

                setBinding(
                    KeyguardQuickAffordanceViewBinder.bind(
                    binder.bind(
                        view,
                        viewModel,
                        transitionAlpha,
                        falsingManager,
                        vibratorHelper,
                        shortcutsLogger,
                    ) {
                        indicationController.showTransientIndication(it)
                    }
+22 −17
Original line number Diff line number Diff line
@@ -30,18 +30,23 @@ import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.app.tracing.coroutines.launch
import com.android.keyguard.logging.KeyguardQuickAffordancesLogger
import com.android.settingslib.Utils
import com.android.systemui.animation.Expandable
import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.ui.binder.IconViewBinder
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.util.doOnEnd
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
@@ -49,11 +54,20 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

/** This is only for a SINGLE Quick affordance */
object KeyguardQuickAffordanceViewBinder {
@SysUISingleton
class KeyguardQuickAffordanceViewBinder
@Inject
constructor(
    private val falsingManager: FalsingManager?,
    private val vibratorHelper: VibratorHelper?,
    private val logger: KeyguardQuickAffordancesLogger,
    @Main private val mainImmediateDispatcher: CoroutineDispatcher,
) {

    private const val EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS = 250L
    private const val SCALE_SELECTED_BUTTON = 1.23f
    private const val DIM_ALPHA = 0.3f
    private val EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS = 250L
    private val SCALE_SELECTED_BUTTON = 1.23f
    private val DIM_ALPHA = 0.3f
    private val TAG = "KeyguardQuickAffordanceViewBinder"

    /**
     * Defines interface for an object that acts as the binding between the view and its view-model.
@@ -73,30 +87,24 @@ object KeyguardQuickAffordanceViewBinder {
        view: LaunchableImageView,
        viewModel: Flow<KeyguardQuickAffordanceViewModel>,
        alpha: Flow<Float>,
        falsingManager: FalsingManager?,
        vibratorHelper: VibratorHelper?,
        logger: KeyguardQuickAffordancesLogger,
        messageDisplayer: (Int) -> Unit,
    ): Binding {
        val button = view as ImageView
        val configurationBasedDimensions = MutableStateFlow(loadFromResources(view))
        val disposableHandle =
            view.repeatWhenAttached {
            view.repeatWhenAttached(mainImmediateDispatcher) {
                repeatOnLifecycle(Lifecycle.State.STARTED) {
                    launch {
                    launch("$TAG#viewModel") {
                        viewModel.collect { buttonModel ->
                            updateButton(
                                view = button,
                                viewModel = buttonModel,
                                falsingManager = falsingManager,
                                messageDisplayer = messageDisplayer,
                                vibratorHelper = vibratorHelper,
                                logger = logger,
                            )
                        }
                    }

                    launch {
                    launch("$TAG#updateButtonAlpha") {
                        updateButtonAlpha(
                            view = button,
                            viewModel = viewModel,
@@ -104,7 +112,7 @@ object KeyguardQuickAffordanceViewBinder {
                        )
                    }

                    launch {
                    launch("$TAG#configurationBasedDimensions") {
                        configurationBasedDimensions.collect { dimensions ->
                            button.updateLayoutParams<ViewGroup.LayoutParams> {
                                width = dimensions.buttonSizePx.width
@@ -131,10 +139,7 @@ object KeyguardQuickAffordanceViewBinder {
    private fun updateButton(
        view: ImageView,
        viewModel: KeyguardQuickAffordanceViewModel,
        falsingManager: FalsingManager?,
        messageDisplayer: (Int) -> Unit,
        vibratorHelper: VibratorHelper?,
        logger: KeyguardQuickAffordancesLogger,
    ) {
        if (!viewModel.isVisible) {
            view.isInvisible = true
+3 −14
Original line number Diff line number Diff line
@@ -50,7 +50,6 @@ import androidx.core.view.isInvisible
import com.android.internal.policy.SystemBarUtils
import com.android.keyguard.ClockEventController
import com.android.keyguard.KeyguardClockSwitch
import com.android.keyguard.logging.KeyguardQuickAffordancesLogger
import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
import com.android.systemui.broadcast.BroadcastDispatcher
@@ -79,7 +78,6 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel
import com.android.systemui.monet.ColorScheme
import com.android.systemui.monet.Style
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
@@ -89,7 +87,6 @@ import com.android.systemui.shared.clocks.shared.model.ClockPreviewConstants
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants
import com.android.systemui.statusbar.KeyguardIndicationController
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView
import com.android.systemui.statusbar.phone.ScreenOffAnimationController
@@ -133,8 +130,6 @@ constructor(
    private val broadcastDispatcher: BroadcastDispatcher,
    private val lockscreenSmartspaceController: LockscreenSmartspaceController,
    private val udfpsOverlayInteractor: UdfpsOverlayInteractor,
    private val falsingManager: FalsingManager,
    private val vibratorHelper: VibratorHelper,
    private val indicationController: KeyguardIndicationController,
    private val keyguardRootViewModel: KeyguardRootViewModel,
    private val keyguardBlueprintViewModel: KeyguardBlueprintViewModel,
@@ -148,7 +143,7 @@ constructor(
    private val defaultShortcutsSection: DefaultShortcutsSection,
    private val keyguardClockInteractor: KeyguardClockInteractor,
    private val keyguardClockViewModel: KeyguardClockViewModel,
    private val quickAffordancesLogger: KeyguardQuickAffordancesLogger,
    private val keyguardQuickAffordanceViewBinder: KeyguardQuickAffordanceViewBinder,
) {
    val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN)
    private val width: Int = bundle.getInt(KEY_VIEW_WIDTH)
@@ -458,13 +453,10 @@ constructor(

        keyguardRootView.findViewById<LaunchableImageView?>(R.id.start_button)?.let { imageView ->
            shortcutsBindings.add(
                KeyguardQuickAffordanceViewBinder.bind(
                keyguardQuickAffordanceViewBinder.bind(
                    view = imageView,
                    viewModel = quickAffordancesCombinedViewModel.startButton,
                    alpha = flowOf(1f),
                    falsingManager = falsingManager,
                    vibratorHelper = vibratorHelper,
                    logger = quickAffordancesLogger,
                ) { message ->
                    indicationController.showTransientIndication(message)
                }
@@ -473,13 +465,10 @@ constructor(

        keyguardRootView.findViewById<LaunchableImageView?>(R.id.end_button)?.let { imageView ->
            shortcutsBindings.add(
                KeyguardQuickAffordanceViewBinder.bind(
                keyguardQuickAffordanceViewBinder.bind(
                    view = imageView,
                    viewModel = quickAffordancesCombinedViewModel.endButton,
                    alpha = flowOf(1f),
                    falsingManager = falsingManager,
                    vibratorHelper = vibratorHelper,
                    logger = quickAffordancesLogger,
                ) { message ->
                    indicationController.showTransientIndication(message)
                }
Loading