1 /* 2 * 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 18 19 import android.app.IActivityTaskManager 20 import android.util.Log 21 import android.view.IRemoteAnimationFinishedCallback 22 import android.view.RemoteAnimationTarget 23 import android.view.WindowManager 24 import com.android.systemui.dagger.SysUISingleton 25 import com.android.systemui.dagger.qualifiers.Main 26 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor 27 import com.android.systemui.keyguard.ui.binder.KeyguardSurfaceBehindParamsApplier 28 import com.android.systemui.statusbar.policy.KeyguardStateController 29 import java.util.concurrent.Executor 30 import javax.inject.Inject 31 32 /** 33 * Manages lockscreen and AOD visibility state via the [IActivityTaskManager], and keeps track of 34 * remote animations related to changes in lockscreen visibility. 35 */ 36 @SysUISingleton 37 class WindowManagerLockscreenVisibilityManager 38 @Inject 39 constructor( 40 @Main private val executor: Executor, 41 private val activityTaskManagerService: IActivityTaskManager, 42 private val keyguardStateController: KeyguardStateController, 43 private val keyguardSurfaceBehindAnimator: KeyguardSurfaceBehindParamsApplier, 44 private val keyguardTransitionInteractor: KeyguardTransitionInteractor, 45 ) { 46 47 /** 48 * Whether the lockscreen is showing, which we pass to [IActivityTaskManager.setLockScreenShown] 49 * in order to show the lockscreen and hide the surface behind the keyguard (or the inverse). 50 * 51 * This value is null if we have not yet called setLockScreenShown with any value. This will 52 * happen during the boot sequence, but we can't default to true here since otherwise we'll 53 * short-circuit on the first call to setLockScreenShown since we'll think we're already 54 * showing. 55 */ 56 private var isLockscreenShowing: Boolean? = null 57 58 /** 59 * Whether AOD is showing, which we pass to [IActivityTaskManager.setLockScreenShown] in order 60 * to show AOD when the lockscreen is visible. 61 */ 62 private var isAodVisible = false 63 64 /** 65 * Whether the keyguard is currently "going away", which we triggered via a call to 66 * [IActivityTaskManager.keyguardGoingAway]. When we tell WM that the keyguard is going away, 67 * the app/launcher surface behind the keyguard is made visible, and WM calls 68 * [onKeyguardGoingAwayRemoteAnimationStart] with a RemoteAnimationTarget so that we can animate 69 * it. 70 * 71 * Going away does not inherently result in [isLockscreenShowing] being set to false; we need to 72 * do that ourselves once we are done animating the surface. 73 * 74 * THIS IS THE ONLY PLACE 'GOING AWAY' TERMINOLOGY SHOULD BE USED. 'Going away' is a WM concept 75 * and we have gotten into trouble using it to mean various different things in the past. Unlock 76 * animations may still be visible when the keyguard is NOT 'going away', for example, when we 77 * play in-window animations, we set the surface to alpha=1f and end the animation immediately. 78 * The remainder of the animation occurs in-window, so while you might expect that the keyguard 79 * is still 'going away' because unlock animations are playing, it's actually not. 80 * 81 * If you want to know if the keyguard is 'going away', you probably want to check if we have 82 * STARTED but not FINISHED a transition to GONE. 83 * 84 * The going away animation will run until: 85 * - We manually call [endKeyguardGoingAwayAnimation] after we're done animating. 86 * - We call [setLockscreenShown] = true, which cancels the going away animation. 87 * - WM calls [onKeyguardGoingAwayRemoteAnimationCancelled] for another reason (such as the 10 88 * second timeout). 89 */ 90 private var isKeyguardGoingAway = false 91 private set(value) { 92 // TODO(b/278086361): Extricate the keyguard state controller. 93 keyguardStateController.notifyKeyguardGoingAway(value) 94 field = value 95 } 96 97 /** Callback provided by WM to call once we're done with the going away animation. */ 98 private var goingAwayRemoteAnimationFinishedCallback: IRemoteAnimationFinishedCallback? = null 99 100 /** 101 * Set the visibility of the surface behind the keyguard, making the appropriate calls to Window 102 * Manager to effect the change. 103 */ setSurfaceBehindVisibilitynull104 fun setSurfaceBehindVisibility(visible: Boolean) { 105 if (isKeyguardGoingAway == visible) { 106 Log.d(TAG, "WmLockscreenVisibilityManager#setVisibility -> already visible=$visible") 107 return 108 } 109 110 // The surface behind is always visible if the lockscreen is not showing, so we're already 111 // visible. 112 if (visible && isLockscreenShowing != true) { 113 Log.d(TAG, "#setVisibility -> already visible since the lockscreen isn't showing") 114 return 115 } 116 117 if (visible) { 118 // Make the surface visible behind the keyguard by calling keyguardGoingAway. The 119 // lockscreen is still showing as well, allowing us to animate unlocked. 120 Log.d(TAG, "ActivityTaskManagerService#keyguardGoingAway()") 121 activityTaskManagerService.keyguardGoingAway(0) 122 isKeyguardGoingAway = true 123 } else { 124 // Hide the surface by setting the lockscreen showing. 125 setLockscreenShown(true) 126 } 127 } 128 setAodVisiblenull129 fun setAodVisible(aodVisible: Boolean) { 130 setWmLockscreenState(aodVisible = aodVisible) 131 } 132 133 /** Sets the visibility of the lockscreen. */ setLockscreenShownnull134 fun setLockscreenShown(lockscreenShown: Boolean) { 135 setWmLockscreenState(lockscreenShowing = lockscreenShown) 136 } 137 onKeyguardGoingAwayRemoteAnimationStartnull138 fun onKeyguardGoingAwayRemoteAnimationStart( 139 @WindowManager.TransitionOldType transit: Int, 140 apps: Array<RemoteAnimationTarget>, 141 wallpapers: Array<RemoteAnimationTarget>, 142 nonApps: Array<RemoteAnimationTarget>, 143 finishedCallback: IRemoteAnimationFinishedCallback 144 ) { 145 // Ensure that we've started a dismiss keyguard transition. WindowManager can start the 146 // going away animation on its own, if an activity launches and then requests dismissing the 147 // keyguard. In this case, this is the first and only signal we'll receive to start 148 // a transition to GONE. This transition needs to start even if we're not provided an app 149 // animation target - it's possible the app is destroyed on creation, etc. but we'll still 150 // be unlocking. 151 keyguardTransitionInteractor.startDismissKeyguardTransition( 152 reason = "Going away remote animation started" 153 ) 154 155 if (apps.isNotEmpty()) { 156 goingAwayRemoteAnimationFinishedCallback = finishedCallback 157 keyguardSurfaceBehindAnimator.applyParamsToSurface(apps[0]) 158 } else { 159 // Nothing to do here if we have no apps, end the animation, which will cancel it and WM 160 // will make *something* visible. 161 finishedCallback.onAnimationFinished() 162 } 163 } 164 onKeyguardGoingAwayRemoteAnimationCancellednull165 fun onKeyguardGoingAwayRemoteAnimationCancelled() { 166 // If WM cancelled the animation, we need to end immediately even if we're still using the 167 // animation. 168 endKeyguardGoingAwayAnimation() 169 } 170 171 /** 172 * Whether the going away remote animation target is in-use, which means we're animating it or 173 * intend to animate it. 174 * 175 * Some unlock animations (such as the translation spring animation) are non-deterministic and 176 * might end after the transition to GONE ends. In that case, we want to keep the remote 177 * animation running until the spring ends. 178 */ setUsingGoingAwayRemoteAnimationnull179 fun setUsingGoingAwayRemoteAnimation(usingTarget: Boolean) { 180 if (!usingTarget) { 181 endKeyguardGoingAwayAnimation() 182 } 183 } 184 185 /** 186 * Sets the lockscreen state WM-side by calling ATMS#setLockScreenShown. 187 * 188 * If [lockscreenShowing] is null, it means we don't know if the lockscreen is showing yet. This 189 * will be decided by the [KeyguardTransitionBootInteractor] shortly. 190 */ setWmLockscreenStatenull191 private fun setWmLockscreenState( 192 lockscreenShowing: Boolean? = this.isLockscreenShowing, 193 aodVisible: Boolean = this.isAodVisible 194 ) { 195 Log.d( 196 TAG, 197 "#setWmLockscreenState(" + 198 "isLockscreenShowing=$lockscreenShowing, " + 199 "aodVisible=$aodVisible)." 200 ) 201 202 if (lockscreenShowing == null) { 203 Log.d( 204 TAG, 205 "isAodVisible=$aodVisible, but lockscreenShowing=null. Waiting for" + 206 "non-null lockscreenShowing before calling ATMS#setLockScreenShown, which" + 207 "will happen once KeyguardTransitionBootInteractor starts the boot transition." 208 ) 209 this.isAodVisible = aodVisible 210 return 211 } 212 213 if (this.isLockscreenShowing == lockscreenShowing && this.isAodVisible == aodVisible) { 214 return 215 } 216 217 Log.d( 218 TAG, 219 "ATMS#setLockScreenShown(" + 220 "isLockscreenShowing=$lockscreenShowing, " + 221 "aodVisible=$aodVisible)." 222 ) 223 activityTaskManagerService.setLockScreenShown(lockscreenShowing, aodVisible) 224 this.isLockscreenShowing = lockscreenShowing 225 this.isAodVisible = aodVisible 226 } 227 endKeyguardGoingAwayAnimationnull228 private fun endKeyguardGoingAwayAnimation() { 229 if (!isKeyguardGoingAway) { 230 Log.d( 231 TAG, 232 "#endKeyguardGoingAwayAnimation() called when isKeyguardGoingAway=false. " + 233 "Short-circuiting." 234 ) 235 return 236 } 237 238 executor.execute { 239 Log.d(TAG, "Finishing remote animation.") 240 goingAwayRemoteAnimationFinishedCallback?.onAnimationFinished() 241 goingAwayRemoteAnimationFinishedCallback = null 242 243 isKeyguardGoingAway = false 244 245 keyguardSurfaceBehindAnimator.notifySurfaceReleased() 246 } 247 } 248 249 companion object { 250 private val TAG = WindowManagerLockscreenVisibilityManager::class.java.simpleName 251 } 252 } 253