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