Disable dialog exit animation when locking (1/2) am: 2d5edc3344

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16140773

Change-Id: I6ca06d82a00b2182bdf8485f3a7a0f38d9f7dd69
This commit is contained in:
Jordan Demeulenaere
2021-11-04 13:22:44 +00:00
committed by Automerger Merge Worker
7 changed files with 57 additions and 49 deletions

View File

@@ -38,9 +38,6 @@ private const val TAG = "DialogLaunchAnimator"
/** /**
* A class that allows dialogs to be started in a seamless way from a view that is transforming * A class that allows dialogs to be started in a seamless way from a view that is transforming
* nicely into the starting dialog. * nicely into the starting dialog.
*
* Important: Don't forget to call [DialogLaunchAnimator.onDozeAmountChanged] when the doze amount
* changes to gracefully handle dialogs fading out when the device is dozing.
*/ */
class DialogLaunchAnimator( class DialogLaunchAnimator(
private val context: Context, private val context: Context,
@@ -89,8 +86,17 @@ class DialogLaunchAnimator(
// host dialog. // host dialog.
if (dialog is ListenableDialog) { if (dialog is ListenableDialog) {
dialog.addListener(object : DialogListener { dialog.addListener(object : DialogListener {
override fun onDismiss() { override fun onDismiss(reason: DialogListener.DismissReason) {
dialog.removeListener(this) dialog.removeListener(this)
// We disable the exit animation if we are dismissing the dialog because the
// device is being locked, otherwise the animation looks bad if AOD is enabled.
// If AOD is disabled the screen will directly becomes black and we won't see
// the animation anyways.
if (reason == DialogListener.DismissReason.DEVICE_LOCKED) {
launchAnimation.exitAnimationDisabled = true
}
hostDialog.dismiss() hostDialog.dismiss()
} }
@@ -117,13 +123,6 @@ class DialogLaunchAnimator(
return hostDialog return hostDialog
} }
/** Notify the current doze amount, to ensure that dialogs fade out when dozing. */
// TODO(b/193634619): Replace this by some mandatory constructor parameter to make sure that we
// don't forget to call this when the doze amount changes.
fun onDozeAmountChanged(amount: Float) {
currentAnimations.forEach { it.onDozeAmountChanged(amount) }
}
/** /**
* Ensure that all dialogs currently shown won't animate into their touch surface when * Ensure that all dialogs currently shown won't animate into their touch surface when
* dismissed. * dismissed.
@@ -168,8 +167,16 @@ interface ListenableDialog {
} }
interface DialogListener { interface DialogListener {
/** The reason why a dialog was dismissed. */
enum class DismissReason {
UNKNOWN,
/** The device was locked, which dismissed this dialog. */
DEVICE_LOCKED,
}
/** Called when this dialog dismiss() is called. */ /** Called when this dialog dismiss() is called. */
fun onDismiss() fun onDismiss(reason: DismissReason)
/** Called when this dialog hide() is called. */ /** Called when this dialog hide() is called. */
fun onHide() fun onHide()
@@ -638,14 +645,4 @@ private class DialogLaunchAnimation(
return (touchSurface.parent as? View)?.isShown ?: true return (touchSurface.parent as? View)?.isShown ?: true
} }
internal fun onDozeAmountChanged(amount: Float) {
val alpha = Interpolators.ALPHA_OUT.getInterpolation(1 - amount)
val decorView = this.hostDialog.window?.decorView ?: return
if (decorView.hasOverlappingRendering() && alpha > 0.0f &&
alpha < 1.0f && decorView.layerType != View.LAYER_TYPE_HARDWARE) {
decorView.setLayerType(View.LAYER_TYPE_HARDWARE, null)
}
decorView.alpha = alpha
}
} }

View File

@@ -136,7 +136,6 @@ import com.android.systemui.R;
import com.android.systemui.SystemUI; import com.android.systemui.SystemUI;
import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DelegateLaunchAnimatorController; import com.android.systemui.animation.DelegateLaunchAnimatorController;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.assist.AssistManager; import com.android.systemui.assist.AssistManager;
import com.android.systemui.battery.BatteryMeterViewController; import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.biometrics.AuthRippleController; import com.android.systemui.biometrics.AuthRippleController;
@@ -680,7 +679,6 @@ public class StatusBar extends SystemUI implements
private HeadsUpAppearanceController mHeadsUpAppearanceController; private HeadsUpAppearanceController mHeadsUpAppearanceController;
private final ActivityLaunchAnimator mActivityLaunchAnimator; private final ActivityLaunchAnimator mActivityLaunchAnimator;
private final DialogLaunchAnimator mDialogLaunchAnimator;
private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider; private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
protected StatusBarNotificationPresenter mPresenter; protected StatusBarNotificationPresenter mPresenter;
private NotificationActivityStarter mNotificationActivityStarter; private NotificationActivityStarter mNotificationActivityStarter;
@@ -806,8 +804,7 @@ public class StatusBar extends SystemUI implements
Optional<StartingSurface> startingSurfaceOptional, Optional<StartingSurface> startingSurfaceOptional,
TunerService tunerService, TunerService tunerService,
DumpManager dumpManager, DumpManager dumpManager,
ActivityLaunchAnimator activityLaunchAnimator, ActivityLaunchAnimator activityLaunchAnimator) {
DialogLaunchAnimator dialogLaunchAnimator) {
super(context); super(context);
mNotificationsController = notificationsController; mNotificationsController = notificationsController;
mLightBarController = lightBarController; mLightBarController = lightBarController;
@@ -919,7 +916,6 @@ public class StatusBar extends SystemUI implements
mActivityIntentHelper = new ActivityIntentHelper(mContext); mActivityIntentHelper = new ActivityIntentHelper(mContext);
mActivityLaunchAnimator = activityLaunchAnimator; mActivityLaunchAnimator = activityLaunchAnimator;
mDialogLaunchAnimator = dialogLaunchAnimator;
// The status bar background may need updating when the ongoing call status changes. // The status bar background may need updating when the ongoing call status changes.
mOngoingCallController.addCallback((animate) -> maybeUpdateBarMode()); mOngoingCallController.addCallback((animate) -> maybeUpdateBarMode());
@@ -4481,8 +4477,6 @@ public class StatusBar extends SystemUI implements
&& !mBiometricUnlockController.isWakeAndUnlock()) { && !mBiometricUnlockController.isWakeAndUnlock()) {
mLightRevealScrim.setRevealAmount(1f - linear); mLightRevealScrim.setRevealAmount(1f - linear);
} }
mDialogLaunchAnimator.onDozeAmountChanged(linear);
} }
@Override @Override

View File

@@ -35,6 +35,7 @@ import android.view.WindowManager.LayoutParams;
import com.android.systemui.Dependency; import com.android.systemui.Dependency;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.animation.DialogListener; import com.android.systemui.animation.DialogListener;
import com.android.systemui.animation.DialogListener.DismissReason;
import com.android.systemui.animation.ListenableDialog; import com.android.systemui.animation.ListenableDialog;
import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -62,6 +63,10 @@ public class SystemUIDialog extends AlertDialog implements ListenableDialog {
} }
public SystemUIDialog(Context context, int theme) { public SystemUIDialog(Context context, int theme) {
this(context, theme, true /* dismissOnDeviceLock */);
}
public SystemUIDialog(Context context, int theme, boolean dismissOnDeviceLock) {
super(context, theme); super(context, theme);
mContext = context; mContext = context;
@@ -70,7 +75,7 @@ public class SystemUIDialog extends AlertDialog implements ListenableDialog {
attrs.setTitle(getClass().getSimpleName()); attrs.setTitle(getClass().getSimpleName());
getWindow().setAttributes(attrs); getWindow().setAttributes(attrs);
mDismissReceiver = new DismissReceiver(this); mDismissReceiver = dismissOnDeviceLock ? new DismissReceiver(this) : null;
} }
@Override @Override
@@ -111,14 +116,20 @@ public class SystemUIDialog extends AlertDialog implements ListenableDialog {
@Override @Override
protected void onStart() { protected void onStart() {
super.onStart(); super.onStart();
if (mDismissReceiver != null) {
mDismissReceiver.register(); mDismissReceiver.register();
} }
}
@Override @Override
protected void onStop() { protected void onStop() {
super.onStop(); super.onStop();
if (mDismissReceiver != null) {
mDismissReceiver.unregister(); mDismissReceiver.unregister();
} }
}
@Override @Override
public void addListener(DialogListener listener) { public void addListener(DialogListener listener) {
@@ -132,10 +143,14 @@ public class SystemUIDialog extends AlertDialog implements ListenableDialog {
@Override @Override
public void dismiss() { public void dismiss() {
dismiss(DismissReason.UNKNOWN);
}
private void dismiss(DismissReason reason) {
super.dismiss(); super.dismiss();
for (DialogListener listener : new LinkedHashSet<>(mDialogListeners)) { for (DialogListener listener : new LinkedHashSet<>(mDialogListeners)) {
listener.onDismiss(); listener.onDismiss(reason);
} }
} }
@@ -251,7 +266,11 @@ public class SystemUIDialog extends AlertDialog implements ListenableDialog {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (mDialog instanceof SystemUIDialog) {
((SystemUIDialog) mDialog).dismiss(DismissReason.DEVICE_LOCKED);
} else {
mDialog.dismiss(); mDialog.dismiss();
} }
} }
} }
}

View File

@@ -16,12 +16,18 @@ class SystemUIHostDialogProvider : HostDialogProvider {
return SystemUIHostDialog(context, theme, onCreateCallback, dismissOverride) return SystemUIHostDialog(context, theme, onCreateCallback, dismissOverride)
} }
/**
* This host dialog is a SystemUIDialog so that it's displayed above all SystemUI windows. Note
* that it is not automatically dismissed when the device is locked, but only when the hosted
* (original) dialog is dismissed. That way, the behavior of the dialog (dismissed when locking
* or not) is consistent with when the dialog is shown with or without the dialog animator.
*/
private class SystemUIHostDialog( private class SystemUIHostDialog(
context: Context, context: Context,
theme: Int, theme: Int,
private val onCreateCallback: () -> Unit, private val onCreateCallback: () -> Unit,
private val dismissOverride: (() -> Unit) -> Unit private val dismissOverride: (() -> Unit) -> Unit
) : SystemUIDialog(context, theme) { ) : SystemUIDialog(context, theme, false /* dismissOnDeviceLock */) {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
onCreateCallback() onCreateCallback()

View File

@@ -29,7 +29,6 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback; import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.InitController; import com.android.systemui.InitController;
import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.assist.AssistManager; import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.classifier.FalsingCollector;
@@ -244,8 +243,7 @@ public interface StatusBarPhoneModule {
Optional<StartingSurface> startingSurfaceOptional, Optional<StartingSurface> startingSurfaceOptional,
TunerService tunerService, TunerService tunerService,
DumpManager dumpManager, DumpManager dumpManager,
ActivityLaunchAnimator activityLaunchAnimator, ActivityLaunchAnimator activityLaunchAnimator) {
DialogLaunchAnimator dialogLaunchAnimator) {
return new StatusBar( return new StatusBar(
context, context,
notificationsController, notificationsController,
@@ -346,7 +344,7 @@ public interface StatusBarPhoneModule {
startingSurfaceOptional, startingSurfaceOptional,
tunerService, tunerService,
dumpManager, dumpManager,
activityLaunchAnimator, activityLaunchAnimator
dialogLaunchAnimator); );
} }
} }

View File

@@ -12,6 +12,7 @@ import android.view.WindowManager
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogListener.DismissReason
import junit.framework.Assert.assertEquals import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue import junit.framework.Assert.assertTrue
@@ -63,10 +64,6 @@ class DialogLaunchAnimatorTest : SysuiTestCase() {
assertEquals(1, hostDialogRoot.childCount) assertEquals(1, hostDialogRoot.childCount)
assertEquals(dialog.contentView, hostDialogRoot.getChildAt(0)) assertEquals(dialog.contentView, hostDialogRoot.getChildAt(0))
// If we are dozing, the host dialog window also fades out.
runOnMainThreadAndWaitForIdleSync { dialogLaunchAnimator.onDozeAmountChanged(0.5f) }
assertTrue(hostDialog.window!!.decorView.alpha < 1f)
// Hiding/showing/dismissing the dialog should hide/show/dismiss the host dialog given that // Hiding/showing/dismissing the dialog should hide/show/dismiss the host dialog given that
// it's a ListenableDialog. // it's a ListenableDialog.
runOnMainThreadAndWaitForIdleSync { dialog.hide() } runOnMainThreadAndWaitForIdleSync { dialog.hide() }
@@ -164,7 +161,7 @@ class DialogLaunchAnimatorTest : SysuiTestCase() {
override fun dismiss() { override fun dismiss() {
super.dismiss() super.dismiss()
notifyListeners { onDismiss() } notifyListeners { onDismiss(DismissReason.UNKNOWN) }
} }
override fun hide() { override fun hide() {

View File

@@ -78,7 +78,6 @@ import com.android.systemui.InitController;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.assist.AssistManager; import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.classifier.FalsingCollectorFake;
@@ -281,7 +280,6 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private OperatorNameViewController.Factory mOperatorNameViewControllerFactory; @Mock private OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
@Mock private PhoneStatusBarViewController.Factory mPhoneStatusBarViewControllerFactory; @Mock private PhoneStatusBarViewController.Factory mPhoneStatusBarViewControllerFactory;
@Mock private ActivityLaunchAnimator mActivityLaunchAnimator; @Mock private ActivityLaunchAnimator mActivityLaunchAnimator;
@Mock private DialogLaunchAnimator mDialogLaunchAnimator;
private ShadeController mShadeController; private ShadeController mShadeController;
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock(); private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock); private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
@@ -462,8 +460,7 @@ public class StatusBarTest extends SysuiTestCase {
Optional.of(mStartingSurface), Optional.of(mStartingSurface),
mTunerService, mTunerService,
mock(DumpManager.class), mock(DumpManager.class),
mActivityLaunchAnimator, mActivityLaunchAnimator);
mDialogLaunchAnimator);
when(mKeyguardViewMediator.registerStatusBar( when(mKeyguardViewMediator.registerStatusBar(
any(StatusBar.class), any(StatusBar.class),
any(NotificationPanelViewController.class), any(NotificationPanelViewController.class),