Loading packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt +2 −35 Original line number Diff line number Diff line Loading @@ -33,13 +33,9 @@ import android.view.WindowInsets import android.view.WindowManager import android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS import android.widget.FrameLayout import android.window.OnBackInvokedDispatcher import com.android.internal.jank.InteractionJankMonitor import com.android.internal.jank.InteractionJankMonitor.CujType import com.android.systemui.animation.back.BackAnimationSpec import com.android.systemui.animation.back.applyTo import com.android.systemui.animation.back.floatingSystemSurfacesForSysUi import com.android.systemui.animation.back.onBackAnimationCallbackFrom import com.android.systemui.util.registerAnimationOnBackInvoked import java.lang.IllegalArgumentException import kotlin.math.roundToInt Loading Loading @@ -798,7 +794,7 @@ private class AnimatedDialog( if (featureFlags.isPredictiveBackQsDialogAnim) { // TODO(b/265923095) Improve animations for QS dialogs on configuration change registerOnBackInvokedCallback(targetView = dialogContentWithBackground) dialog.registerAnimationOnBackInvoked(targetView = dialogContentWithBackground) } // Show the dialog. Loading @@ -806,35 +802,6 @@ private class AnimatedDialog( moveSourceDrawingToDialog() } private fun registerOnBackInvokedCallback(targetView: View) { val metrics = targetView.resources.displayMetrics val onBackAnimationCallback = onBackAnimationCallbackFrom( backAnimationSpec = BackAnimationSpec.floatingSystemSurfacesForSysUi(metrics), displayMetrics = metrics, // TODO(b/265060720): We could remove this onBackProgressed = { backTransformation -> backTransformation.applyTo(targetView) }, onBackInvoked = { dialog.dismiss() }, ) val dispatcher = dialog.onBackInvokedDispatcher targetView.addOnAttachStateChangeListener( object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View) { dispatcher.registerOnBackInvokedCallback( OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackAnimationCallback ) } override fun onViewDetachedFromWindow(v: View) { targetView.removeOnAttachStateChangeListener(this) dispatcher.unregisterOnBackInvokedCallback(onBackAnimationCallback) } } ) } private fun moveSourceDrawingToDialog() { if (decorView.viewRootImpl == null) { // Make sure that we have access to the dialog view root to move the drawing to the Loading packages/SystemUI/animation/src/com/android/systemui/animation/back/OnBackAnimationCallbackExtension.kt +37 −0 Original line number Diff line number Diff line Loading @@ -16,15 +16,21 @@ package com.android.systemui.animation.back import android.annotation.IntRange import android.util.DisplayMetrics import android.view.View import android.window.BackEvent import android.window.OnBackAnimationCallback import android.window.OnBackInvokedDispatcher import android.window.OnBackInvokedDispatcher.Priority /** * Generates an [OnBackAnimationCallback] given a [backAnimationSpec]. [onBackProgressed] will be * called on each update passing the current [BackTransformation]. * * Optionally, you can specify [onBackStarted], [onBackInvoked], and [onBackCancelled] callbacks. * * @sample com.android.systemui.util.registerAnimationOnBackInvoked */ fun onBackAnimationCallbackFrom( backAnimationSpec: BackAnimationSpec, Loading Loading @@ -64,3 +70,34 @@ fun onBackAnimationCallbackFrom( } } } /** * Register [OnBackAnimationCallback] when View is attached and unregister it when View is detached * * @sample com.android.systemui.util.registerAnimationOnBackInvoked */ fun View.registerOnBackInvokedCallbackOnViewAttached( onBackInvokedDispatcher: OnBackInvokedDispatcher, onBackAnimationCallback: OnBackAnimationCallback, @Priority @IntRange(from = 0) priority: Int = OnBackInvokedDispatcher.PRIORITY_DEFAULT, ) { addOnAttachStateChangeListener( object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View) { onBackInvokedDispatcher.registerOnBackInvokedCallback( priority, onBackAnimationCallback ) } override fun onViewDetachedFromWindow(v: View) { removeOnAttachStateChangeListener(this) onBackInvokedDispatcher.unregisterOnBackInvokedCallback(onBackAnimationCallback) } } ) if (isAttachedToWindow) { onBackInvokedDispatcher.registerOnBackInvokedCallback(priority, onBackAnimationCallback) } } packages/SystemUI/animation/src/com/android/systemui/util/Dialog.kt 0 → 100644 +51 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.util import android.app.Dialog import android.view.View import android.window.OnBackInvokedDispatcher import com.android.systemui.animation.back.BackAnimationSpec import com.android.systemui.animation.back.BackTransformation import com.android.systemui.animation.back.applyTo import com.android.systemui.animation.back.floatingSystemSurfacesForSysUi import com.android.systemui.animation.back.onBackAnimationCallbackFrom import com.android.systemui.animation.back.registerOnBackInvokedCallbackOnViewAttached /** * Register on the Dialog's [OnBackInvokedDispatcher] an animation using the [BackAnimationSpec]. * The [BackTransformation] will be applied on the [targetView]. */ @JvmOverloads fun Dialog.registerAnimationOnBackInvoked( targetView: View, backAnimationSpec: BackAnimationSpec = BackAnimationSpec.floatingSystemSurfacesForSysUi( displayMetrics = targetView.resources.displayMetrics, ), ) { targetView.registerOnBackInvokedCallbackOnViewAttached( onBackInvokedDispatcher = onBackInvokedDispatcher, onBackAnimationCallback = onBackAnimationCallbackFrom( backAnimationSpec = backAnimationSpec, displayMetrics = targetView.resources.displayMetrics, onBackProgressed = { backTransformation -> backTransformation.applyTo(targetView) }, onBackInvoked = { dismiss() }, ), ) } packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java +21 −4 Original line number Diff line number Diff line Loading @@ -45,8 +45,11 @@ import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.model.SysUiState; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.util.DialogKt; import java.util.ArrayList; import java.util.List; Loading @@ -68,6 +71,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh private static final boolean DEFAULT_DISMISS_ON_DEVICE_LOCK = true; private final Context mContext; private final FeatureFlags mFeatureFlags; @Nullable private final DismissReceiver mDismissReceiver; private final Handler mHandler = new Handler(); private final SystemUIDialogManager mDialogManager; Loading Loading @@ -96,16 +100,23 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh // TODO(b/219008720): Remove those calls to Dependency.get by introducing a // SystemUIDialogFactory and make all other dialogs create a SystemUIDialog to which we set // the content and attach listeners. this(context, theme, dismissOnDeviceLock, Dependency.get(SystemUIDialogManager.class), Dependency.get(SysUiState.class), Dependency.get(BroadcastDispatcher.class), this(context, theme, dismissOnDeviceLock, Dependency.get(FeatureFlags.class), Dependency.get(SystemUIDialogManager.class), Dependency.get(SysUiState.class), Dependency.get(BroadcastDispatcher.class), Dependency.get(DialogLaunchAnimator.class)); } public SystemUIDialog(Context context, int theme, boolean dismissOnDeviceLock, SystemUIDialogManager dialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator) { FeatureFlags featureFlags, SystemUIDialogManager dialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator) { super(context, theme); mContext = context; mFeatureFlags = featureFlags; applyFlags(this); WindowManager.LayoutParams attrs = getWindow().getAttributes(); Loading @@ -130,6 +141,12 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh for (int i = 0; i < mOnCreateRunnables.size(); i++) { mOnCreateRunnables.get(i).run(); } if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_QS_DIALOG_ANIM)) { DialogKt.registerAnimationOnBackInvoked( /* dialog = */ this, /* targetView = */ getWindow().getDecorView() ); } } private void updateWindowSize() { Loading packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt +15 −7 Original line number Diff line number Diff line Loading @@ -13,8 +13,9 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @SmallTest internal class FloatingRotationButtonPositionCalculatorTest(private val testCase: TestCase) : SysuiTestCase() { internal class FloatingRotationButtonPositionCalculatorTest( private val testCase: TestCase, ) : SysuiTestCase() { @Test fun calculatePosition() { Loading @@ -34,11 +35,18 @@ internal class FloatingRotationButtonPositionCalculatorTest(private val testCase val expectedPosition: Position ) { override fun toString(): String = "when calculator = $calculator, " + "rotation = $rotation, " + "taskbarVisible = $taskbarVisible, " + "taskbarStashed = $taskbarStashed - " + "expected $expectedPosition" buildString { append("when calculator = ") append(when (calculator) { posLeftCalculator -> "LEFT" posRightCalculator -> "RIGHT" else -> error("Unknown calculator: $calculator") }) append(", rotation = $rotation") append(", taskbarVisible = $taskbarVisible") append(", taskbarStashed = $taskbarStashed") append(" - expected $expectedPosition") } } companion object { Loading Loading
packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt +2 −35 Original line number Diff line number Diff line Loading @@ -33,13 +33,9 @@ import android.view.WindowInsets import android.view.WindowManager import android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS import android.widget.FrameLayout import android.window.OnBackInvokedDispatcher import com.android.internal.jank.InteractionJankMonitor import com.android.internal.jank.InteractionJankMonitor.CujType import com.android.systemui.animation.back.BackAnimationSpec import com.android.systemui.animation.back.applyTo import com.android.systemui.animation.back.floatingSystemSurfacesForSysUi import com.android.systemui.animation.back.onBackAnimationCallbackFrom import com.android.systemui.util.registerAnimationOnBackInvoked import java.lang.IllegalArgumentException import kotlin.math.roundToInt Loading Loading @@ -798,7 +794,7 @@ private class AnimatedDialog( if (featureFlags.isPredictiveBackQsDialogAnim) { // TODO(b/265923095) Improve animations for QS dialogs on configuration change registerOnBackInvokedCallback(targetView = dialogContentWithBackground) dialog.registerAnimationOnBackInvoked(targetView = dialogContentWithBackground) } // Show the dialog. Loading @@ -806,35 +802,6 @@ private class AnimatedDialog( moveSourceDrawingToDialog() } private fun registerOnBackInvokedCallback(targetView: View) { val metrics = targetView.resources.displayMetrics val onBackAnimationCallback = onBackAnimationCallbackFrom( backAnimationSpec = BackAnimationSpec.floatingSystemSurfacesForSysUi(metrics), displayMetrics = metrics, // TODO(b/265060720): We could remove this onBackProgressed = { backTransformation -> backTransformation.applyTo(targetView) }, onBackInvoked = { dialog.dismiss() }, ) val dispatcher = dialog.onBackInvokedDispatcher targetView.addOnAttachStateChangeListener( object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View) { dispatcher.registerOnBackInvokedCallback( OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackAnimationCallback ) } override fun onViewDetachedFromWindow(v: View) { targetView.removeOnAttachStateChangeListener(this) dispatcher.unregisterOnBackInvokedCallback(onBackAnimationCallback) } } ) } private fun moveSourceDrawingToDialog() { if (decorView.viewRootImpl == null) { // Make sure that we have access to the dialog view root to move the drawing to the Loading
packages/SystemUI/animation/src/com/android/systemui/animation/back/OnBackAnimationCallbackExtension.kt +37 −0 Original line number Diff line number Diff line Loading @@ -16,15 +16,21 @@ package com.android.systemui.animation.back import android.annotation.IntRange import android.util.DisplayMetrics import android.view.View import android.window.BackEvent import android.window.OnBackAnimationCallback import android.window.OnBackInvokedDispatcher import android.window.OnBackInvokedDispatcher.Priority /** * Generates an [OnBackAnimationCallback] given a [backAnimationSpec]. [onBackProgressed] will be * called on each update passing the current [BackTransformation]. * * Optionally, you can specify [onBackStarted], [onBackInvoked], and [onBackCancelled] callbacks. * * @sample com.android.systemui.util.registerAnimationOnBackInvoked */ fun onBackAnimationCallbackFrom( backAnimationSpec: BackAnimationSpec, Loading Loading @@ -64,3 +70,34 @@ fun onBackAnimationCallbackFrom( } } } /** * Register [OnBackAnimationCallback] when View is attached and unregister it when View is detached * * @sample com.android.systemui.util.registerAnimationOnBackInvoked */ fun View.registerOnBackInvokedCallbackOnViewAttached( onBackInvokedDispatcher: OnBackInvokedDispatcher, onBackAnimationCallback: OnBackAnimationCallback, @Priority @IntRange(from = 0) priority: Int = OnBackInvokedDispatcher.PRIORITY_DEFAULT, ) { addOnAttachStateChangeListener( object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View) { onBackInvokedDispatcher.registerOnBackInvokedCallback( priority, onBackAnimationCallback ) } override fun onViewDetachedFromWindow(v: View) { removeOnAttachStateChangeListener(this) onBackInvokedDispatcher.unregisterOnBackInvokedCallback(onBackAnimationCallback) } } ) if (isAttachedToWindow) { onBackInvokedDispatcher.registerOnBackInvokedCallback(priority, onBackAnimationCallback) } }
packages/SystemUI/animation/src/com/android/systemui/util/Dialog.kt 0 → 100644 +51 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.util import android.app.Dialog import android.view.View import android.window.OnBackInvokedDispatcher import com.android.systemui.animation.back.BackAnimationSpec import com.android.systemui.animation.back.BackTransformation import com.android.systemui.animation.back.applyTo import com.android.systemui.animation.back.floatingSystemSurfacesForSysUi import com.android.systemui.animation.back.onBackAnimationCallbackFrom import com.android.systemui.animation.back.registerOnBackInvokedCallbackOnViewAttached /** * Register on the Dialog's [OnBackInvokedDispatcher] an animation using the [BackAnimationSpec]. * The [BackTransformation] will be applied on the [targetView]. */ @JvmOverloads fun Dialog.registerAnimationOnBackInvoked( targetView: View, backAnimationSpec: BackAnimationSpec = BackAnimationSpec.floatingSystemSurfacesForSysUi( displayMetrics = targetView.resources.displayMetrics, ), ) { targetView.registerOnBackInvokedCallbackOnViewAttached( onBackInvokedDispatcher = onBackInvokedDispatcher, onBackAnimationCallback = onBackAnimationCallbackFrom( backAnimationSpec = backAnimationSpec, displayMetrics = targetView.resources.displayMetrics, onBackProgressed = { backTransformation -> backTransformation.applyTo(targetView) }, onBackInvoked = { dismiss() }, ), ) }
packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java +21 −4 Original line number Diff line number Diff line Loading @@ -45,8 +45,11 @@ import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.model.SysUiState; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.util.DialogKt; import java.util.ArrayList; import java.util.List; Loading @@ -68,6 +71,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh private static final boolean DEFAULT_DISMISS_ON_DEVICE_LOCK = true; private final Context mContext; private final FeatureFlags mFeatureFlags; @Nullable private final DismissReceiver mDismissReceiver; private final Handler mHandler = new Handler(); private final SystemUIDialogManager mDialogManager; Loading Loading @@ -96,16 +100,23 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh // TODO(b/219008720): Remove those calls to Dependency.get by introducing a // SystemUIDialogFactory and make all other dialogs create a SystemUIDialog to which we set // the content and attach listeners. this(context, theme, dismissOnDeviceLock, Dependency.get(SystemUIDialogManager.class), Dependency.get(SysUiState.class), Dependency.get(BroadcastDispatcher.class), this(context, theme, dismissOnDeviceLock, Dependency.get(FeatureFlags.class), Dependency.get(SystemUIDialogManager.class), Dependency.get(SysUiState.class), Dependency.get(BroadcastDispatcher.class), Dependency.get(DialogLaunchAnimator.class)); } public SystemUIDialog(Context context, int theme, boolean dismissOnDeviceLock, SystemUIDialogManager dialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator) { FeatureFlags featureFlags, SystemUIDialogManager dialogManager, SysUiState sysUiState, BroadcastDispatcher broadcastDispatcher, DialogLaunchAnimator dialogLaunchAnimator) { super(context, theme); mContext = context; mFeatureFlags = featureFlags; applyFlags(this); WindowManager.LayoutParams attrs = getWindow().getAttributes(); Loading @@ -130,6 +141,12 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh for (int i = 0; i < mOnCreateRunnables.size(); i++) { mOnCreateRunnables.get(i).run(); } if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_QS_DIALOG_ANIM)) { DialogKt.registerAnimationOnBackInvoked( /* dialog = */ this, /* targetView = */ getWindow().getDecorView() ); } } private void updateWindowSize() { Loading
packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt +15 −7 Original line number Diff line number Diff line Loading @@ -13,8 +13,9 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @SmallTest internal class FloatingRotationButtonPositionCalculatorTest(private val testCase: TestCase) : SysuiTestCase() { internal class FloatingRotationButtonPositionCalculatorTest( private val testCase: TestCase, ) : SysuiTestCase() { @Test fun calculatePosition() { Loading @@ -34,11 +35,18 @@ internal class FloatingRotationButtonPositionCalculatorTest(private val testCase val expectedPosition: Position ) { override fun toString(): String = "when calculator = $calculator, " + "rotation = $rotation, " + "taskbarVisible = $taskbarVisible, " + "taskbarStashed = $taskbarStashed - " + "expected $expectedPosition" buildString { append("when calculator = ") append(when (calculator) { posLeftCalculator -> "LEFT" posRightCalculator -> "RIGHT" else -> error("Unknown calculator: $calculator") }) append(", rotation = $rotation") append(", taskbarVisible = $taskbarVisible") append(", taskbarStashed = $taskbarStashed") append(" - expected $expectedPosition") } } companion object { Loading