Adds the staggered ring unlock animation!
Bug: 197636896 Test: a lot of unlocking Change-Id: I18438b279c911c4f6ca37d954eeca506a1e05980
This commit is contained in:
@@ -30,7 +30,7 @@ interface ILauncherUnlockAnimationController {
|
|||||||
|
|
||||||
// Play a full unlock animation from 0f to 1f. This is used when System UI is unlocking from a
|
// Play a full unlock animation from 0f to 1f. This is used when System UI is unlocking from a
|
||||||
// single action, such as biometric auth, and doesn't need to control individual frames.
|
// single action, such as biometric auth, and doesn't need to control individual frames.
|
||||||
oneway void playUnlockAnimation(boolean unlocked, long duration);
|
oneway void playUnlockAnimation(boolean unlocked, long duration, long startDelay);
|
||||||
|
|
||||||
// Set the selected page on Launcher's smartspace.
|
// Set the selected page on Launcher's smartspace.
|
||||||
oneway void setSmartspaceSelectedPage(int selectedPage);
|
oneway void setSmartspaceSelectedPage(int selectedPage);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.content.Context
|
|||||||
import android.graphics.Matrix
|
import android.graphics.Matrix
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
|
import android.provider.Settings
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.RemoteAnimationTarget
|
import android.view.RemoteAnimationTarget
|
||||||
import android.view.SyncRtSurfaceTransactionApplier
|
import android.view.SyncRtSurfaceTransactionApplier
|
||||||
@@ -93,6 +94,20 @@ const val DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD = 0.4f
|
|||||||
*/
|
*/
|
||||||
const val UNLOCK_ANIMATION_DURATION_MS = 200L
|
const val UNLOCK_ANIMATION_DURATION_MS = 200L
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How long the in-window launcher icon animation takes. This is used if the launcher is underneath
|
||||||
|
* the lock screen and supports in-window animations.
|
||||||
|
*
|
||||||
|
* This animation will take place entirely within the Launcher window. We can safely unlock the
|
||||||
|
* device, end remote animations, etc. even if this is still running.
|
||||||
|
*/
|
||||||
|
const val LAUNCHER_ICONS_ANIMATION_DURATION_MS = 633L
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How long to wait for the shade to get out of the way before starting the canned unlock animation.
|
||||||
|
*/
|
||||||
|
const val CANNED_UNLOCK_START_DELAY = 100L
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Duration for the alpha animation on the surface behind. This plays to fade in the surface during
|
* Duration for the alpha animation on the surface behind. This plays to fade in the surface during
|
||||||
* a swipe to unlock (and to fade it back out if the swipe is cancelled).
|
* a swipe to unlock (and to fade it back out if the swipe is cancelled).
|
||||||
@@ -119,7 +134,7 @@ const val UNLOCK_ANIMATION_SURFACE_BEHIND_START_DELAY_MS = 75L
|
|||||||
*/
|
*/
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
class KeyguardUnlockAnimationController @Inject constructor(
|
class KeyguardUnlockAnimationController @Inject constructor(
|
||||||
context: Context,
|
private val context: Context,
|
||||||
private val keyguardStateController: KeyguardStateController,
|
private val keyguardStateController: KeyguardStateController,
|
||||||
private val
|
private val
|
||||||
keyguardViewMediator: Lazy<KeyguardViewMediator>,
|
keyguardViewMediator: Lazy<KeyguardViewMediator>,
|
||||||
@@ -483,23 +498,34 @@ class KeyguardUnlockAnimationController @Inject constructor(
|
|||||||
* transition if possible.
|
* transition if possible.
|
||||||
*/
|
*/
|
||||||
private fun unlockToLauncherWithInWindowAnimations() {
|
private fun unlockToLauncherWithInWindowAnimations() {
|
||||||
unlockingToLauncherWithInWindowAnimations = true
|
|
||||||
|
|
||||||
// See if we can do the smartspace transition, and if so, do it!
|
// See if we can do the smartspace transition, and if so, do it!
|
||||||
if (prepareForSmartspaceTransition()) {
|
if (prepareForSmartspaceTransition()) {
|
||||||
animateSmartspaceToDestination()
|
animateSmartspaceToDestination()
|
||||||
listeners.forEach { it.onSmartspaceSharedElementTransitionStarted() }
|
listeners.forEach { it.onSmartspaceSharedElementTransitionStarted() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the launcher to prepare for the animation by setting its views invisible and
|
val startDelay = Settings.Secure.getLong(
|
||||||
// syncing the selected smartspace pages.
|
context.contentResolver, "unlock_start_delay", CANNED_UNLOCK_START_DELAY)
|
||||||
launcherUnlockController?.prepareForUnlock(
|
val duration = Settings.Secure.getLong(
|
||||||
unlockingWithSmartspaceTransition /* willAnimateSmartspace */,
|
context.contentResolver, "unlock_duration", LAUNCHER_ICONS_ANIMATION_DURATION_MS)
|
||||||
(lockscreenSmartspace as BcSmartspaceDataPlugin.SmartspaceView?)?.selectedPage ?: -1)
|
|
||||||
|
|
||||||
// Begin the animation.
|
unlockingToLauncherWithInWindowAnimations = true
|
||||||
|
prepareLauncherWorkspaceForUnlockAnimation()
|
||||||
|
|
||||||
|
// Begin the animation, waiting for the shade to animate out.
|
||||||
launcherUnlockController?.playUnlockAnimation(
|
launcherUnlockController?.playUnlockAnimation(
|
||||||
true /* unlocked */, UNLOCK_ANIMATION_DURATION_MS)
|
true /* unlocked */,
|
||||||
|
duration /* duration */,
|
||||||
|
startDelay /* startDelay */)
|
||||||
|
|
||||||
|
handler.postDelayed({
|
||||||
|
applyParamsToSurface(
|
||||||
|
SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(
|
||||||
|
surfaceBehindRemoteAnimationTarget!!.leash)
|
||||||
|
.withAlpha(1f)
|
||||||
|
.build())
|
||||||
|
}, startDelay)
|
||||||
|
|
||||||
if (!unlockingWithSmartspaceTransition) {
|
if (!unlockingWithSmartspaceTransition) {
|
||||||
// If we are not unlocking with the smartspace transition, wait for the unlock animation
|
// If we are not unlocking with the smartspace transition, wait for the unlock animation
|
||||||
// to end and then finish the remote animation. If we are using the smartspace
|
// to end and then finish the remote animation. If we are using the smartspace
|
||||||
@@ -509,9 +535,18 @@ class KeyguardUnlockAnimationController @Inject constructor(
|
|||||||
false /* cancelled */)
|
false /* cancelled */)
|
||||||
}, UNLOCK_ANIMATION_DURATION_MS)
|
}, UNLOCK_ANIMATION_DURATION_MS)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Wait a moment, then show the launcher surface.
|
/**
|
||||||
setSurfaceBehindAppearAmount(1f)
|
* Asks Launcher to prepare the workspace to be unlocked. This sets up the animation and makes
|
||||||
|
* the page invisible.
|
||||||
|
*/
|
||||||
|
private fun prepareLauncherWorkspaceForUnlockAnimation() {
|
||||||
|
// Tell the launcher to prepare for the animation by setting its views invisible and
|
||||||
|
// syncing the selected smartspace pages.
|
||||||
|
launcherUnlockController?.prepareForUnlock(
|
||||||
|
unlockingWithSmartspaceTransition /* willAnimateSmartspace */,
|
||||||
|
(lockscreenSmartspace as BcSmartspaceDataPlugin.SmartspaceView?)?.selectedPage ?: -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -615,8 +650,11 @@ class KeyguardUnlockAnimationController @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (unlockingToLauncherWithInWindowAnimations) {
|
if (unlockingToLauncherWithInWindowAnimations) {
|
||||||
// If we're using the in-window launcher animations, and haven't yet applied alpha = 1f
|
// If we aren't using the canned unlock animation (which would be setting the unlock
|
||||||
// to the launcher surface, do that now so we can see the launcher animations.
|
// amount in its update listener), do it here.
|
||||||
|
if (!isPlayingCannedUnlockAnimation()) {
|
||||||
|
launcherUnlockController?.setUnlockAmount(amount)
|
||||||
|
|
||||||
if (surfaceBehindParams?.alpha?.let { it < 1f } != false) {
|
if (surfaceBehindParams?.alpha?.let { it < 1f } != false) {
|
||||||
applyParamsToSurface(
|
applyParamsToSurface(
|
||||||
SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(
|
SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(
|
||||||
@@ -624,11 +662,6 @@ class KeyguardUnlockAnimationController @Inject constructor(
|
|||||||
.withAlpha(1f)
|
.withAlpha(1f)
|
||||||
.build())
|
.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we aren't using the canned unlock animation (which would be setting the unlock
|
|
||||||
// amount in its update listener), do it here.
|
|
||||||
if (!isPlayingCannedUnlockAnimation()) {
|
|
||||||
launcherUnlockController?.setUnlockAmount(amount)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, animate in the surface's scale/transltion.
|
// Otherwise, animate in the surface's scale/transltion.
|
||||||
@@ -743,9 +776,10 @@ class KeyguardUnlockAnimationController @Inject constructor(
|
|||||||
!keyguardViewMediator.get().requestedShowSurfaceBehindKeyguard()) {
|
!keyguardViewMediator.get().requestedShowSurfaceBehindKeyguard()) {
|
||||||
// We passed the threshold, and we're not yet showing the surface behind the
|
// We passed the threshold, and we're not yet showing the surface behind the
|
||||||
// keyguard. Animate it in.
|
// keyguard. Animate it in.
|
||||||
if (canPerformInWindowLauncherAnimations()) {
|
if (!unlockingToLauncherWithInWindowAnimations &&
|
||||||
launcherUnlockController?.setUnlockAmount(0f)
|
canPerformInWindowLauncherAnimations()) {
|
||||||
unlockingToLauncherWithInWindowAnimations = true
|
unlockingToLauncherWithInWindowAnimations = true
|
||||||
|
prepareLauncherWorkspaceForUnlockAnimation()
|
||||||
}
|
}
|
||||||
keyguardViewMediator.get().showSurfaceBehindKeyguard()
|
keyguardViewMediator.get().showSurfaceBehindKeyguard()
|
||||||
fadeInSurfaceBehind()
|
fadeInSurfaceBehind()
|
||||||
@@ -928,7 +962,11 @@ class KeyguardUnlockAnimationController @Inject constructor(
|
|||||||
* the device.
|
* the device.
|
||||||
*/
|
*/
|
||||||
fun canPerformInWindowLauncherAnimations(): Boolean {
|
fun canPerformInWindowLauncherAnimations(): Boolean {
|
||||||
return isNexusLauncherUnderneath() && launcherUnlockController != null
|
return isNexusLauncherUnderneath() &&
|
||||||
|
launcherUnlockController != null &&
|
||||||
|
// Temporarily disable for foldables since foldable launcher has two first pages,
|
||||||
|
// which breaks the in-window animation.
|
||||||
|
!isFoldable(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -969,5 +1007,9 @@ class KeyguardUnlockAnimationController @Inject constructor(
|
|||||||
.runningTask?.topActivity?.className?.equals(
|
.runningTask?.topActivity?.className?.equals(
|
||||||
QuickStepContract.LAUNCHER_ACTIVITY_CLASS_NAME) ?: false
|
QuickStepContract.LAUNCHER_ACTIVITY_CLASS_NAME) ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isFoldable(context: Context): Boolean {
|
||||||
|
return context.resources.getIntArray(R.array.config_foldedDeviceStates).isNotEmpty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -903,7 +903,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
onTrackingStopped(false);
|
onTrackingStopped(false);
|
||||||
instantCollapse();
|
instantCollapse();
|
||||||
} else {
|
} else {
|
||||||
fling(0f, false, 0.7f, false);
|
fling(0f, false, 1f, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user