Fix bouncer to launcher/app animation

This CL ensures that we don't show the keyguard early when unlocking the
phone from the bouncer after swiping up on the lockscreen.

Bug: 191031464
Test: Manual, swipe up on lockscreen with PIN
Change-Id: Id7269189c857e1108a8e33074bb5abfd40437deb
This commit is contained in:
Jordan Demeulenaere
2021-06-16 10:57:41 +02:00
parent 0052940080
commit 534aef4d05
4 changed files with 167 additions and 96 deletions

View File

@@ -92,5 +92,12 @@ public interface ActivityStarter {
* *after* returning to start hiding the keyguard.
*/
boolean onDismiss();
/**
* Whether running this action when we are locked will start an animation on the keyguard.
*/
default boolean willRunAnimationOnKeyguard() {
return false;
}
}
}

View File

@@ -2841,9 +2841,11 @@ public class StatusBar extends SystemUI implements DemoMode,
mActivityIntentHelper.wouldLaunchResolverActivity(intent,
mLockscreenUserManager.getCurrentUserId());
boolean animate =
animationController != null && !willLaunchResolverActivity && shouldAnimateLaunch(
true /* isActivityIntent */);
ActivityLaunchAnimator.Controller animController =
!willLaunchResolverActivity && shouldAnimateLaunch(true /* isActivityIntent */)
? wrapAnimationController(animationController, dismissShade) : null;
animate ? wrapAnimationController(animationController, dismissShade) : null;
// If we animate, we will dismiss the shade only once the animation is done. This is taken
// care of by the StatusBarLaunchAnimationController.
@@ -2857,7 +2859,7 @@ public class StatusBar extends SystemUI implements DemoMode,
int[] result = new int[]{ActivityManager.START_CANCELED};
mActivityLaunchAnimator.startIntentWithAnimation(animController,
true /* animate */, intent.getPackage(), (adapter) -> {
animate, intent.getPackage(), (adapter) -> {
ActivityOptions options = new ActivityOptions(
getActivityOptions(mDisplayId, adapter));
options.setDisallowEnterPictureInPictureWhileLaunching(
@@ -2907,16 +2909,12 @@ public class StatusBar extends SystemUI implements DemoMode,
}
};
executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly,
willLaunchResolverActivity, true /* deferred */);
willLaunchResolverActivity, true /* deferred */, animate);
}
@Nullable
private ActivityLaunchAnimator.Controller wrapAnimationController(
@Nullable ActivityLaunchAnimator.Controller animationController, boolean dismissShade) {
if (animationController == null) {
return null;
}
ActivityLaunchAnimator.Controller animationController, boolean dismissShade) {
View rootView = animationController.getLaunchContainer().getRootView();
if (rootView == mSuperStatusBarViewFactory.getStatusBarWindowView()) {
// We are animating a view in the status bar. We have to make sure that the status bar
@@ -2959,34 +2957,56 @@ public class StatusBar extends SystemUI implements DemoMode,
final boolean dismissShade,
final boolean afterKeyguardGone,
final boolean deferred) {
dismissKeyguardThenExecute(() -> {
if (runnable != null) {
if (mStatusBarKeyguardViewManager.isShowing()
&& mStatusBarKeyguardViewManager.isOccluded()) {
mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
} else {
AsyncTask.execute(runnable);
}
}
if (dismissShade) {
if (mExpandedVisible && !mBouncerShowing) {
mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
true /* force */, true /* delayed*/);
} else {
executeRunnableDismissingKeyguard(runnable, cancelAction, dismissShade, afterKeyguardGone,
deferred, false /* willAnimateOnKeyguard */);
}
// Do it after DismissAction has been processed to conserve the needed ordering.
mHandler.post(mShadeController::runPostCollapseRunnables);
public void executeRunnableDismissingKeyguard(final Runnable runnable,
final Runnable cancelAction,
final boolean dismissShade,
final boolean afterKeyguardGone,
final boolean deferred,
final boolean willAnimateOnKeyguard) {
OnDismissAction onDismissAction = new OnDismissAction() {
@Override
public boolean onDismiss() {
if (runnable != null) {
if (mStatusBarKeyguardViewManager.isShowing()
&& mStatusBarKeyguardViewManager.isOccluded()) {
mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
} else {
AsyncTask.execute(runnable);
}
}
} else if (isInLaunchTransition()
&& mNotificationPanelViewController.isLaunchTransitionFinished()) {
if (dismissShade) {
if (mExpandedVisible && !mBouncerShowing) {
mShadeController.animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
true /* force */, true /* delayed*/);
} else {
// We are not dismissing the shade, but the launch transition is already finished,
// so nobody will call readyForKeyguardDone anymore. Post it such that
// keyguardDonePending gets called first.
mHandler.post(mStatusBarKeyguardViewManager::readyForKeyguardDone);
// Do it after DismissAction has been processed to conserve the needed
// ordering.
mHandler.post(mShadeController::runPostCollapseRunnables);
}
} else if (StatusBar.this.isInLaunchTransition()
&& mNotificationPanelViewController.isLaunchTransitionFinished()) {
// We are not dismissing the shade, but the launch transition is already
// finished,
// so nobody will call readyForKeyguardDone anymore. Post it such that
// keyguardDonePending gets called first.
mHandler.post(mStatusBarKeyguardViewManager::readyForKeyguardDone);
}
return deferred;
}
return deferred;
}, cancelAction, afterKeyguardGone);
@Override
public boolean willRunAnimationOnKeyguard() {
return willAnimateOnKeyguard;
}
};
dismissKeyguardThenExecute(onDismissAction, cancelAction, afterKeyguardGone);
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -4609,28 +4629,37 @@ public class StatusBar extends SystemUI implements DemoMode,
*
* @param action The action to execute after dismissing the keyguard.
* @param collapsePanel Whether we should collapse the panel after dismissing the keyguard.
* @param deferKeyguardDismiss Whether we should defer the keyguard actual dismissal, for
* instance to run animations on the keyguard before hiding it.
* @param willAnimateOnKeyguard Whether {@param action} will run an animation on the keyguard if
* we are locked.
*/
private void executeActionDismissingKeyguard(Runnable action, boolean afterKeyguardGone,
boolean collapsePanel, boolean deferKeyguardDismiss) {
boolean collapsePanel, boolean willAnimateOnKeyguard) {
if (!mDeviceProvisionedController.isDeviceProvisioned()) return;
dismissKeyguardThenExecute(() -> {
new Thread(() -> {
try {
// The intent we are sending is for the application, which
// won't have permission to immediately start an activity after
// the user switches to home. We know it is safe to do at this
// point, so make sure new activity switches are now allowed.
ActivityManager.getService().resumeAppSwitches();
} catch (RemoteException e) {
}
action.run();
}).start();
OnDismissAction onDismissAction = new OnDismissAction() {
@Override
public boolean onDismiss() {
new Thread(() -> {
try {
// The intent we are sending is for the application, which
// won't have permission to immediately start an activity after
// the user switches to home. We know it is safe to do at this
// point, so make sure new activity switches are now allowed.
ActivityManager.getService().resumeAppSwitches();
} catch (RemoteException e) {
}
action.run();
}).start();
return collapsePanel ? mShadeController.collapsePanel() : deferKeyguardDismiss;
}, afterKeyguardGone);
return collapsePanel ? mShadeController.collapsePanel() : willAnimateOnKeyguard;
}
@Override
public boolean willRunAnimationOnKeyguard() {
return willAnimateOnKeyguard;
}
};
dismissKeyguardThenExecute(onDismissAction, afterKeyguardGone);
}
@Override
@@ -4674,7 +4703,6 @@ public class StatusBar extends SystemUI implements DemoMode,
// the animation on the keyguard). The animation will take care of (instantly) collapsing
// the shade and hiding the keyguard once it is done.
boolean collapse = !animate;
boolean deferKeyguardDismiss = animate;
executeActionDismissingKeyguard(() -> {
try {
// We wrap animationCallback with a StatusBarLaunchAnimatorController so that the
@@ -4703,7 +4731,7 @@ public class StatusBar extends SystemUI implements DemoMode,
if (intentSentUiThreadCallback != null) {
postOnUiThread(intentSentUiThreadCallback);
}
}, willLaunchResolverActivity, collapse, deferKeyguardDismiss);
}, willLaunchResolverActivity, collapse, animate);
}
private void postOnUiThread(Runnable runnable) {

View File

@@ -192,6 +192,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private OnDismissAction mAfterKeyguardGoneAction;
private Runnable mKeyguardGoneCancelAction;
private boolean mDismissActionWillAnimateOnKeyguard;
private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
// Dismiss action to be launched when we stop dozing or the keyguard is gone.
@@ -447,6 +448,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mAfterKeyguardGoneAction = r;
mKeyguardGoneCancelAction = cancelAction;
mDismissActionWillAnimateOnKeyguard = r != null && r.willRunAnimationOnKeyguard();
// If there is an an alternate auth interceptor (like the UDFPS), show that one instead
// of the bouncer.
@@ -625,9 +627,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mBouncer.startPreHideAnimation(finishRunnable);
mStatusBar.onBouncerPreHideAnimation();
// startPreHideAnimation() will change the visibility of the bouncer, so we have to
// make sure to update its state.
updateStates();
// We update the state (which will show the keyguard) only if an animation will run on
// the keyguard. If there is no animation, we wait before updating the state so that we
// go directly from bouncer to launcher/app.
if (mDismissActionWillAnimateOnKeyguard) {
updateStates();
}
} else if (finishRunnable != null) {
finishRunnable.run();
}
@@ -798,6 +803,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mAfterKeyguardGoneAction = null;
}
mKeyguardGoneCancelAction = null;
mDismissActionWillAnimateOnKeyguard = false;
for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) {
mAfterKeyguardGoneRunnables.get(i).run();
}
@@ -866,6 +872,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
return; // allow bouncer to trigger saved actions
}
mAfterKeyguardGoneAction = null;
mDismissActionWillAnimateOnKeyguard = false;
if (mKeyguardGoneCancelAction != null) {
mKeyguardGoneCancelAction.run();
mKeyguardGoneCancelAction = null;

View File

@@ -260,10 +260,19 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
boolean showOverLockscreen = mKeyguardStateController.isShowing() && intent != null
&& mActivityIntentHelper.wouldShowOverLockscreen(intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
ActivityStarter.OnDismissAction postKeyguardAction =
() -> handleNotificationClickAfterKeyguardDismissed(
ActivityStarter.OnDismissAction postKeyguardAction = new ActivityStarter.OnDismissAction() {
@Override
public boolean onDismiss() {
return handleNotificationClickAfterKeyguardDismissed(
entry, row, controller, intent,
isActivityIntent, animate, showOverLockscreen);
}
@Override
public boolean willRunAnimationOnKeyguard() {
return animate;
}
};
if (showOverLockscreen) {
mIsCollapsingToShowActivityOverLockscreen = true;
postKeyguardAction.onDismiss();
@@ -453,53 +462,73 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
public void startNotificationGutsIntent(final Intent intent, final int appUid,
ExpandableNotificationRow row) {
boolean animate = mStatusBar.shouldAnimateLaunch(true /* isActivityIntent */);
mActivityStarter.dismissKeyguardThenExecute(() -> {
AsyncTask.execute(() -> {
ActivityLaunchAnimator.Controller animationController =
new StatusBarLaunchAnimatorController(
mNotificationAnimationProvider.getAnimatorController(row),
mStatusBar, true /* isActivityIntent */);
ActivityStarter.OnDismissAction onDismissAction = new ActivityStarter.OnDismissAction() {
@Override
public boolean onDismiss() {
AsyncTask.execute(() -> {
ActivityLaunchAnimator.Controller animationController =
new StatusBarLaunchAnimatorController(
mNotificationAnimationProvider.getAnimatorController(row),
mStatusBar, true /* isActivityIntent */);
mActivityLaunchAnimator.startIntentWithAnimation(
animationController, animate, intent.getPackage(),
(adapter) -> TaskStackBuilder.create(mContext)
.addNextIntentWithParentStack(intent)
.startActivities(getActivityOptions(
mStatusBar.getDisplayId(),
adapter),
new UserHandle(UserHandle.getUserId(appUid))));
});
return true;
}, null, false /* afterKeyguardGone */);
mActivityLaunchAnimator.startIntentWithAnimation(
animationController, animate, intent.getPackage(),
(adapter) -> TaskStackBuilder.create(mContext)
.addNextIntentWithParentStack(intent)
.startActivities(getActivityOptions(
mStatusBar.getDisplayId(),
adapter),
new UserHandle(UserHandle.getUserId(appUid))));
});
return true;
}
@Override
public boolean willRunAnimationOnKeyguard() {
return animate;
}
};
mActivityStarter.dismissKeyguardThenExecute(onDismissAction, null,
false /* afterKeyguardGone */);
}
@Override
public void startHistoryIntent(View view, boolean showHistory) {
boolean animate = mStatusBar.shouldAnimateLaunch(true /* isActivityIntent */);
mActivityStarter.dismissKeyguardThenExecute(() -> {
AsyncTask.execute(() -> {
Intent intent = showHistory ? new Intent(
Settings.ACTION_NOTIFICATION_HISTORY) : new Intent(
Settings.ACTION_NOTIFICATION_SETTINGS);
TaskStackBuilder tsb = TaskStackBuilder.create(mContext)
.addNextIntent(new Intent(Settings.ACTION_NOTIFICATION_SETTINGS));
if (showHistory) {
tsb.addNextIntent(intent);
}
ActivityStarter.OnDismissAction onDismissAction = new ActivityStarter.OnDismissAction() {
@Override
public boolean onDismiss() {
AsyncTask.execute(() -> {
Intent intent = showHistory ? new Intent(
Settings.ACTION_NOTIFICATION_HISTORY) : new Intent(
Settings.ACTION_NOTIFICATION_SETTINGS);
TaskStackBuilder tsb = TaskStackBuilder.create(mContext)
.addNextIntent(new Intent(Settings.ACTION_NOTIFICATION_SETTINGS));
if (showHistory) {
tsb.addNextIntent(intent);
}
ActivityLaunchAnimator.Controller animationController =
new StatusBarLaunchAnimatorController(
ActivityLaunchAnimator.Controller.fromView(view), mStatusBar,
true /* isActivityIntent */);
ActivityLaunchAnimator.Controller animationController =
new StatusBarLaunchAnimatorController(
ActivityLaunchAnimator.Controller.fromView(view), mStatusBar,
true /* isActivityIntent */);
mActivityLaunchAnimator.startIntentWithAnimation(animationController, animate,
intent.getPackage(),
(adapter) -> tsb.startActivities(
getActivityOptions(mStatusBar.getDisplayId(), adapter),
UserHandle.CURRENT));
});
return true;
}, null, false /* afterKeyguardGone */);
mActivityLaunchAnimator.startIntentWithAnimation(animationController, animate,
intent.getPackage(),
(adapter) -> tsb.startActivities(
getActivityOptions(mStatusBar.getDisplayId(), adapter),
UserHandle.CURRENT));
});
return true;
}
@Override
public boolean willRunAnimationOnKeyguard() {
return animate;
}
};
mActivityStarter.dismissKeyguardThenExecute(onDismissAction, null,
false /* afterKeyguardGone */);
}
private void removeHunAfterClick(ExpandableNotificationRow row) {