Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0ae961f authored by Omar Miatello's avatar Omar Miatello Committed by Automerger Merge Worker
Browse files

Merge "Add Predictive Back animation to all SysUI dialogs" into tm-qpr-dev am:...

Merge "Add Predictive Back animation to all SysUI dialogs" into tm-qpr-dev am: f5834024 am: e17675d2

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



Change-Id: I8d10439e5fcbfe6f36d3b4d8f2283db0c9b938b3
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 8a8a6840 e17675d2
Loading
Loading
Loading
Loading
+2 −35
Original line number Diff line number Diff line
@@ -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

@@ -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.
@@ -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
+37 −0
Original line number Diff line number Diff line
@@ -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,
@@ -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)
    }
}
+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() },
            ),
    )
}
+21 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -92,16 +96,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();
@@ -126,6 +137,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() {
+15 −7
Original line number Diff line number Diff line
@@ -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() {
@@ -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