Merge "Launcher side implementation of gesture seekable back to home animation." into tm-dev

This commit is contained in:
TreeHugger Robot
2022-03-11 02:11:03 +00:00
committed by Android (Google) Code Review
5 changed files with 483 additions and 85 deletions
@@ -111,6 +111,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;
@@ -216,6 +217,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) {
@@ -241,6 +243,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);
@@ -1159,6 +1163,9 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
mLauncherOpenTransition.addHomeOpenCheck(mLauncher.getComponentName());
SystemUiProxy.INSTANCE.getNoCreate().registerRemoteTransition(mLauncherOpenTransition);
}
if (mBackAnimationController != null) {
mBackAnimationController.registerBackCallbacks(mHandler);
}
}
public void onActivityDestroyed() {
@@ -1194,6 +1201,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
mLauncherOpenTransition = null;
mWallpaperOpenTransitionRunner = null;
}
if (mBackAnimationController != null) {
mBackAnimationController.unregisterBackCallbacks();
mBackAnimationController = null;
}
}
private boolean launcherIsATargetWithMode(RemoteAnimationTargetCompat[] targets, int mode) {
@@ -1346,8 +1357,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();
@@ -1379,8 +1391,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.
@@ -1414,7 +1425,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
final float floatingWidgetAlpha = isTransluscent ? 0 : 1;
FloatingWidgetView finalFloatingWidget = floatingWidget;
RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect,
RectFSpringAnim.OnUpdateListener runner = new SpringAnimRunner(targets, targetRect,
windowTargetBounds) {
@Override
public void onUpdate(RectF currentRectF, float progress) {
@@ -1438,6 +1449,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
anim.start(mLauncher, velocityPxPerS);
}
});
return anim;
}
/**
@@ -1561,6 +1573,97 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
});
}
/**
* Creates the {@link RectFSpringAnim} and {@link AnimatorSet} required to animate
* the transition.
*/
public Pair<RectFSpringAnim, AnimatorSet> createWallpaperOpenAnimations(
RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets,
boolean fromUnlock,
RectF startRect) {
AnimatorSet anim = null;
RectFSpringAnim rectFSpringAnim = null;
RemoteAnimationProvider provider = mRemoteAnimationProvider;
if (provider != null) {
anim = provider.createWindowAnimation(appTargets, wallpaperTargets);
}
if (anim == null) {
anim = new AnimatorSet();
final boolean launcherIsForceInvisibleOrOpening = mLauncher.isForceInvisible()
|| launcherIsATargetWithMode(appTargets, MODE_OPENING);
View launcherView = findLauncherView(appTargets);
boolean playFallBackAnimation = (launcherView == null
&& launcherIsForceInvisibleOrOpening)
|| mLauncher.getWorkspace().isOverlayShown()
|| hasMultipleTargetsWithMode(appTargets, MODE_CLOSING);
boolean playWorkspaceReveal = true;
boolean skipAllAppsScale = false;
if (fromUnlock) {
anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
} else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get()
&& !playFallBackAnimation) {
// Use a fixed velocity to start the animation.
float velocityPxPerS = DynamicResource.provider(mLauncher)
.getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
PointF velocity = new PointF(0, -velocityPxPerS);
rectFSpringAnim = getClosingWindowAnimators(
anim, appTargets, launcherView, velocity, startRect);
if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
true /* animateOverviewScrim */, launcherView).getAnimators());
// We play StaggeredWorkspaceAnim as a part of the closing window animation.
playWorkspaceReveal = false;
} else {
// Skip scaling all apps, otherwise FloatingIconView will get wrong
// layout bounds.
skipAllAppsScale = true;
}
} else {
anim.play(getFallbackClosingWindowAnimators(appTargets));
}
// Normally, we run the launcher content animation when we are transitioning
// home, but if home is already visible, then we don't want to animate the
// contents of launcher unless we know that we are animating home as a result
// of the home button press with quickstep, which will result in launcher being
// started on touch down, prior to the animation home (and won't be in the
// targets list because it is already visible). In that case, we force
// invisibility on touch down, and only reset it after the animation to home
// is initialized.
if (launcherIsForceInvisibleOrOpening) {
addCujInstrumentation(
anim, InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
// Only register the content animation for cancellation when state changes
mLauncher.getStateManager().setCurrentAnimation(anim);
if (mLauncher.isInState(LauncherState.ALL_APPS)) {
Pair<AnimatorSet, Runnable> contentAnimator =
getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY,
skipAllAppsScale);
anim.play(contentAnimator.first);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
contentAnimator.second.run();
}
});
} else {
if (playWorkspaceReveal) {
anim.play(new WorkspaceRevealAnim(mLauncher, false).getAnimators());
}
}
}
}
return new Pair(rectFSpringAnim, anim);
}
/**
* Remote animation runner for animation from the app to Launcher, including recents.
*/
@@ -1601,84 +1704,12 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
mLauncher.getStateManager().moveToRestState();
}
AnimatorSet anim = null;
RemoteAnimationProvider provider = mRemoteAnimationProvider;
if (provider != null) {
anim = provider.createWindowAnimation(appTargets, wallpaperTargets);
}
if (anim == null) {
anim = new AnimatorSet();
final boolean launcherIsForceInvisibleOrOpening = mLauncher.isForceInvisible()
|| launcherIsATargetWithMode(appTargets, MODE_OPENING);
View launcherView = findLauncherView(appTargets);
boolean playFallBackAnimation = (launcherView == null
&& launcherIsForceInvisibleOrOpening)
|| mLauncher.getWorkspace().isOverlayShown()
|| hasMultipleTargetsWithMode(appTargets, MODE_CLOSING);
boolean playWorkspaceReveal = true;
boolean skipAllAppsScale = false;
if (mFromUnlock) {
anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
} else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get()
&& !playFallBackAnimation) {
// Use a fixed velocity to start the animation.
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);
if (!mLauncher.isInState(LauncherState.ALL_APPS)) {
anim.play(new StaggeredWorkspaceAnim(mLauncher, velocity.y,
true /* animateOverviewScrim */, launcherView).getAnimators());
// We play StaggeredWorkspaceAnim as a part of the closing window animation.
playWorkspaceReveal = false;
} else {
// Skip scaling all apps, otherwise FloatingIconView will get wrong
// layout bounds.
skipAllAppsScale = true;
}
} else {
anim.play(getFallbackClosingWindowAnimators(appTargets));
}
// Normally, we run the launcher content animation when we are transitioning
// home, but if home is already visible, then we don't want to animate the
// contents of launcher unless we know that we are animating home as a result
// of the home button press with quickstep, which will result in launcher being
// started on touch down, prior to the animation home (and won't be in the
// targets list because it is already visible). In that case, we force
// invisibility on touch down, and only reset it after the animation to home
// is initialized.
if (launcherIsForceInvisibleOrOpening) {
addCujInstrumentation(
anim, InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME);
// Only register the content animation for cancellation when state changes
mLauncher.getStateManager().setCurrentAnimation(anim);
if (mLauncher.isInState(LauncherState.ALL_APPS)) {
Pair<AnimatorSet, Runnable> contentAnimator =
getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY,
skipAllAppsScale);
anim.play(contentAnimator.first);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
contentAnimator.second.run();
}
});
} else {
if (playWorkspaceReveal) {
anim.play(new WorkspaceRevealAnim(mLauncher, false).getAnimators());
}
}
}
}
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);
}
}
@@ -0,0 +1,308 @@
/*
* 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();
}
}
}
@@ -39,6 +39,7 @@ import android.view.MotionEvent;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.window.IOnBackInvokedCallback;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
@@ -50,6 +51,7 @@ import com.android.systemui.shared.system.RemoteTransitionCompat;
import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController;
import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
import com.android.systemui.shared.system.smartspace.SmartspaceState;
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.pip.IPipAnimationListener;
@@ -82,6 +84,7 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI
private IShellTransitions mShellTransitions;
private IStartingWindow mStartingWindow;
private IRecentTasks mRecentTasks;
private IBackAnimation mBackAnimation;
private final DeathRecipient mSystemUiProxyDeathRecipient = () -> {
MAIN_EXECUTOR.execute(() -> clearProxy());
};
@@ -96,6 +99,7 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI
private ILauncherUnlockAnimationController mPendingLauncherUnlockAnimationController;
private IRecentTasksListener mRecentTasksListener;
private final ArrayList<RemoteTransitionCompat> mRemoteTransitions = new ArrayList<>();
private IOnBackInvokedCallback mBackToLaunchCallback;
// Used to dedupe calls to SystemUI
private int mLastShelfHeight;
@@ -162,8 +166,8 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI
public void setProxy(ISystemUiProxy proxy, IPip pip, ISplitScreen splitScreen,
IOneHanded oneHanded, IShellTransitions shellTransitions,
IStartingWindow startingWindow, IRecentTasks recentTasks,
ISysuiUnlockAnimationController sysuiUnlockAnimationController) {
ISysuiUnlockAnimationController sysuiUnlockAnimationController,
IBackAnimation backAnimation) {
unlinkToDeath();
mSystemUiProxy = proxy;
mPip = pip;
@@ -173,6 +177,7 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI
mStartingWindow = startingWindow;
mSysuiUnlockAnimationController = sysuiUnlockAnimationController;
mRecentTasks = recentTasks;
mBackAnimation = backAnimation;
linkToDeath();
// re-attach the listeners once missing due to setProxy has not been initialized yet.
if (mPipAnimationListener != null && mPip != null) {
@@ -195,6 +200,9 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI
if (mRecentTasksListener != null && mRecentTasks != null) {
registerRecentTasksListener(mRecentTasksListener);
}
if (mBackAnimation != null && mBackToLaunchCallback != null) {
setBackToLauncherCallback(mBackToLaunchCallback);
}
if (mPendingSetNavButtonAlpha != null) {
mPendingSetNavButtonAlpha.run();
@@ -203,7 +211,7 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI
}
public void clearProxy() {
setProxy(null, null, null, null, null, null, null, null);
setProxy(null, null, null, null, null, null, null, null, null);
}
// TODO(141886704): Find a way to remove this
@@ -822,6 +830,49 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI
mRecentTasksListener = null;
}
//
// Back navigation transitions
//
/** Sets the launcher {@link android.window.IOnBackInvokedCallback} to shell */
public void setBackToLauncherCallback(IOnBackInvokedCallback callback) {
mBackToLaunchCallback = callback;
if (mBackAnimation == null) {
return;
}
try {
mBackAnimation.setBackToLauncherCallback(callback);
} catch (RemoteException e) {
Log.e(TAG, "Failed call setBackToLauncherCallback", e);
}
}
/** Clears the previously registered {@link IOnBackInvokedCallback}. */
public void clearBackToLauncherCallback() {
if (mBackAnimation == null) {
return;
}
try {
mBackAnimation.clearBackToLauncherCallback();
} catch (RemoteException e) {
Log.e(TAG, "Failed call clearBackToLauncherCallback", e);
}
}
/**
* Notifies shell that all back to launcher animations have finished (including the transition
* that plays after the gesture is committed and before the app is closed.
*/
public void onBackToLauncherAnimationFinished() {
if (mBackAnimation != null) {
try {
mBackAnimation.onBackToLauncherAnimationFinished();
} catch (RemoteException e) {
Log.w(TAG, "Failed call onBackAnimationFinished", e);
}
}
}
public ArrayList<GroupedRecentTaskInfo> getRecentTasks(int numTasks, int userId) {
if (mRecentTasks != null) {
try {
@@ -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
View File
@@ -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>