Uses ActivityLaunchAnimator for occlusion animations.
This is used when the lock screen is visible and an activity occludes it, such as the camera. Currently, the camera launches behind the lock screen and then the lock screen janks out of the way to show the camera. There are currently some pretty severe performance issues, but I'm not sure yet whether that's due to the new launch animator, or the fact that the old animation is so janky that you can't really tell. I'm investigating that, but we should get this into the build to start working out any bugs with the remote occlude animations. This requires remote occlude animations to be enabled: adb shell setprop persist.wm.enable_remote_keyguard_animation 2 Test: atest SystemUITests Bug: 197312643 Change-Id: Id801e44c25c6e2340b4269d215b9a1c056f0ceff
This commit is contained in:
@@ -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() {}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
|
||||
|
||||
@@ -679,6 +679,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the secure camera is currently showing over the keyguard.
|
||||
*/
|
||||
public boolean isSecureCameraLaunchedOverKeyguard() {
|
||||
return mSecureCameraLaunched;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a cached version of DreamManager.isDreaming()
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user