• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.keyguard.ui.composable
18 
19 import android.view.View
20 import androidx.compose.foundation.layout.Box
21 import androidx.compose.runtime.Composable
22 import androidx.compose.runtime.DisposableEffect
23 import androidx.compose.ui.Modifier
24 import androidx.compose.ui.platform.LocalView
25 import com.android.compose.animation.scene.ContentScope
26 import com.android.internal.jank.Cuj
27 import com.android.internal.jank.Cuj.CujType
28 import com.android.internal.jank.InteractionJankMonitor
29 import com.android.systemui.compose.modifiers.sysuiResTag
30 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
31 import com.android.systemui.keyguard.shared.model.KeyguardState
32 import com.android.systemui.keyguard.shared.transition.KeyguardTransitionAnimationCallback
33 import com.android.systemui.keyguard.ui.composable.blueprint.ComposableLockscreenSceneBlueprint
34 import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel
35 import com.android.systemui.lifecycle.rememberViewModel
36 import com.android.systemui.notifications.ui.composable.NotificationLockscreenScrim
37 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationLockscreenScrimViewModel
38 
39 /**
40  * Renders the content of the lockscreen.
41  *
42  * This is separate from the [LockscreenScene] because it's meant to support usage of this UI from
43  * outside the scene container framework.
44  */
45 class LockscreenContent(
46     private val viewModelFactory: LockscreenContentViewModel.Factory,
47     private val notificationScrimViewModelFactory: NotificationLockscreenScrimViewModel.Factory,
48     private val blueprints: Set<@JvmSuppressWildcards ComposableLockscreenSceneBlueprint>,
49     private val clockInteractor: KeyguardClockInteractor,
50     private val interactionJankMonitor: InteractionJankMonitor,
51 ) {
52     private val blueprintByBlueprintId: Map<String, ComposableLockscreenSceneBlueprint> by lazy {
53         blueprints.associateBy { it.id }
54     }
55 
56     @Composable
57     fun ContentScope.Content(modifier: Modifier = Modifier) {
58         val view = LocalView.current
59         val viewModel =
60             rememberViewModel("LockscreenContent-viewModel") {
61                 viewModelFactory.create(
62                     keyguardTransitionAnimationCallback =
63                         KeyguardTransitionAnimationCallbackImpl(view, interactionJankMonitor)
64                 )
65             }
66         val notificationLockscreenScrimViewModel =
67             rememberViewModel("LockscreenContent-scrimViewModel") {
68                 notificationScrimViewModelFactory.create()
69             }
70         if (!viewModel.isContentVisible) {
71             // If the content isn't supposed to be visible, show a large empty box as it's needed
72             // for scene transition animations (can't just skip rendering everything or shared
73             // elements won't have correct final/initial bounds from animating in and out of the
74             // lockscreen scene).
75             Box(modifier)
76             return
77         }
78 
79         DisposableEffect(view) {
80             clockInteractor.clockEventController.registerListeners(view)
81 
82             onDispose { clockInteractor.clockEventController.unregisterListeners() }
83         }
84 
85         val blueprint = blueprintByBlueprintId[viewModel.blueprintId] ?: return
86         with(blueprint) {
87             Content(viewModel, modifier.sysuiResTag("keyguard_root_view"))
88             NotificationLockscreenScrim(notificationLockscreenScrimViewModel)
89         }
90     }
91 }
92 
93 private class KeyguardTransitionAnimationCallbackImpl(
94     private val view: View,
95     private val interactionJankMonitor: InteractionJankMonitor,
96 ) : KeyguardTransitionAnimationCallback {
97 
onAnimationStartednull98     override fun onAnimationStarted(from: KeyguardState, to: KeyguardState) {
99         cujOrNull(from, to)?.let { cuj -> interactionJankMonitor.begin(view, cuj) }
100     }
101 
onAnimationEndednull102     override fun onAnimationEnded(from: KeyguardState, to: KeyguardState) {
103         cujOrNull(from, to)?.let { cuj -> interactionJankMonitor.end(cuj) }
104     }
105 
onAnimationCancelednull106     override fun onAnimationCanceled(from: KeyguardState, to: KeyguardState) {
107         cujOrNull(from, to)?.let { cuj -> interactionJankMonitor.cancel(cuj) }
108     }
109 
110     @CujType
cujOrNullnull111     private fun cujOrNull(from: KeyguardState, to: KeyguardState): Int? {
112         return when {
113             from == KeyguardState.AOD -> Cuj.CUJ_LOCKSCREEN_TRANSITION_FROM_AOD
114             to == KeyguardState.AOD -> Cuj.CUJ_LOCKSCREEN_TRANSITION_TO_AOD
115             else -> null
116         }
117     }
118 }
119