diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar index 53a6ceb4d0..308e92f666 100644 Binary files a/quickstep/libs/sysui_shared.jar and b/quickstep/libs/sysui_shared.jar differ diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index 2630edb3d2..0674c61196 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -72,6 +72,7 @@ import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.RemoteAnimationProvider; +import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.system.ActivityCompat; @@ -80,7 +81,8 @@ import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; import com.android.systemui.shared.system.RemoteAnimationDefinitionCompat; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; -import com.android.systemui.shared.system.TransactionCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier.SurfaceParams; import com.android.systemui.shared.system.WindowManagerWrapper; /** @@ -558,22 +560,21 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag Rect crop = new Rect(); Matrix matrix = new Matrix(); + RemoteAnimationTargetSet openingTargets = new RemoteAnimationTargetSet(targets, + MODE_OPENING); + RemoteAnimationTargetSet closingTargets = new RemoteAnimationTargetSet(targets, + MODE_CLOSING); + SyncRtSurfaceTransactionApplier surfaceApplier = new SyncRtSurfaceTransactionApplier( + mFloatingView); + ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); appAnimator.setDuration(APP_LAUNCH_DURATION); appAnimator.addUpdateListener(new MultiValueUpdateListener() { // Fade alpha for the app window. FloatProp mAlpha = new FloatProp(0f, 1f, 0, 60, LINEAR); - boolean isFirstFrame = true; @Override public void onUpdate(float percent) { - final Surface surface = getSurface(mFloatingView); - final long frameNumber = surface != null ? getNextFrameNumber(surface) : -1; - if (frameNumber == -1) { - // Booo, not cool! Our surface got destroyed, so no reason to animate anything. - Log.w(TAG, "Failed to animate, surface got destroyed."); - return; - } final float easePercent = AGGRESSIVE_EASE.getInterpolation(percent); // Calculate app icon size. @@ -584,7 +585,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag float scaleX = iconWidth / windowTargetBounds.width(); float scaleY = iconHeight / windowTargetBounds.height(); float scale = Math.min(1f, Math.min(scaleX, scaleY)); - matrix.setScale(scale, scale); // Position the scaled window on top of the icon int windowWidth = windowTargetBounds.width(); @@ -598,7 +598,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag float transX0 = floatingViewBounds[0] - offsetX; float transY0 = floatingViewBounds[1] - offsetY; - matrix.postTranslate(transX0, transY0); // Animate the window crop so that it starts off as a square, and then reveals // horizontally. @@ -609,23 +608,27 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag crop.right = windowWidth; crop.bottom = (int) (crop.top + cropHeight); - TransactionCompat t = new TransactionCompat(); - if (isFirstFrame) { - RemoteAnimationProvider.prepareTargetsForFirstFrame(targets, t, MODE_OPENING); - isFirstFrame = false; - } - for (RemoteAnimationTargetCompat target : targets) { - if (target.mode == MODE_OPENING) { - t.setAlpha(target.leash, mAlpha.value); - t.setMatrix(target.leash, matrix); - t.setWindowCrop(target.leash, crop); - t.deferTransactionUntil(target.leash, surface, getNextFrameNumber(surface)); - } - } - t.setEarlyWakeup(); - t.apply(); + SurfaceParams[] params = new SurfaceParams[targets.length]; + for (int i = targets.length - 1; i >= 0; i--) { + RemoteAnimationTargetCompat target = targets[i]; - matrix.reset(); + Rect targetCrop; + float alpha; + if (target.mode == MODE_OPENING) { + matrix.setScale(scale, scale); + matrix.postTranslate(transX0, transY0); + targetCrop = crop; + alpha = mAlpha.value; + } else { + matrix.reset(); + alpha = 1f; + targetCrop = target.sourceContainerBounds; + } + + params[i] = new SurfaceParams(target.leash, alpha, matrix, targetCrop, + RemoteAnimationProvider.getLayer(target, MODE_OPENING)); + } + surfaceApplier.scheduleApply(params); } }); return appAnimator; @@ -705,6 +708,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag * Animator that controls the transformations of the windows the targets that are closing. */ private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] targets) { + SyncRtSurfaceTransactionApplier surfaceApplier = + new SyncRtSurfaceTransactionApplier(mDragLayer); Matrix matrix = new Matrix(); ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1); int duration = CLOSING_TRANSITION_DURATION_MS; @@ -714,30 +719,28 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag FloatProp mScale = new FloatProp(1f, 1f, 0, duration, DEACCEL_1_7); FloatProp mAlpha = new FloatProp(1f, 0f, 25, 125, LINEAR); - boolean isFirstFrame = true; - @Override public void onUpdate(float percent) { - TransactionCompat t = new TransactionCompat(); - if (isFirstFrame) { - RemoteAnimationProvider.prepareTargetsForFirstFrame(targets, t, MODE_CLOSING); - isFirstFrame = false; - } - for (RemoteAnimationTargetCompat app : targets) { - if (app.mode == RemoteAnimationTargetCompat.MODE_CLOSING) { - t.setAlpha(app.leash, mAlpha.value); + SurfaceParams[] params = new SurfaceParams[targets.length]; + for (int i = targets.length - 1; i >= 0; i--) { + RemoteAnimationTargetCompat target = targets[i]; + float alpha; + if (target.mode == MODE_CLOSING) { matrix.setScale(mScale.value, mScale.value, - app.sourceContainerBounds.centerX(), - app.sourceContainerBounds.centerY()); + target.sourceContainerBounds.centerX(), + target.sourceContainerBounds.centerY()); matrix.postTranslate(0, mDy.value); - matrix.postTranslate(app.position.x, app.position.y); - t.setMatrix(app.leash, matrix); + matrix.postTranslate(target.position.x, target.position.y); + alpha = mAlpha.value; + } else { + matrix.reset(); + alpha = 1f; } + params[i] = new SurfaceParams(target.leash, alpha, matrix, + target.sourceContainerBounds, + RemoteAnimationProvider.getLayer(target, MODE_CLOSING)); } - t.setEarlyWakeup(); - t.apply(); - - matrix.reset(); + surfaceApplier.scheduleApply(params); } }); diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java index 41a45501d0..eff94fcb5c 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java @@ -67,6 +67,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.PackageManagerWrapper; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier; import com.android.systemui.shared.system.TransactionCompat; import java.util.ArrayList; @@ -350,11 +351,14 @@ public class OverviewCommandHelper { clipHelper.updateTargetRect(targetRect); clipHelper.prepareAnimation(false /* isOpening */); + SyncRtSurfaceTransactionApplier syncTransactionApplier = + new SyncRtSurfaceTransactionApplier(rootView); ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1); valueAnimator.setDuration(RECENTS_LAUNCH_DURATION); valueAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); valueAnimator.addUpdateListener((v) -> - clipHelper.applyTransform(targetSet, (float) v.getAnimatedValue())); + clipHelper.applyTransform(targetSet, (float) v.getAnimatedValue(), + syncTransactionApplier)); if (targetSet.isAnimatingHome()) { // If we are animating home, fade in the opening targets diff --git a/quickstep/src/com/android/quickstep/TaskUtils.java b/quickstep/src/com/android/quickstep/TaskUtils.java index 2b0c98f939..ec2c318d35 100644 --- a/quickstep/src/com/android/quickstep/TaskUtils.java +++ b/quickstep/src/com/android/quickstep/TaskUtils.java @@ -46,6 +46,7 @@ import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier; import java.util.List; @@ -144,6 +145,8 @@ public class TaskUtils { */ public static ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipViewChanges, RemoteAnimationTargetCompat[] targets, final ClipAnimationHelper inOutHelper) { + SyncRtSurfaceTransactionApplier syncTransactionApplier = + new SyncRtSurfaceTransactionApplier(v); final ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); appAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); appAnimator.addUpdateListener(new MultiValueUpdateListener() { @@ -155,18 +158,10 @@ public class TaskUtils { final RemoteAnimationTargetSet mTargetSet; final RectF mThumbnailRect; - private Surface mSurface; - private long mFrameNumber; { mTargetSet = new RemoteAnimationTargetSet(targets, MODE_OPENING); - inOutHelper.setTaskTransformCallback((t, app) -> { - t.setAlpha(app.leash, mTaskAlpha.value); - - if (!skipViewChanges) { - t.deferTransactionUntil(app.leash, mSurface, mFrameNumber); - } - }); + inOutHelper.setTaskAlphaCallback((t, alpha) -> mTaskAlpha.value); inOutHelper.prepareAnimation(true /* isOpening */); inOutHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(), @@ -179,15 +174,8 @@ public class TaskUtils { @Override public void onUpdate(float percent) { - mSurface = getSurface(v); - mFrameNumber = mSurface != null ? getNextFrameNumber(mSurface) : -1; - if (mFrameNumber == -1) { - // Booo, not cool! Our surface got destroyed, so no reason to animate anything. - Log.w(TAG, "Failed to animate, surface got destroyed."); - return; - } - - RectF taskBounds = inOutHelper.applyTransform(mTargetSet, 1 - percent); + RectF taskBounds = inOutHelper.applyTransform(mTargetSet, 1 - percent, + syncTransactionApplier); if (!skipViewChanges) { float scale = taskBounds.width() / mThumbnailRect.width(); v.setScaleX(scale); diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index aecb66c77d..49a4ac8bab 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -49,6 +49,7 @@ import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.ChoreographerCompat; import com.android.systemui.shared.system.NavigationBarCompat.HitTarget; /** @@ -406,6 +407,6 @@ public class TouchInteractionService extends Service { sRemoteUiThread.start(); } new Handler(sRemoteUiThread.getLooper()).post(() -> - mBackgroundThreadChoreographer = Choreographer.getInstance()); + mBackgroundThreadChoreographer = ChoreographerCompat.getSfInstance()); } } diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index b1663b169a..28062cfccc 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -79,6 +79,7 @@ import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier; import com.android.systemui.shared.system.WindowCallbacksCompat; import com.android.systemui.shared.system.WindowManagerWrapper; @@ -192,6 +193,7 @@ public class WindowTransformSwipeHandler { private T mActivity; private LayoutListener mLayoutListener; private RecentsView mRecentsView; + private SyncRtSurfaceTransactionApplier mSyncTransactionApplier; private QuickScrubController mQuickScrubController; private AnimationFactory mAnimationFactory = (t, i) -> { }; @@ -360,6 +362,7 @@ public class WindowTransformSwipeHandler { } mRecentsView = activity.getOverviewPanel(); + mSyncTransactionApplier = new SyncRtSurfaceTransactionApplier(mRecentsView); mQuickScrubController = mRecentsView.getQuickScrubController(); mLayoutListener = mActivityControlHelper.createLayoutListener(mActivity); @@ -546,7 +549,11 @@ public class WindowTransformSwipeHandler { RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController(); if (controller != null) { - mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet, shift); + + mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet, shift, + Looper.myLooper() == mMainThreadHandler.getLooper() + ? mSyncTransactionApplier + : null); // TODO: This logic is spartanic! boolean passedThreshold = shift > 0.12f; diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java index a654482f97..df70a8a394 100644 --- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java +++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java @@ -30,6 +30,7 @@ import android.graphics.RectF; import android.os.Build; import android.os.RemoteException; import android.support.annotation.Nullable; +import android.view.Surface; import android.view.animation.Interpolator; import com.android.launcher3.BaseDraggingActivity; @@ -44,10 +45,13 @@ import com.android.quickstep.views.TaskThumbnailView; import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.recents.utilities.RectFEvaluator; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier.SurfaceParams; import com.android.systemui.shared.system.TransactionCompat; import com.android.systemui.shared.system.WindowManagerWrapper; import java.util.function.BiConsumer; +import java.util.function.BiFunction; /** * Utility class to handle window clip animation @@ -90,8 +94,8 @@ public class ClipAnimationHelper { // Wether or not applyTransform has been called yet since prepareAnimation() private boolean mIsFirstFrame = true; - private BiConsumer mTaskTransformCallback = - (t, a) -> { }; + private BiFunction mTaskAlphaCallback = + (t, a1) -> a1; private void updateSourceStack(RemoteAnimationTargetCompat target) { mSourceInsets.set(target.contentInsets); @@ -134,11 +138,11 @@ public class ClipAnimationHelper { } public void prepareAnimation(boolean isOpening) { - mIsFirstFrame = true; mBoostModeTargetLayers = isOpening ? MODE_OPENING : MODE_CLOSING; } - public RectF applyTransform(RemoteAnimationTargetSet targetSet, float progress) { + public RectF applyTransform(RemoteAnimationTargetSet targetSet, float progress, + @Nullable SyncRtSurfaceTransactionApplier syncTransactionApplier) { RectF currentRect; mTmpRectF.set(mTargetRect); Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale); @@ -159,35 +163,51 @@ public class ClipAnimationHelper { mClipRect.bottom = (int) (mSourceStackBounds.height() - (mSourceWindowClipInsets.bottom * progress)); - TransactionCompat transaction = new TransactionCompat(); - if (mIsFirstFrame) { - RemoteAnimationProvider.prepareTargetsForFirstFrame(targetSet.unfilteredApps, - transaction, mBoostModeTargetLayers); - mIsFirstFrame = false; - } - for (RemoteAnimationTargetCompat app : targetSet.apps) { - if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) { - mTmpMatrix.setRectToRect(mSourceRect, currentRect, ScaleToFit.FILL); - mTmpMatrix.postTranslate(app.position.x, app.position.y); - transaction.setMatrix(app.leash, mTmpMatrix) - .setWindowCrop(app.leash, mClipRect); + SurfaceParams[] params = new SurfaceParams[targetSet.unfilteredApps.length]; + for (int i = 0; i < targetSet.unfilteredApps.length; i++) { + RemoteAnimationTargetCompat app = targetSet.unfilteredApps[i]; + mTmpMatrix.setTranslate(app.position.x, app.position.y); + Rect crop = app.sourceContainerBounds; + float alpha = 1f; + if (app.mode == targetSet.targetMode) { + if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) { + mTmpMatrix.setRectToRect(mSourceRect, currentRect, ScaleToFit.FILL); + mTmpMatrix.postTranslate(app.position.x, app.position.y); + crop = mClipRect; + } + + if (app.isNotInRecents + || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) { + alpha = 1 - progress; + } + + alpha = mTaskAlphaCallback.apply(app, alpha); } - if (app.isNotInRecents - || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) { - transaction.setAlpha(app.leash, 1 - progress); - } - - mTaskTransformCallback.accept(transaction, app); + params[i] = new SurfaceParams(app.leash, alpha, mTmpMatrix, crop, + RemoteAnimationProvider.getLayer(app, mBoostModeTargetLayers)); } - transaction.setEarlyWakeup(); - transaction.apply(); + applyParams(syncTransactionApplier, params); return currentRect; } - public void setTaskTransformCallback - (BiConsumer callback) { - mTaskTransformCallback = callback; + private void applyParams(@Nullable SyncRtSurfaceTransactionApplier syncTransactionApplier, + SurfaceParams[] params) { + if (syncTransactionApplier != null) { + syncTransactionApplier.scheduleApply(params); + } else { + TransactionCompat t = new TransactionCompat(); + for (SurfaceParams param : params) { + SyncRtSurfaceTransactionApplier.applyParams(t, param); + } + t.setEarlyWakeup(); + t.apply(); + } + } + + public void setTaskAlphaCallback( + BiFunction callback) { + mTaskAlphaCallback = callback; } public void offsetTarget(float scale, float offsetX, float offsetY, Interpolator interpolator) { diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java index bbf223d1ef..a7e6d74f02 100644 --- a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java +++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java @@ -28,6 +28,8 @@ import com.android.systemui.shared.system.TransactionCompat; @FunctionalInterface public interface RemoteAnimationProvider { + static final int Z_BOOST_BASE = 800570000; + AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targets); default ActivityOptions toActivityOptions(Handler handler, long duration) { @@ -54,11 +56,14 @@ public interface RemoteAnimationProvider { static void prepareTargetsForFirstFrame(RemoteAnimationTargetCompat[] targets, TransactionCompat t, int boostModeTargets) { for (RemoteAnimationTargetCompat target : targets) { - int layer = target.mode == boostModeTargets - ? Integer.MAX_VALUE - : target.prefixOrderIndex; - t.setLayer(target.leash, layer); + t.setLayer(target.leash, getLayer(target, boostModeTargets)); t.show(target.leash); } } + + static int getLayer(RemoteAnimationTargetCompat target, int boostModeTarget) { + return target.mode == boostModeTarget + ? Z_BOOST_BASE + target.prefixOrderIndex + : target.prefixOrderIndex; + } } diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java index 04b8be58bf..c3724853ae 100644 --- a/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java +++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java @@ -26,6 +26,7 @@ public class RemoteAnimationTargetSet { public final RemoteAnimationTargetCompat[] unfilteredApps; public final RemoteAnimationTargetCompat[] apps; + public final int targetMode; public RemoteAnimationTargetSet(RemoteAnimationTargetCompat[] apps, int targetMode) { ArrayList filteredApps = new ArrayList<>(); @@ -39,6 +40,7 @@ public class RemoteAnimationTargetSet { this.unfilteredApps = apps; this.apps = filteredApps.toArray(new RemoteAnimationTargetCompat[filteredApps.size()]); + this.targetMode = targetMode; } public RemoteAnimationTargetCompat findTask(int taskId) {