• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.quickstep.util;
17 
18 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
19 
20 import static com.android.launcher3.Flags.enableGridOnlyOverview;
21 import static com.android.launcher3.states.RotationHelper.deltaRotation;
22 import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE;
23 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
24 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
25 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
26 import static com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
27 import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
28 import static com.android.quickstep.util.RecentsOrientedState.preDisplayRotation;
29 
30 import android.animation.TimeInterpolator;
31 import android.content.Context;
32 import android.content.res.Resources;
33 import android.graphics.Matrix;
34 import android.graphics.PointF;
35 import android.graphics.Rect;
36 import android.graphics.RectF;
37 import android.util.Log;
38 import android.view.RemoteAnimationTarget;
39 import android.view.animation.Interpolator;
40 
41 import androidx.annotation.NonNull;
42 import androidx.annotation.Nullable;
43 
44 import com.android.launcher3.DeviceProfile;
45 import com.android.launcher3.Utilities;
46 import com.android.launcher3.anim.AnimatedFloat;
47 import com.android.launcher3.anim.PendingAnimation;
48 import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
49 import com.android.launcher3.util.TraceHelper;
50 import com.android.quickstep.BaseActivityInterface;
51 import com.android.quickstep.BaseContainerInterface;
52 import com.android.quickstep.DesktopFullscreenDrawParams;
53 import com.android.quickstep.FullscreenDrawParams;
54 import com.android.quickstep.TaskAnimationManager;
55 import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
56 import com.android.systemui.shared.recents.model.ThumbnailData;
57 import com.android.systemui.shared.recents.utilities.PreviewPositionHelper;
58 
59 /**
60  * A utility class which emulates the layout behavior of TaskView and RecentsView
61  */
62 public class TaskViewSimulator implements TransformParams.BuilderProxy {
63 
64     private static final String TAG = "TaskViewSimulator";
65     private static final boolean DEBUG = false;
66 
67     private final Rect mTmpCropRect = new Rect();
68     private final RectF mTempRectF = new RectF();
69     private final float[] mTempPoint = new float[2];
70 
71     private final Context mContext;
72     private final BaseContainerInterface mSizeStrategy;
73 
74     @NonNull
75     private RecentsOrientedState mOrientationState;
76     private final boolean mIsRecentsRtl;
77 
78     private final Rect mTaskRect = new Rect();
79     private final Rect mFullTaskSize = new Rect();
80     private final Rect mCarouselTaskSize = new Rect();
81     private PointF mPivotOverride = null;
82     private final PointF mPivot = new PointF();
83     private DeviceProfile mDp;
84     @StagePosition
85     private int mStagePosition = STAGE_POSITION_UNDEFINED;
86 
87     private final Matrix mMatrix = new Matrix();
88     private final Matrix mMatrixTmp = new Matrix();
89 
90     // Thumbnail view properties
91     private final Rect mThumbnailPosition = new Rect();
92     private final ThumbnailData mThumbnailData = new ThumbnailData();
93     private final PreviewPositionHelper mPositionHelper = new PreviewPositionHelper();
94     private final Matrix mInversePositionMatrix = new Matrix();
95 
96     // TaskView properties
97     private final FullscreenDrawParams mCurrentFullscreenParams;
98     public final AnimatedFloat taskPrimaryTranslation = new AnimatedFloat();
99     public final AnimatedFloat taskSecondaryTranslation = new AnimatedFloat();
100     public final AnimatedFloat taskGridTranslationX = new AnimatedFloat();
101     public final AnimatedFloat taskGridTranslationY = new AnimatedFloat();
102 
103     // Carousel properties
104     public final AnimatedFloat carouselScale = new AnimatedFloat();
105 
106     // RecentsView properties
107     public final AnimatedFloat recentsViewScale = new AnimatedFloat();
108     public final AnimatedFloat fullScreenProgress = new AnimatedFloat();
109     public final AnimatedFloat recentsViewSecondaryTranslation = new AnimatedFloat();
110     public final AnimatedFloat recentsViewPrimaryTranslation = new AnimatedFloat();
111     public final AnimatedFloat recentsViewScroll = new AnimatedFloat();
112 
113     // Cached calculations
114     private boolean mLayoutValid = false;
115     private int mOrientationStateId;
116     private SplitBounds mSplitBounds;
117     private Boolean mDrawsBelowRecents = null;
118     private boolean mIsGridTask;
119     private final boolean mIsDesktopTask;
120     private boolean mIsAnimatingToCarousel = false;
121     private int mTaskRectTranslationX;
122     private int mTaskRectTranslationY;
123     private int mDesktopTaskIndex = 0;
124 
125     @Nullable
126     private Matrix mTaskRectTransform = null;
127 
TaskViewSimulator(Context context, BaseContainerInterface sizeStrategy, boolean isDesktop, int desktopTaskIndex)128     public TaskViewSimulator(Context context, BaseContainerInterface sizeStrategy,
129             boolean isDesktop, int desktopTaskIndex) {
130         mContext = context;
131         mSizeStrategy = sizeStrategy;
132         mIsDesktopTask = isDesktop;
133         mDesktopTaskIndex = desktopTaskIndex;
134 
135         mOrientationState = TraceHelper.allowIpcs("TaskViewSimulator.init",
136                 () -> new RecentsOrientedState(context, sizeStrategy, i -> { }));
137         mOrientationState.setGestureActive(true);
138         mCurrentFullscreenParams = mIsDesktopTask
139                 ? new DesktopFullscreenDrawParams(context)
140                 : new FullscreenDrawParams(context);
141         mOrientationStateId = mOrientationState.getStateId();
142         Resources resources = context.getResources();
143         mIsRecentsRtl = mOrientationState.getOrientationHandler().getRecentsRtlSetting(resources);
144         carouselScale.value = 1f;
145     }
146 
147     /**
148      * Sets the device profile for the current state
149      */
setDp(DeviceProfile dp)150     public void setDp(DeviceProfile dp) {
151         mDp = dp;
152         mLayoutValid = false;
153         mOrientationState.setDeviceProfile(dp);
154         if (enableGridOnlyOverview()) {
155             mIsGridTask = dp.isTablet && !mIsDesktopTask;
156         }
157         calculateTaskSize();
158     }
159 
calculateTaskSize()160     private void calculateTaskSize() {
161         if (mDp == null) {
162             return;
163         }
164 
165         if (mIsGridTask) {
166             mSizeStrategy.calculateGridTaskSize(mContext, mDp, mFullTaskSize,
167                     mOrientationState.getOrientationHandler());
168             if (enableGridOnlyOverview()) {
169                 mSizeStrategy.calculateTaskSize(mContext, mDp, mCarouselTaskSize,
170                         mOrientationState.getOrientationHandler());
171             }
172         } else {
173             mSizeStrategy.calculateTaskSize(mContext, mDp, mFullTaskSize,
174                     mOrientationState.getOrientationHandler());
175             if (enableGridOnlyOverview()) {
176                 mCarouselTaskSize.set(mFullTaskSize);
177             }
178         }
179 
180         if (mSplitBounds != null) {
181             // The task rect changes according to the staged split task sizes, but recents
182             // fullscreen scale and pivot remains the same since the task fits into the existing
183             // sized task space bounds
184             mTaskRect.set(mFullTaskSize);
185             mOrientationState.getOrientationHandler()
186                     .setSplitTaskSwipeRect(mDp, mTaskRect, mSplitBounds, mStagePosition);
187         } else if (mIsDesktopTask) {
188             // For desktop, tasks can take up only part of the screen size.
189             // Full task size represents the whole screen size, but scaled down to fit in recents.
190             // Task rect will represent the scaled down thumbnail position and is placed inside
191             // full task size as it is on the home screen.
192             PointF fullscreenTaskDimension = new PointF();
193             BaseActivityInterface.getTaskDimension(mContext, mDp, fullscreenTaskDimension);
194             // Calculate the scale down factor used in recents
195             float scale = mFullTaskSize.width() / fullscreenTaskDimension.x;
196             mTaskRect.set(mThumbnailPosition);
197             mTaskRect.scale(scale);
198             // Ensure the task rect is inside the full task rect
199             mTaskRect.offset(mFullTaskSize.left, mFullTaskSize.top);
200 
201             Rect taskDimension = new Rect(0, 0, (int) fullscreenTaskDimension.x,
202                     (int) fullscreenTaskDimension.y);
203             mTmpCropRect.set(mThumbnailPosition);
204             if (mTmpCropRect.setIntersect(taskDimension, mThumbnailPosition)) {
205                 mTmpCropRect.offset(-mThumbnailPosition.left, -mThumbnailPosition.top);
206             } else {
207                 mTmpCropRect.setEmpty();
208             }
209         } else {
210             mTaskRect.set(mFullTaskSize);
211         }
212         mTaskRect.offset(mTaskRectTranslationX, mTaskRectTranslationY);
213     }
214 
215     /**
216      * Sets the orientation state used for this animation
217      */
setOrientationState(@onNull RecentsOrientedState orientationState)218     public void setOrientationState(@NonNull RecentsOrientedState orientationState) {
219         mOrientationState = orientationState;
220         mLayoutValid = false;
221     }
222 
223     /**
224      * @see com.android.quickstep.views.RecentsView#FULLSCREEN_PROGRESS
225      */
getFullScreenScale()226     public float getFullScreenScale() {
227         if (mDp == null) {
228             return 1;
229         }
230         // Copy mFullTaskSize instead of updating it directly so it could be reused next time
231         // without recalculating
232         Rect scaleRect = new Rect(mIsAnimatingToCarousel ? mCarouselTaskSize : mFullTaskSize);
233         scaleRect.offset(mTaskRectTranslationX, mTaskRectTranslationY);
234         float scale = mOrientationState.getFullScreenScaleAndPivot(scaleRect, mDp, mPivot);
235         if (mPivotOverride != null) {
236             mPivot.set(mPivotOverride);
237         }
238         return scale;
239     }
240 
241     /**
242      * Sets the targets which the simulator will control
243      */
setPreview(RemoteAnimationTarget runningTarget)244     public void setPreview(RemoteAnimationTarget runningTarget) {
245         setPreviewBounds(
246                 runningTarget.startBounds == null
247                         ? runningTarget.screenSpaceBounds : runningTarget.startBounds,
248                 runningTarget.contentInsets);
249     }
250 
251     /**
252      * Sets the targets which the simulator will control specifically for targets to animate when
253      * in split screen
254      *
255      * @param splitInfo set to {@code null} when not in staged split mode
256      */
setPreview(RemoteAnimationTarget runningTarget, SplitBounds splitInfo)257     public void setPreview(RemoteAnimationTarget runningTarget, SplitBounds splitInfo) {
258         setPreview(runningTarget);
259         mSplitBounds = splitInfo;
260         if (mSplitBounds == null) {
261             mStagePosition = STAGE_POSITION_UNDEFINED;
262         } else {
263             mStagePosition = runningTarget.taskId == splitInfo.leftTopTaskId
264                     ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT;
265         }
266         calculateTaskSize();
267     }
268 
269     /**
270      * Sets the targets which the simulator will control
271      */
setPreviewBounds(Rect bounds, Rect insets)272     public void setPreviewBounds(Rect bounds, Rect insets) {
273         mThumbnailData.insets.set(insets);
274         // TODO: What is this?
275         mThumbnailData.windowingMode = WINDOWING_MODE_FULLSCREEN;
276 
277         mThumbnailPosition.set(bounds);
278         mLayoutValid = false;
279     }
280 
281     /**
282      * Updates the scroll for RecentsView
283      */
setScroll(float scroll)284     public void setScroll(float scroll) {
285         recentsViewScroll.value = scroll;
286     }
287 
setDrawsBelowRecents(boolean drawsBelowRecents)288     public void setDrawsBelowRecents(boolean drawsBelowRecents) {
289         mDrawsBelowRecents = drawsBelowRecents;
290     }
291 
292     /**
293      * Sets whether the task is part of overview grid and not being focused.
294      */
setIsGridTask(boolean isGridTask)295     public void setIsGridTask(boolean isGridTask) {
296         mIsGridTask = isGridTask;
297     }
298 
299     /**
300      * Apply translations on TaskRect's starting location.
301      */
setTaskRectTranslation(int taskRectTranslationX, int taskRectTranslationY)302     public void setTaskRectTranslation(int taskRectTranslationX, int taskRectTranslationY) {
303         mTaskRectTranslationX = taskRectTranslationX;
304         mTaskRectTranslationY = taskRectTranslationY;
305         // Re-calculate task size after changing translation
306         calculateTaskSize();
307     }
308 
309     /**
310      * Override the pivot used to apply scale changes.
311      */
setPivotOverride(PointF pivotOverride)312     public void setPivotOverride(PointF pivotOverride) {
313         mPivotOverride = pivotOverride;
314         getFullScreenScale();
315     }
316 
317     /**
318      * Adds animation for all the components corresponding to transition from an app to carousel.
319      */
addAppToCarouselAnim(PendingAnimation pa, Interpolator interpolator)320     public void addAppToCarouselAnim(PendingAnimation pa, Interpolator interpolator) {
321         pa.addFloat(fullScreenProgress, AnimatedFloat.VALUE, 1, 0, interpolator);
322         if (enableGridOnlyOverview() && mDp.isTablet && mDp.isGestureMode) {
323             mIsAnimatingToCarousel = true;
324             carouselScale.value = mCarouselTaskSize.width() / (float) mFullTaskSize.width();
325         }
326         pa.addFloat(recentsViewScale, AnimatedFloat.VALUE, getFullScreenScale(), 1,
327                 interpolator);
328     }
329 
330     /**
331      * Adds animation for all the components corresponding to transition from overview to the app.
332      */
addOverviewToAppAnim(PendingAnimation pa, TimeInterpolator interpolator)333     public void addOverviewToAppAnim(PendingAnimation pa, TimeInterpolator interpolator) {
334         pa.addFloat(fullScreenProgress, AnimatedFloat.VALUE, 0, 1, interpolator);
335         pa.addFloat(recentsViewScale, AnimatedFloat.VALUE, 1, getFullScreenScale(), interpolator);
336     }
337 
338     /**
339      * Returns the current clipped/visible window bounds in the window coordinate space
340      */
getCurrentCropRect()341     public RectF getCurrentCropRect() {
342         // Crop rect is the inverse of thumbnail matrix
343         mTempRectF.set(0, 0, mTaskRect.width(), mTaskRect.height());
344         mInversePositionMatrix.mapRect(mTempRectF);
345         return mTempRectF;
346     }
347 
348     /**
349      * Returns the current task bounds in the Launcher coordinate space.
350      */
getCurrentRect()351     public RectF getCurrentRect() {
352         RectF result = getCurrentCropRect();
353         mMatrixTmp.set(mMatrix);
354         preDisplayRotation(mOrientationState.getDisplayRotation(), mDp.widthPx, mDp.heightPx,
355                 mMatrixTmp);
356         mMatrixTmp.mapRect(result);
357         return result;
358     }
359 
getOrientationState()360     public RecentsOrientedState getOrientationState() {
361         return mOrientationState;
362     }
363 
364     /**
365      * Returns the current transform applied to the window
366      */
getCurrentMatrix()367     public Matrix getCurrentMatrix() {
368         return mMatrix;
369     }
370 
371     /**
372      * Sets a matrix used to transform the position of tasks. If set, this matrix is applied to
373      * the task rect after the task has been scaled and positioned inside the fulltask, but
374      * before scaling and translation of the whole recents view is performed.
375      */
setTaskRectTransform(@ullable Matrix taskRectTransform)376     public void setTaskRectTransform(@Nullable Matrix taskRectTransform) {
377         mTaskRectTransform = taskRectTransform;
378     }
379 
380     /**
381      * Calculates the crop rect for desktop tasks given the current matrix.
382      */
calculateDesktopTaskCropRect()383     private void calculateDesktopTaskCropRect() {
384         // The approach here is to map a rect that represents the untransformed thumbnail position
385         // using the current matrix. This will give us a rect that can be intersected with
386         // [mFullTaskSize]. Using the intersection, we then compute how much of the task window that
387         // needs to be cropped (which will be nothing if the window is entirely within the desktop).
388         mTempRectF.set(0, 0, mThumbnailPosition.width(), mThumbnailPosition.height());
389         mMatrix.mapRect(mTempRectF);
390 
391         float offsetX = mTempRectF.left;
392         float offsetY = mTempRectF.top;
393         float scale = mThumbnailPosition.width() / mTempRectF.width();
394 
395         if (mTempRectF.intersect(mFullTaskSize.left, mFullTaskSize.top, mFullTaskSize.right,
396                 mFullTaskSize.bottom)) {
397             mTempRectF.offset(-offsetX, -offsetY);
398             mTempRectF.scale(scale);
399             mTempRectF.round(mTmpCropRect);
400         }
401     }
402 
403     /**
404      * Applies the rotation on the matrix to so that it maps from launcher coordinate space to
405      * window coordinate space.
406      */
applyWindowToHomeRotation(Matrix matrix)407     public void applyWindowToHomeRotation(Matrix matrix) {
408         matrix.postTranslate(mDp.windowX, mDp.windowY);
409         postDisplayRotation(deltaRotation(
410                         mOrientationState.getRecentsActivityRotation(),
411                         mOrientationState.getDisplayRotation()),
412                 mDp.widthPx, mDp.heightPx, matrix);
413     }
414 
415     /**
416      * Applies the target to the previously set parameters
417      */
apply(TransformParams params)418     public void apply(TransformParams params) {
419         apply(params, null);
420     }
421 
422     /**
423      * Applies the target to the previously set parameters, optionally with an overridden
424      * surface transaction
425      */
apply(TransformParams params, @Nullable SurfaceTransaction surfaceTransaction)426     public void apply(TransformParams params, @Nullable SurfaceTransaction surfaceTransaction) {
427         if (mDp == null || mThumbnailPosition.isEmpty()) {
428             return;
429         }
430         if (!mLayoutValid || mOrientationStateId != mOrientationState.getStateId()) {
431             mLayoutValid = true;
432             mOrientationStateId = mOrientationState.getStateId();
433 
434             getFullScreenScale();
435             if (TaskAnimationManager.SHELL_TRANSITIONS_ROTATION) {
436                 // With shell transitions, the display is rotated early so we need to actually use
437                 // the rotation when the gesture starts
438                 mThumbnailData.rotation = mOrientationState.getTouchRotation();
439             } else {
440                 mThumbnailData.rotation = mOrientationState.getDisplayRotation();
441             }
442 
443             // mIsRecentsRtl is the inverse of TaskView RTL.
444             boolean isRtlEnabled = !mIsRecentsRtl;
445             mPositionHelper.updateThumbnailMatrix(
446                     mThumbnailPosition, mThumbnailData, mTaskRect.width(), mTaskRect.height(),
447                     mDp.isTablet, mOrientationState.getRecentsActivityRotation(), isRtlEnabled);
448             mPositionHelper.getMatrix().invert(mInversePositionMatrix);
449             if (DEBUG) {
450                 Log.d(TAG, " taskRect: " + mTaskRect);
451             }
452         }
453 
454         float fullScreenProgress = Utilities.boundToRange(this.fullScreenProgress.value, 0, 1);
455         mCurrentFullscreenParams.setProgress(fullScreenProgress, recentsViewScale.value,
456                 carouselScale.value);
457 
458         // Apply thumbnail matrix
459         float taskWidth = mTaskRect.width();
460         float taskHeight = mTaskRect.height();
461 
462         mMatrix.set(mPositionHelper.getMatrix());
463 
464         // Apply TaskView matrix: taskRect, optional transform, translate
465         mMatrix.postTranslate(mTaskRect.left, mTaskRect.top);
466         if (mTaskRectTransform != null) {
467             mMatrix.postConcat(mTaskRectTransform);
468 
469             // Calculate cropping for desktop tasks. The order is important since it uses the
470             // current matrix. Therefore we calculate it here, after applying the task rect
471             // transform, but before applying scaling/translation that affects the whole
472             // recentsview.
473             if (mIsDesktopTask) {
474                 calculateDesktopTaskCropRect();
475             }
476         }
477 
478         mOrientationState.getOrientationHandler().setPrimary(mMatrix, MATRIX_POST_TRANSLATE,
479                 taskPrimaryTranslation.value);
480         mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE,
481                 taskSecondaryTranslation.value);
482         mMatrix.postTranslate(taskGridTranslationX.value, taskGridTranslationY.value);
483 
484         mMatrix.postScale(carouselScale.value, carouselScale.value,
485                 mIsRecentsRtl ? mCarouselTaskSize.right : mCarouselTaskSize.left,
486                 mCarouselTaskSize.top);
487 
488         mOrientationState.getOrientationHandler().setPrimary(
489                 mMatrix, MATRIX_POST_TRANSLATE, recentsViewScroll.value);
490 
491         // Apply RecentsView matrix
492         mMatrix.postScale(recentsViewScale.value, recentsViewScale.value, mPivot.x, mPivot.y);
493         mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE,
494                 recentsViewSecondaryTranslation.value);
495         mOrientationState.getOrientationHandler().setPrimary(mMatrix, MATRIX_POST_TRANSLATE,
496                 recentsViewPrimaryTranslation.value);
497         applyWindowToHomeRotation(mMatrix);
498 
499         if (!mIsDesktopTask) {
500             // Crop rect is the inverse of thumbnail matrix
501             mTempRectF.set(0, 0, taskWidth, taskHeight);
502             mInversePositionMatrix.mapRect(mTempRectF);
503             mTempRectF.roundOut(mTmpCropRect);
504         }
505 
506         params.setProgress(1f - fullScreenProgress);
507         params.applySurfaceParams(surfaceTransaction == null
508                 ? params.createSurfaceParams(this) : surfaceTransaction);
509 
510         if (!DEBUG) {
511             return;
512         }
513         Log.d(TAG, "progress: " + fullScreenProgress
514                 + " carouselScale: " + carouselScale.value
515                 + " recentsViewScale: " + recentsViewScale.value
516                 + " crop: " + mTmpCropRect
517                 + " radius: " + getCurrentCornerRadius()
518                 + " taskW: " + taskWidth + " H: " + taskHeight
519                 + " taskRect: " + mTaskRect
520                 + " taskPrimaryT: " + taskPrimaryTranslation.value
521                 + " taskSecondaryT: " + taskSecondaryTranslation.value
522                 + " taskGridTranslationX: " + taskGridTranslationX.value
523                 + " taskGridTranslationY: " + taskGridTranslationY.value
524                 + " recentsPrimaryT: " + recentsViewPrimaryTranslation.value
525                 + " recentsSecondaryT: " + recentsViewSecondaryTranslation.value
526                 + " recentsScroll: " + recentsViewScroll.value
527                 + " pivot: " + mPivot
528         );
529     }
530 
531     @Override
onBuildTargetParams( SurfaceProperties builder, RemoteAnimationTarget app, TransformParams params)532     public void onBuildTargetParams(
533             SurfaceProperties builder, RemoteAnimationTarget app, TransformParams params) {
534         builder.setMatrix(mMatrix)
535                 .setWindowCrop(mTmpCropRect)
536                 .setCornerRadius(getCurrentCornerRadius());
537 
538         // If mDrawsBelowRecents is unset, no reordering will be enforced.
539         if (mDrawsBelowRecents != null) {
540             // In shell transitions, the animation leashes are reparented to an animation container
541             // so we can bump layers as needed.
542             builder.setLayer(mDrawsBelowRecents
543                     // 1000 is an arbitrary number to give room for multiple layers.
544                     ? Integer.MIN_VALUE + 1000 + app.prefixOrderIndex - mDesktopTaskIndex
545                     : Integer.MAX_VALUE - 1000 + app.prefixOrderIndex - mDesktopTaskIndex);
546         }
547     }
548 
549     /**
550      * Returns the corner radius that should be applied to the target so that it matches the
551      * TaskView
552      */
getCurrentCornerRadius()553     public float getCurrentCornerRadius() {
554         float visibleRadius = mCurrentFullscreenParams.getCurrentCornerRadius();
555         mTempPoint[0] = visibleRadius;
556         mTempPoint[1] = 0;
557         mInversePositionMatrix.mapVectors(mTempPoint);
558 
559         // Ideally we should use square-root. This is an optimization as one of the dimension is 0.
560         return Math.max(Math.abs(mTempPoint[0]), Math.abs(mTempPoint[1]));
561     }
562 }
563