diff options
7 files changed, 196 insertions, 45 deletions
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt index 08d217d15a5a..4540b77d0a40 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt @@ -301,6 +301,7 @@ class ActivityLaunchAnimator( * The intent was started. If [willAnimate] is false, nothing else will happen and the * animation will not be started. */ + @JvmDefault fun onIntentStarted(willAnimate: Boolean) {} /** @@ -308,6 +309,7 @@ class ActivityLaunchAnimator( * this if the animation was already started, i.e. if [onLaunchAnimationStart] was called * before the cancellation. */ + @JvmDefault fun onLaunchAnimationCancelled() {} } diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt index ebe96ebf2988..77386cf2ff10 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt @@ -100,9 +100,11 @@ class LaunchAnimator( * needed for the animation. [isExpandingFullyAbove] will be true if the window is expanding * fully above the [launchContainer]. */ + @JvmDefault fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {} /** The animation made progress and the expandable view [state] should be updated. */ + @JvmDefault fun onLaunchAnimationProgress(state: State, progress: Float, linearProgress: Float) {} /** @@ -110,6 +112,7 @@ class LaunchAnimator( * called previously. This is typically used to clean up the resources initialized when the * animation was started. */ + @JvmDefault fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {} } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index f2d0427c39d3..451fa63af398 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -680,6 +680,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } /** + * Whether the secure camera is currently showing over the keyguard. + */ + public boolean isSecureCameraLaunchedOverKeyguard() { + return mSecureCameraLaunched; + } + + /** * @return a cached version of DreamManager.isDreaming() */ public boolean isDreaming() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index e88011e0d3fe..88555edd1e8b 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -233,10 +233,13 @@ public class KeyguardService extends Service { mKeyguardViewMediator = keyguardViewMediator; mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher; mShellTransitions = shellTransitions; + } - if (shellTransitions != null && Transitions.ENABLE_SHELL_TRANSITIONS) { - // Nothing here. Initialization for this happens in onCreate. - } else { + @Override + public void onCreate() { + ((SystemUIApplication) getApplication()).startServicesIfNeeded(); + + if (mShellTransitions == null || !Transitions.ENABLE_SHELL_TRANSITIONS) { RemoteAnimationDefinition definition = new RemoteAnimationDefinition(); if (sEnableRemoteKeyguardGoingAwayAnimation) { final RemoteAnimationAdapter exitAnimationAdapter = @@ -248,22 +251,19 @@ public class KeyguardService extends Service { } if (sEnableRemoteKeyguardOccludeAnimation) { final RemoteAnimationAdapter occludeAnimationAdapter = - new RemoteAnimationAdapter(mOccludeAnimationRunner, 0, 0); + new RemoteAnimationAdapter( + mKeyguardViewMediator.getOccludeAnimationRunner(), 0, 0); definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_OCCLUDE, occludeAnimationAdapter); + + final RemoteAnimationAdapter unoccludeAnimationAdapter = + new RemoteAnimationAdapter( + mKeyguardViewMediator.getUnoccludeAnimationRunner(), 0, 0); definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_UNOCCLUDE, - occludeAnimationAdapter); + unoccludeAnimationAdapter); } ActivityTaskManager.getInstance().registerRemoteAnimationsForDisplay( DEFAULT_DISPLAY, definition); - } - } - - @Override - public void onCreate() { - ((SystemUIApplication) getApplication()).startServicesIfNeeded(); - - if (mShellTransitions == null || !Transitions.ENABLE_SHELL_TRANSITIONS) { return; } if (sEnableRemoteKeyguardGoingAwayAnimation) { @@ -354,33 +354,6 @@ public class KeyguardService extends Service { } }; - private final IRemoteAnimationRunner.Stub mOccludeAnimationRunner = - new IRemoteAnimationRunner.Stub() { - @Override // Binder interface - public void onAnimationStart(@WindowManager.TransitionOldType int transit, - RemoteAnimationTarget[] apps, - RemoteAnimationTarget[] wallpapers, - RemoteAnimationTarget[] nonApps, - IRemoteAnimationFinishedCallback finishedCallback) { - Slog.d(TAG, "mOccludeAnimationRunner.onAnimationStart: transit=" + transit); - try { - if (transit == TRANSIT_OLD_KEYGUARD_OCCLUDE) { - mBinder.setOccluded(true /* isOccluded */, true /* animate */); - } else if (transit == TRANSIT_OLD_KEYGUARD_UNOCCLUDE) { - mBinder.setOccluded(false /* isOccluded */, false /* animate */); - } - // TODO(bc-unlock): Implement (un)occlude animation. - finishedCallback.onAnimationFinished(); - } catch (RemoteException e) { - Slog.e(TAG, "RemoteException"); - } - } - - @Override // Binder interface - public void onAnimationCancelled() { - } - }; - final IRemoteTransition mOccludeAnimation = new IRemoteTransition.Stub() { @Override public void startAnimation(IBinder transition, TransitionInfo info, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index fd2c6dd3ca36..0f08a1863e08 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -77,11 +77,13 @@ import android.view.IRemoteAnimationRunner; import android.view.RemoteAnimationTarget; import android.view.SyncRtSurfaceTransactionApplier; import android.view.View; +import android.view.ViewGroup; import android.view.WindowManager; import android.view.WindowManagerPolicyConstants; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.jank.InteractionJankMonitor; @@ -89,6 +91,7 @@ import com.android.internal.jank.InteractionJankMonitor.Configuration; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IKeyguardExitCallback; import com.android.internal.policy.IKeyguardStateCallback; +import com.android.internal.policy.ScreenDecorationsUtils; import com.android.internal.util.LatencyTracker; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardConstants; @@ -102,7 +105,10 @@ import com.android.keyguard.mediator.ScreenOnCoordinator; import com.android.systemui.CoreStartable; import com.android.systemui.DejankUtils; import com.android.systemui.Dumpable; +import com.android.systemui.R; +import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.Interpolators; +import com.android.systemui.animation.LaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.dagger.qualifiers.UiBackground; @@ -375,6 +381,9 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, private int mUnlockSoundId; private int mTrustedSoundId; private int mLockSoundStreamId; + private final float mPowerButtonY; + private final float mWindowCornerRadius; + /** * The animation used for hiding keyguard. This is used to fetch the animation timings if * WindowManager is not providing us with them. @@ -815,6 +824,109 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, } }; + /** + * Animation launch controller for activities that occlude the keyguard. + */ + private final ActivityLaunchAnimator.Controller mOccludeAnimationController = + new ActivityLaunchAnimator.Controller() { + @Override + public void onLaunchAnimationStart(boolean isExpandingFullyAbove) { + setOccluded(true /* occluded */, false /* animate */); + } + + @Override + public void onLaunchAnimationCancelled() { + setOccluded(true /* occluded */, false /* animate */); + } + + @NonNull + @Override + public ViewGroup getLaunchContainer() { + return ((ViewGroup) mKeyguardViewControllerLazy.get() + .getViewRootImpl().getView()); + } + + @Override + public void setLaunchContainer(@NonNull ViewGroup launchContainer) { + // No-op, launch container is always the shade. + Log.wtf(TAG, "Someone tried to change the launch container for the " + + "ActivityLaunchAnimator, which should never happen."); + } + + @NonNull + @Override + public LaunchAnimator.State createAnimatorState() { + final int width = getLaunchContainer().getWidth(); + final int height = getLaunchContainer().getHeight(); + + final float initialHeight = height / 3f; + final float initialWidth = width / 3f; + + if (mUpdateMonitor.isSecureCameraLaunchedOverKeyguard()) { + // Start the animation near the power button, at one-third size, since the + // camera was launched from the power button. + return new LaunchAnimator.State( + (int) (mPowerButtonY - initialHeight / 2f) /* top */, + (int) (mPowerButtonY + initialHeight / 2f) /* bottom */, + (int) (width - initialWidth) /* left */, + width /* right */, + mWindowCornerRadius, mWindowCornerRadius); + } else { + // Start the animation in the center of the screen, scaled down. + return new LaunchAnimator.State( + height / 2, height / 2, width / 2, width / 2, + mWindowCornerRadius, mWindowCornerRadius); + } + } + }; + + /** + * Animation controller for activities that unocclude the keyguard. This will play the launch + * animation in reverse. + */ + private final ActivityLaunchAnimator.Controller mUnoccludeAnimationController = + new ActivityLaunchAnimator.Controller() { + @Override + public void onLaunchAnimationEnd(boolean isExpandingFullyAbove) { + setOccluded(false /* isOccluded */, false /* animate */); + } + + @Override + public void onLaunchAnimationCancelled() { + setOccluded(false /* isOccluded */, false /* animate */); + } + + @NonNull + @Override + public ViewGroup getLaunchContainer() { + return ((ViewGroup) mKeyguardViewControllerLazy.get() + .getViewRootImpl().getView()); + } + + @Override + public void setLaunchContainer(@NonNull ViewGroup launchContainer) { + // No-op, launch container is always the shade. + Log.wtf(TAG, "Someone tried to change the launch container for the " + + "ActivityLaunchAnimator, which should never happen."); + } + + @NonNull + @Override + public LaunchAnimator.State createAnimatorState() { + final int width = getLaunchContainer().getWidth(); + final int height = getLaunchContainer().getHeight(); + + // TODO(b/207399883): Unocclude animation. This currently ends instantly. + return new LaunchAnimator.State( + 0, height, 0, width, mWindowCornerRadius, mWindowCornerRadius); + } + }; + + private IRemoteAnimationRunner mOccludeAnimationRunner = + new ActivityLaunchRemoteAnimationRunner(mOccludeAnimationController); + private IRemoteAnimationRunner mUnoccludeAnimationRunner = + new ActivityLaunchRemoteAnimationRunner(mUnoccludeAnimationController); + private DeviceConfigProxy mDeviceConfig; private DozeParameters mDozeParameters; @@ -824,6 +936,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, private boolean mWallpaperSupportsAmbientMode; private ScreenOnCoordinator mScreenOnCoordinator; + private Lazy<ActivityLaunchAnimator> mActivityLaunchAnimator; + /** * Injected constructor. See {@link KeyguardModule}. */ @@ -850,7 +964,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, ScreenOnCoordinator screenOnCoordinator, InteractionJankMonitor interactionJankMonitor, DreamOverlayStateController dreamOverlayStateController, - Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy) { + Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy, + Lazy<ActivityLaunchAnimator> activityLaunchAnimator) { super(context); mFalsingCollector = falsingCollector; mLockPatternUtils = lockPatternUtils; @@ -890,6 +1005,12 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, mScreenOffAnimationController = screenOffAnimationController; mInteractionJankMonitor = interactionJankMonitor; mDreamOverlayStateController = dreamOverlayStateController; + + mActivityLaunchAnimator = activityLaunchAnimator; + + mPowerButtonY = context.getResources().getDimensionPixelSize( + R.dimen.physical_power_button_center_screen_location_y); + mWindowCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context); } public void userActivity() { @@ -1440,6 +1561,14 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, Trace.endSection(); } + public IRemoteAnimationRunner getOccludeAnimationRunner() { + return mOccludeAnimationRunner; + } + + public IRemoteAnimationRunner getUnoccludeAnimationRunner() { + return mUnoccludeAnimationRunner; + } + public boolean isHiding() { return mHiding; } @@ -2868,4 +2997,36 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, return mMessage; } } + + /** + * Implementation of RemoteAnimationRunner that creates a new + * {@link ActivityLaunchAnimator.Runner} whenever onAnimationStart is called, delegating the + * remote animation methods to that runner. + */ + private class ActivityLaunchRemoteAnimationRunner extends IRemoteAnimationRunner.Stub { + + private final ActivityLaunchAnimator.Controller mActivityLaunchController; + @Nullable private ActivityLaunchAnimator.Runner mRunner; + + ActivityLaunchRemoteAnimationRunner(ActivityLaunchAnimator.Controller controller) { + mActivityLaunchController = controller; + } + + @Override + public void onAnimationCancelled() throws RemoteException { + if (mRunner != null) { + mRunner.onAnimationCancelled(); + } + } + + @Override + public void onAnimationStart(int transit, RemoteAnimationTarget[] apps, + RemoteAnimationTarget[] wallpapers, + RemoteAnimationTarget[] nonApps, + IRemoteAnimationFinishedCallback finishedCallback) + throws RemoteException { + mRunner = mActivityLaunchAnimator.get().createRunner(mActivityLaunchController); + mRunner.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java index b49b49cbbb6d..195ef1a84c43 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java @@ -32,6 +32,7 @@ import com.android.keyguard.dagger.KeyguardStatusBarViewComponent; import com.android.keyguard.dagger.KeyguardStatusViewComponent; import com.android.keyguard.dagger.KeyguardUserSwitcherComponent; import com.android.keyguard.mediator.ScreenOnCoordinator; +import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.classifier.FalsingModule; @@ -102,7 +103,8 @@ public class KeyguardModule { ScreenOnCoordinator screenOnCoordinator, InteractionJankMonitor interactionJankMonitor, DreamOverlayStateController dreamOverlayStateController, - Lazy<NotificationShadeWindowController> notificationShadeWindowController) { + Lazy<NotificationShadeWindowController> notificationShadeWindowController, + Lazy<ActivityLaunchAnimator> activityLaunchAnimator) { return new KeyguardViewMediator( context, falsingCollector, @@ -128,8 +130,8 @@ public class KeyguardModule { screenOnCoordinator, interactionJankMonitor, dreamOverlayStateController, - notificationShadeWindowController - ); + notificationShadeWindowController, + activityLaunchAnimator); } @SysUISingleton diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index d94e2eee9ffa..210cb82e1606 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -46,6 +46,7 @@ import com.android.keyguard.KeyguardDisplayManager; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.mediator.ScreenOnCoordinator; import com.android.systemui.SysuiTestCase; +import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.dreams.DreamOverlayStateController; @@ -100,6 +101,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock ScreenOnCoordinator mScreenOnCoordinator; private @Mock Lazy<NotificationShadeWindowController> mNotificationShadeWindowControllerLazy; private @Mock DreamOverlayStateController mDreamOverlayStateController; + private @Mock ActivityLaunchAnimator mActivityLaunchAnimator; private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake(); private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -205,7 +207,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mScreenOnCoordinator, mInteractionJankMonitor, mDreamOverlayStateController, - mNotificationShadeWindowControllerLazy); + mNotificationShadeWindowControllerLazy, + () -> mActivityLaunchAnimator); mViewMediator.start(); } } |