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

Commit 581429b3 authored by Shan Huang's avatar Shan Huang
Browse files

Launcher side implementation of gesture seekable back to home animation.

This is a two part animation. The first part is an animation that tracks gesture location to scale and move the leaving app window. Once the gesture is committed, the second part takes over the app window and plays the rest of app close transitions in one go.

This animation is used only for apps that enable back dispatching via {@link android.view.OnBackInvokedDispatcher}. The controller registers an {@link IOnBackInvokedCallback} with WM Shell and receives back dispatches when a back navigation to launcher starts.

Apps using the legacy back dispatching will keep triggering the WALLPAPER_OPEN remote transition registered in {@link QuickstepTransitionManager}.

Bug: b/195946584
Test: m -j
Test: Swipe back to home on pre-T and T apps, at different life cycle
stages.

Change-Id: I615c5171cd875130f10346fa3ca2a8e9670176cf
parent 968c3256
Loading
Loading
Loading
Loading
+112 −81
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ import com.android.launcher3.util.Themes;
import com.android.launcher3.views.FloatingIconView;
import com.android.launcher3.views.ScrimView;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.quickstep.LauncherBackAnimationController;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskViewUtils;
@@ -213,6 +214,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
    private RemoteAnimationFactory mWallpaperOpenTransitionRunner;
    private RemoteTransitionCompat mLauncherOpenTransition;

    private LauncherBackAnimationController mBackAnimationController;
    private final AnimatorListenerAdapter mForceInvisibleListener = new AnimatorListenerAdapter() {
        @Override
        public void onAnimationStart(Animator animation) {
@@ -238,6 +240,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
        mDragLayerAlpha = mDragLayer.getAlphaProperty(ALPHA_INDEX_TRANSITIONS);
        mHandler = new Handler(Looper.getMainLooper());
        mDeviceProfile = mLauncher.getDeviceProfile();
        mBackAnimationController = new LauncherBackAnimationController(
                mDeviceProfile, mLauncher, this);

        Resources res = mLauncher.getResources();
        mContentScale = res.getFloat(R.dimen.content_scale);
@@ -1136,6 +1140,9 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
            mLauncherOpenTransition.addHomeOpenCheck(mLauncher.getComponentName());
            SystemUiProxy.INSTANCE.getNoCreate().registerRemoteTransition(mLauncherOpenTransition);
        }
        if (mBackAnimationController != null) {
            mBackAnimationController.registerBackCallbacks(mHandler);
        }
    }

    public void onActivityDestroyed() {
@@ -1171,6 +1178,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
            mLauncherOpenTransition = null;
            mWallpaperOpenTransitionRunner = null;
        }
        if (mBackAnimationController != null) {
            mBackAnimationController.unregisterBackCallbacks();
            mBackAnimationController = null;
        }
    }

    private boolean launcherIsATargetWithMode(RemoteAnimationTargetCompat[] targets, int mode) {
@@ -1323,8 +1334,9 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
    /**
     * Closing animator that animates the window into its final location on the workspace.
     */
    private void getClosingWindowAnimators(AnimatorSet animation,
            RemoteAnimationTargetCompat[] targets, View launcherView, PointF velocityPxPerS) {
    private RectFSpringAnim getClosingWindowAnimators(AnimatorSet animation,
            RemoteAnimationTargetCompat[] targets, View launcherView, PointF velocityPxPerS,
            RectF closingWindowStartRect) {
        FloatingIconView floatingIconView = null;
        FloatingWidgetView floatingWidget = null;
        RectF targetRect = new RectF();
@@ -1356,8 +1368,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
            targetRect.set(getDefaultWindowTargetRect());
        }

        final RectF startRect = new RectF(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx);
        RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mLauncher,
        RectFSpringAnim anim = new RectFSpringAnim(closingWindowStartRect, targetRect, mLauncher,
                mDeviceProfile);

        // Hook up floating views to the closing window animators.
@@ -1415,6 +1426,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
                anim.start(mLauncher, velocityPxPerS);
            }
        });
        return anim;
    }

    /**
@@ -1539,46 +1551,17 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
    }

    /**
     * Remote animation runner for animation from the app to Launcher, including recents.
     * Creates the {@link RectFSpringAnim} and {@link AnimatorSet} required to animate
     * the transition.
     */
    protected class WallpaperOpenLauncherAnimationRunner implements RemoteAnimationFactory {

        private final Handler mHandler;
        private final boolean mFromUnlock;

        public WallpaperOpenLauncherAnimationRunner(Handler handler, boolean fromUnlock) {
            mHandler = handler;
            mFromUnlock = fromUnlock;
        }

        @Override
        public void onCreateAnimation(int transit,
    public Pair<RectFSpringAnim, AnimatorSet> createWallpaperOpenAnimations(
            RemoteAnimationTargetCompat[] appTargets,
            RemoteAnimationTargetCompat[] wallpaperTargets,
                RemoteAnimationTargetCompat[] nonAppTargets,
                LauncherAnimationRunner.AnimationResult result) {
            if (mLauncher.isDestroyed()) {
                AnimatorSet anim = new AnimatorSet();
                anim.play(getFallbackClosingWindowAnimators(appTargets));
                result.setAnimation(anim, mLauncher.getApplicationContext());
                return;
            }

            if (!mLauncher.hasBeenResumed()) {
                // If launcher is not resumed, wait until new async-frame after resume
                mLauncher.addOnResumeCallback(() ->
                        postAsyncCallback(mHandler, () ->
                                onCreateAnimation(transit, appTargets, wallpaperTargets,
                                        nonAppTargets, result)));
                return;
            }

            if (mLauncher.hasSomeInvisibleFlag(PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION)) {
                mLauncher.addForceInvisibleFlag(INVISIBLE_BY_PENDING_FLAGS);
                mLauncher.getStateManager().moveToRestState();
            }

            boolean fromUnlock,
            RectF startRect) {
        AnimatorSet anim = null;
        RectFSpringAnim rectFSpringAnim = null;

        RemoteAnimationProvider provider = mRemoteAnimationProvider;
        if (provider != null) {
            anim = provider.createWindowAnimation(appTargets, wallpaperTargets);
@@ -1598,7 +1581,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener

            boolean playWorkspaceReveal = true;
            boolean skipAllAppsScale = false;
                if (mFromUnlock) {
            if (fromUnlock) {
                anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
            } else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get()
                    && !playFallBackAnimation) {
@@ -1606,7 +1589,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
                float velocityPxPerS = DynamicResource.provider(mLauncher)
                        .getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
                PointF velocity = new PointF(0, -velocityPxPerS);
                    getClosingWindowAnimators(anim, appTargets, launcherView, velocity);
                rectFSpringAnim = getClosingWindowAnimators(
                        anim, appTargets, launcherView, velocity, startRect);
                if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
                    anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
                            true /* animateOverviewScrim */, launcherView).getAnimators());
@@ -1654,8 +1638,55 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
            }
        }

        return new Pair(rectFSpringAnim, anim);
    }

    /**
     * Remote animation runner for animation from the app to Launcher, including recents.
     */
    protected class WallpaperOpenLauncherAnimationRunner implements RemoteAnimationFactory {

        private final Handler mHandler;
        private final boolean mFromUnlock;

        public WallpaperOpenLauncherAnimationRunner(Handler handler, boolean fromUnlock) {
            mHandler = handler;
            mFromUnlock = fromUnlock;
        }

        @Override
        public void onCreateAnimation(int transit,
                RemoteAnimationTargetCompat[] appTargets,
                RemoteAnimationTargetCompat[] wallpaperTargets,
                RemoteAnimationTargetCompat[] nonAppTargets,
                LauncherAnimationRunner.AnimationResult result) {
            if (mLauncher.isDestroyed()) {
                AnimatorSet anim = new AnimatorSet();
                anim.play(getFallbackClosingWindowAnimators(appTargets));
                result.setAnimation(anim, mLauncher.getApplicationContext());
                return;
            }

            if (!mLauncher.hasBeenResumed()) {
                // If launcher is not resumed, wait until new async-frame after resume
                mLauncher.addOnResumeCallback(() ->
                        postAsyncCallback(mHandler, () ->
                                onCreateAnimation(transit, appTargets, wallpaperTargets,
                                        nonAppTargets, result)));
                return;
            }

            if (mLauncher.hasSomeInvisibleFlag(PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION)) {
                mLauncher.addForceInvisibleFlag(INVISIBLE_BY_PENDING_FLAGS);
                mLauncher.getStateManager().moveToRestState();
            }

            Pair<RectFSpringAnim, AnimatorSet> pair = createWallpaperOpenAnimations(
                    appTargets, wallpaperTargets, mFromUnlock,
                    new RectF(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx));

            mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
            result.setAnimation(anim, mLauncher);
            result.setAnimation(pair.second, mLauncher);
        }
    }

+308 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.quickstep;

import static com.android.launcher3.BaseActivity.INVISIBLE_ALL;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_PENDING_FLAGS;
import static com.android.launcher3.BaseActivity.PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
import android.util.Log;
import android.util.MathUtils;
import android.util.Pair;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.window.BackEvent;
import android.window.IOnBackInvokedCallback;

import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
/**
 * Controls the animation of swiping back and returning to launcher.
 *
 * This is a two part animation. The first part is an animation that tracks gesture location to
 * scale and move the leaving app window. Once the gesture is committed, the second part takes over
 * the app window and plays the rest of app close transitions in one go.
 *
 * This animation is used only for apps that enable back dispatching via
 * {@link android.view.OnBackInvokedDispatcher}. The controller registers
 * an {@link IOnBackInvokedCallback} with WM Shell and receives back dispatches when a back
 * navigation to launcher starts.
 *
 * Apps using the legacy back dispatching will keep triggering the WALLPAPER_OPEN remote
 * transition registered in {@link QuickstepTransitionManager}.
 *
 */
public class LauncherBackAnimationController {
    private static final int CANCEL_TRANSITION_DURATION = 150;
    private static final String TAG = "LauncherBackAnimationController";
    private final DeviceProfile mDeviceProfile;
    private final QuickstepTransitionManager mQuickstepTransitionManager;
    private final Matrix mTransformMatrix = new Matrix();
    private final RectF mTargetRectF = new RectF();
    private final RectF mStartRectF = new RectF();
    private final RectF mCurrentRect = new RectF();
    private final BaseQuickstepLauncher mLauncher;
    private final int mWindowScaleMarginX;
    private final int mWindowScaleMarginY;
    private final float mWindowScaleEndCornerRadius;
    private final float mWindowScaleStartCornerRadius;

    private RemoteAnimationTargetCompat mBackTarget;
    private SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
    private boolean mSpringAnimationInProgress = false;
    private boolean mAnimatorSetInProgress = false;
    @BackEvent.SwipeEdge
    private int mSwipeEdge;
    private float mBackProgress = 0;
    private boolean mBackInProgress = false;

    public LauncherBackAnimationController(
            DeviceProfile deviceProfile,
            BaseQuickstepLauncher launcher,
            QuickstepTransitionManager quickstepTransitionManager) {
        mDeviceProfile = deviceProfile;
        mLauncher = launcher;
        mQuickstepTransitionManager = quickstepTransitionManager;
        mWindowScaleEndCornerRadius = QuickStepContract.supportsRoundedCornersOnWindows(
                mLauncher.getResources())
                ? mLauncher.getResources().getDimensionPixelSize(
                        R.dimen.swipe_back_window_corner_radius)
                : 0;
        mWindowScaleStartCornerRadius = QuickStepContract.getWindowCornerRadius(mLauncher);
        mWindowScaleMarginX = mLauncher.getResources().getDimensionPixelSize(
                R.dimen.swipe_back_window_scale_x_margin);
        mWindowScaleMarginY = mLauncher.getResources().getDimensionPixelSize(
                R.dimen.swipe_back_window_scale_y_margin);
    }

    /**
     * Registers {@link IOnBackInvokedCallback} to receive back dispatches from shell.
     * @param handler Handler to the thread to run the animations on.
     */
    public void registerBackCallbacks(Handler handler) {
        SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate();
        if (systemUiProxy == null) {
            Log.e(TAG, "SystemUiProxy is null. Skip registering back invocation callbacks");
            return;
        }
        systemUiProxy.setBackToLauncherCallback(
                new IOnBackInvokedCallback.Stub() {
                    @Override
                    public void onBackCancelled() {
                        handler.post(() -> resetPositionAnimated());
                    }

                    @Override
                    public void onBackInvoked() {
                        handler.post(() -> startTransition());
                    }

                    @Override
                    public void onBackProgressed(BackEvent backEvent) {
                        mBackProgress = backEvent.getProgress();
                        // TODO: Update once the interpolation curve spec is finalized.
                        mBackProgress =
                                1 - (1 - mBackProgress) * (1 - mBackProgress) * (1
                                        - mBackProgress);
                        if (!mBackInProgress) {
                            startBack(backEvent);
                        } else {
                            updateBackProgress(mBackProgress);
                        }
                    }

                    public void onBackStarted() { }
                });
    }

    private void resetPositionAnimated() {
        ValueAnimator cancelAnimator = ValueAnimator.ofFloat(mBackProgress, 0);
        cancelAnimator.setDuration(CANCEL_TRANSITION_DURATION);
        cancelAnimator.addUpdateListener(
                animation -> {
                    updateBackProgress((float) animation.getAnimatedValue());
                });
        cancelAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                finishAnimation();
            }
        });
        cancelAnimator.start();
    }

    /** Unregisters the back to launcher callback in shell. */
    public void unregisterBackCallbacks() {
        SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate();
        if (systemUiProxy != null) {
            systemUiProxy.clearBackToLauncherCallback();
        }
    }

    private void startBack(BackEvent backEvent) {
        mBackInProgress = true;
        RemoteAnimationTarget appTarget = backEvent.getDepartingAnimationTarget();

        if (appTarget == null) {
            return;
        }

        mTransaction.show(appTarget.leash).apply();
        mTransaction.setAnimationTransaction();
        mBackTarget = new RemoteAnimationTargetCompat(appTarget);
        mSwipeEdge = backEvent.getSwipeEdge();
        float screenWidth = mDeviceProfile.widthPx;
        float screenHeight = mDeviceProfile.heightPx;
        float targetHeight = screenHeight - 2 * mWindowScaleMarginY;
        float targetWidth = targetHeight * screenWidth / screenHeight;
        float left;
        if (mSwipeEdge == BackEvent.EDGE_LEFT) {
            left = screenWidth - targetWidth - mWindowScaleMarginX;
        } else {
            left = mWindowScaleMarginX;
        }
        float top = mWindowScaleMarginY;
        // TODO(b/218916755): Offset start rectangle in multiwindow mode.
        mStartRectF.set(0, 0, screenWidth, screenHeight);
        mTargetRectF.set(left, top, targetWidth + left, targetHeight + top);
    }

    private void updateBackProgress(float progress) {
        if (mBackTarget == null) {
            return;
        }

        mCurrentRect.set(
                MathUtils.lerp(mStartRectF.left, mTargetRectF.left, progress),
                MathUtils.lerp(mStartRectF.top, mTargetRectF.top, progress),
                MathUtils.lerp(mStartRectF.right, mTargetRectF.right, progress),
                MathUtils.lerp(mStartRectF.bottom, mTargetRectF.bottom, progress));
        SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder builder =
                new SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder(mBackTarget.leash);

        Rect currentRect = new Rect();
        mCurrentRect.round(currentRect);

        // Scale the target window to match the currentRectF.
        final float scale = mCurrentRect.width() / mStartRectF.width();
        mTransformMatrix.reset();
        mTransformMatrix.setScale(scale, scale);
        mTransformMatrix.postTranslate(mCurrentRect.left, mCurrentRect.top);
        Rect startRect = new Rect();
        mStartRectF.round(startRect);
        float cornerRadius = Utilities.mapRange(
                progress, mWindowScaleStartCornerRadius, mWindowScaleEndCornerRadius);
        builder.withMatrix(mTransformMatrix)
                .withWindowCrop(startRect)
                .withCornerRadius(cornerRadius);
        SyncRtSurfaceTransactionApplierCompat.SurfaceParams surfaceParams = builder.build();

        if (surfaceParams.surface.isValid()) {
            surfaceParams.applyTo(mTransaction);
        }
        mTransaction.apply();
    }

    private void startTransition() {
        if (mBackTarget == null) {
            // Trigger transition system instead of custom transition animation.
            finishAnimation();
            return;
        }
        if (mLauncher.isDestroyed()) {
            return;
        }
        // TODO: Catch the moment when launcher becomes visible after the top app un-occludes
        //  launcher and start animating afterwards. Currently we occasionally get a flicker from
        //  animating when launcher is still invisible.
        if (mLauncher.hasSomeInvisibleFlag(PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION)) {
            mLauncher.addForceInvisibleFlag(INVISIBLE_BY_PENDING_FLAGS);
            mLauncher.getStateManager().moveToRestState();
        }

        Pair<RectFSpringAnim, AnimatorSet> pair =
                mQuickstepTransitionManager.createWallpaperOpenAnimations(
                    new RemoteAnimationTargetCompat[]{mBackTarget},
                    new RemoteAnimationTargetCompat[]{},
                    false /* fromUnlock */,
                    mCurrentRect);
        startTransitionAnimations(pair.first, pair.second);
        mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
    }

    private void finishAnimation() {
        mBackTarget = null;
        mBackInProgress = false;
        mBackProgress = 0;
        mSwipeEdge = BackEvent.EDGE_LEFT;
        mTransformMatrix.reset();
        mTargetRectF.setEmpty();
        mCurrentRect.setEmpty();
        mStartRectF.setEmpty();
        mAnimatorSetInProgress = false;
        mSpringAnimationInProgress = false;
        SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate();
        if (systemUiProxy != null) {
            SystemUiProxy.INSTANCE.getNoCreate().onBackToLauncherAnimationFinished();
        }
    }

    private void startTransitionAnimations(RectFSpringAnim springAnim, AnimatorSet anim) {
        mAnimatorSetInProgress = anim != null;
        mSpringAnimationInProgress = springAnim != null;
        if (springAnim != null) {
            springAnim.addAnimatorListener(
                    new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            mSpringAnimationInProgress = false;
                            tryFinishBackAnimation();
                        }
                    }
            );
        }
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mAnimatorSetInProgress = false;
                tryFinishBackAnimation();
            }
        });
        anim.start();
    }

    private void tryFinishBackAnimation() {
        if (!mSpringAnimationInProgress && !mAnimatorSetInProgress) {
            finishAnimation();
        }
    }
}
+54 −3

File changed.

Preview size limit exceeded, changes collapsed.

+5 −1
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.quickstep.GestureState.DEFAULT_STATE;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_RECENT_TASKS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_BACK_ANIMATION;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_ONE_HANDED;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_PIP;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
@@ -106,6 +107,7 @@ import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.wm.shell.back.IBackAnimation;
import com.android.wm.shell.onehanded.IOneHanded;
import com.android.wm.shell.pip.IPip;
import com.android.wm.shell.recents.IRecentTasks;
@@ -166,10 +168,12 @@ public class TouchInteractionService extends Service
                            bundle.getBinder(KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER));
            IRecentTasks recentTasks = IRecentTasks.Stub.asInterface(
                    bundle.getBinder(KEY_EXTRA_RECENT_TASKS));
            IBackAnimation backAnimation = IBackAnimation.Stub.asInterface(
                    bundle.getBinder(KEY_EXTRA_SHELL_BACK_ANIMATION));
            MAIN_EXECUTOR.execute(() -> {
                SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip,
                        splitscreen, onehanded, shellTransitions, startingWindow, recentTasks,
                        launcherUnlockAnimationController);
                        launcherUnlockAnimationController, backAnimation);
                TouchInteractionService.this.initInputMonitor();
                preloadOverview(true /* fromInit */);
            });
+4 −0
Original line number Diff line number Diff line
@@ -166,4 +166,8 @@
    <!-- Name of the class used to generate colors from the wallpaper colors. Must be implementing the LauncherAppWidgetHostView.ColorGenerator interface. -->
    <string name="color_generator_class" translatable="false"/>

    <!-- Swipe back to home related -->
    <dimen name="swipe_back_window_scale_x_margin">10dp</dimen>
    <dimen name="swipe_back_window_scale_y_margin">80dp</dimen>
    <dimen name="swipe_back_window_corner_radius">40dp</dimen>
</resources>