Loading libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java +37 −63 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.wm.shell.activityembedding; import static android.graphics.Matrix.MSCALE_X; import static android.graphics.Matrix.MTRANS_X; import static android.graphics.Matrix.MTRANS_Y; Loading @@ -42,31 +41,45 @@ class ActivityEmbeddingAnimationAdapter { */ private static final int LAYER_NO_OVERRIDE = -1; @NonNull final Animation mAnimation; @NonNull final TransitionInfo.Change mChange; @NonNull final SurfaceControl mLeash; /** Area in absolute coordinate that the animation surface shouldn't go beyond. */ @NonNull private final Rect mWholeAnimationBounds = new Rect(); @NonNull final Transformation mTransformation = new Transformation(); @NonNull final float[] mMatrix = new float[9]; @NonNull final float[] mVecs = new float[4]; @NonNull final Rect mRect = new Rect(); private boolean mIsFirstFrame = true; private int mOverrideLayer = LAYER_NO_OVERRIDE; ActivityEmbeddingAnimationAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change) { this(animation, change, change.getLeash()); this(animation, change, change.getLeash(), change.getEndAbsBounds()); } /** * @param leash the surface to animate, which is not necessary the same as * {@link TransitionInfo.Change#getLeash()}, it can be a screenshot for example. * @param wholeAnimationBounds area in absolute coordinate that the animation surface shouldn't * go beyond. */ ActivityEmbeddingAnimationAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change, @NonNull SurfaceControl leash) { @NonNull TransitionInfo.Change change, @NonNull SurfaceControl leash, @NonNull Rect wholeAnimationBounds) { mAnimation = animation; mChange = change; mLeash = leash; mWholeAnimationBounds.set(wholeAnimationBounds); } /** Loading Loading @@ -96,23 +109,31 @@ class ActivityEmbeddingAnimationAdapter { /** To be overridden by subclasses to adjust the animation surface change. */ void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) { // Update the surface position and alpha. final Point offset = mChange.getEndRelOffset(); mTransformation.getMatrix().postTranslate(offset.x, offset.y); t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix); t.setAlpha(mLeash, mTransformation.getAlpha()); // Get current animation position. // Get current surface bounds in absolute coordinate. // positionX/Y are in local coordinate, so minus the local offset to get the slide amount. final int positionX = Math.round(mMatrix[MTRANS_X]); final int positionY = Math.round(mMatrix[MTRANS_Y]); // The exiting surface starts at position: Change#getEndRelOffset() and moves with // positionX varying. Offset our crop region by the amount we have slided so crop // regions stays exactly on the original container in split. final int cropOffsetX = offset.x - positionX; final int cropOffsetY = offset.y - positionY; final Rect cropRect = new Rect(); cropRect.set(mChange.getEndAbsBounds()); // Because window crop uses absolute position. cropRect.offsetTo(0, 0); cropRect.offset(cropOffsetX, cropOffsetY); final Rect cropRect = new Rect(mChange.getEndAbsBounds()); cropRect.offset(positionX - offset.x, positionY - offset.y); // Store the current offset of the surface top left from (0,0) in absolute coordinate. final int offsetX = cropRect.left; final int offsetY = cropRect.top; // Intersect to make sure the animation happens within the whole animation bounds. if (!cropRect.intersect(mWholeAnimationBounds)) { // Hide the surface when it is outside of the animation area. t.setAlpha(mLeash, 0); } // cropRect is in absolute coordinate, so we need to translate it to surface top left. cropRect.offset(-offsetX, -offsetY); t.setCrop(mLeash, cropRect); } Loading @@ -126,53 +147,6 @@ class ActivityEmbeddingAnimationAdapter { return mAnimation.computeDurationHint(); } /** * Should be used when the {@link TransitionInfo.Change} is in split with others, and wants to * animate together as one. This adapter will offset the animation leash to make the animate of * two windows look like a single window. */ static class SplitAdapter extends ActivityEmbeddingAnimationAdapter { private final boolean mIsLeftHalf; private final int mWholeAnimationWidth; /** * @param isLeftHalf whether this is the left half of the animation. * @param wholeAnimationWidth the whole animation windows width. */ SplitAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change, boolean isLeftHalf, int wholeAnimationWidth) { super(animation, change); mIsLeftHalf = isLeftHalf; mWholeAnimationWidth = wholeAnimationWidth; if (wholeAnimationWidth == 0) { throw new IllegalArgumentException("SplitAdapter must provide wholeAnimationWidth"); } } @Override void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) { final Point offset = mChange.getEndRelOffset(); float posX = offset.x; final float posY = offset.y; // This window is half of the whole animation window. Offset left/right to make it // look as one with the other half. mTransformation.getMatrix().getValues(mMatrix); final int changeWidth = mChange.getEndAbsBounds().width(); final float scaleX = mMatrix[MSCALE_X]; final float totalOffset = mWholeAnimationWidth * (1 - scaleX) / 2; final float curOffset = changeWidth * (1 - scaleX) / 2; final float offsetDiff = totalOffset - curOffset; if (mIsLeftHalf) { posX += offsetDiff; } else { posX -= offsetDiff; } mTransformation.getMatrix().postTranslate(posX, posY); t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix); t.setAlpha(mLeash, mTransformation.getAlpha()); } } /** * Should be used for the animation of the snapshot of a {@link TransitionInfo.Change} that has * size change. Loading @@ -181,7 +155,7 @@ class ActivityEmbeddingAnimationAdapter { SnapshotAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change, @NonNull SurfaceControl snapshotLeash) { super(animation, change, snapshotLeash); super(animation, change, snapshotLeash, change.getEndAbsBounds()); } @Override Loading libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java +4 −22 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET; import android.animation.Animator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; import android.util.Log; Loading Loading @@ -169,15 +168,12 @@ class ActivityEmbeddingAnimationRunner { final Rect openingWholeScreenBounds = new Rect(); final Rect closingWholeScreenBounds = new Rect(); for (TransitionInfo.Change change : info.getChanges()) { final Rect bounds = new Rect(change.getEndAbsBounds()); final Point offset = change.getEndRelOffset(); bounds.offsetTo(offset.x, offset.y); if (Transitions.isOpeningType(change.getMode())) { openingChanges.add(change); openingWholeScreenBounds.union(bounds); openingWholeScreenBounds.union(change.getEndAbsBounds()); } else { closingChanges.add(change); closingWholeScreenBounds.union(bounds); closingWholeScreenBounds.union(change.getEndAbsBounds()); } } Loading Loading @@ -210,22 +206,8 @@ class ActivityEmbeddingAnimationRunner { @NonNull BiFunction<TransitionInfo.Change, Rect, Animation> animationProvider, @NonNull Rect wholeAnimationBounds) { final Animation animation = animationProvider.apply(change, wholeAnimationBounds); final Rect bounds = new Rect(change.getEndAbsBounds()); final Point offset = change.getEndRelOffset(); bounds.offsetTo(offset.x, offset.y); if (bounds.left == wholeAnimationBounds.left && bounds.right != wholeAnimationBounds.right) { // This is the left split of the whole animation window. return new ActivityEmbeddingAnimationAdapter.SplitAdapter(animation, change, true /* isLeftHalf */, wholeAnimationBounds.width()); } else if (bounds.left != wholeAnimationBounds.left && bounds.right == wholeAnimationBounds.right) { // This is the right split of the whole animation window. return new ActivityEmbeddingAnimationAdapter.SplitAdapter(animation, change, false /* isLeftHalf */, wholeAnimationBounds.width()); } // Open/close window that fills the whole animation. return new ActivityEmbeddingAnimationAdapter(animation, change); return new ActivityEmbeddingAnimationAdapter(animation, change, change.getLeash(), wholeAnimationBounds); } @NonNull Loading libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java +8 −4 Original line number Diff line number Diff line Loading @@ -185,8 +185,10 @@ class ActivityEmbeddingAnimationSpec { animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter ? R.anim.task_fragment_open_enter : R.anim.task_fragment_open_exit); final Rect bounds = change.getEndAbsBounds(); animation.initialize(bounds.width(), bounds.height(), // Use the whole animation bounds instead of the change bounds, so that when multiple change // targets are opening at the same time, the animation applied to each will be the same. // Otherwise, we may see gap between the activities that are launching together. animation.initialize(wholeAnimationBounds.width(), wholeAnimationBounds.height(), wholeAnimationBounds.width(), wholeAnimationBounds.height()); animation.scaleCurrentDuration(mTransitionAnimationScaleSetting); return animation; Loading @@ -203,8 +205,10 @@ class ActivityEmbeddingAnimationSpec { animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter ? R.anim.task_fragment_close_enter : R.anim.task_fragment_close_exit); final Rect bounds = change.getEndAbsBounds(); animation.initialize(bounds.width(), bounds.height(), // Use the whole animation bounds instead of the change bounds, so that when multiple change // targets are closing at the same time, the animation applied to each will be the same. // Otherwise, we may see gap between the activities that are finishing together. animation.initialize(wholeAnimationBounds.width(), wholeAnimationBounds.height(), wholeAnimationBounds.width(), wholeAnimationBounds.height()); animation.scaleCurrentDuration(mTransitionAnimationScaleSetting); return animation; Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java +37 −63 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.wm.shell.activityembedding; import static android.graphics.Matrix.MSCALE_X; import static android.graphics.Matrix.MTRANS_X; import static android.graphics.Matrix.MTRANS_Y; Loading @@ -42,31 +41,45 @@ class ActivityEmbeddingAnimationAdapter { */ private static final int LAYER_NO_OVERRIDE = -1; @NonNull final Animation mAnimation; @NonNull final TransitionInfo.Change mChange; @NonNull final SurfaceControl mLeash; /** Area in absolute coordinate that the animation surface shouldn't go beyond. */ @NonNull private final Rect mWholeAnimationBounds = new Rect(); @NonNull final Transformation mTransformation = new Transformation(); @NonNull final float[] mMatrix = new float[9]; @NonNull final float[] mVecs = new float[4]; @NonNull final Rect mRect = new Rect(); private boolean mIsFirstFrame = true; private int mOverrideLayer = LAYER_NO_OVERRIDE; ActivityEmbeddingAnimationAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change) { this(animation, change, change.getLeash()); this(animation, change, change.getLeash(), change.getEndAbsBounds()); } /** * @param leash the surface to animate, which is not necessary the same as * {@link TransitionInfo.Change#getLeash()}, it can be a screenshot for example. * @param wholeAnimationBounds area in absolute coordinate that the animation surface shouldn't * go beyond. */ ActivityEmbeddingAnimationAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change, @NonNull SurfaceControl leash) { @NonNull TransitionInfo.Change change, @NonNull SurfaceControl leash, @NonNull Rect wholeAnimationBounds) { mAnimation = animation; mChange = change; mLeash = leash; mWholeAnimationBounds.set(wholeAnimationBounds); } /** Loading Loading @@ -96,23 +109,31 @@ class ActivityEmbeddingAnimationAdapter { /** To be overridden by subclasses to adjust the animation surface change. */ void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) { // Update the surface position and alpha. final Point offset = mChange.getEndRelOffset(); mTransformation.getMatrix().postTranslate(offset.x, offset.y); t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix); t.setAlpha(mLeash, mTransformation.getAlpha()); // Get current animation position. // Get current surface bounds in absolute coordinate. // positionX/Y are in local coordinate, so minus the local offset to get the slide amount. final int positionX = Math.round(mMatrix[MTRANS_X]); final int positionY = Math.round(mMatrix[MTRANS_Y]); // The exiting surface starts at position: Change#getEndRelOffset() and moves with // positionX varying. Offset our crop region by the amount we have slided so crop // regions stays exactly on the original container in split. final int cropOffsetX = offset.x - positionX; final int cropOffsetY = offset.y - positionY; final Rect cropRect = new Rect(); cropRect.set(mChange.getEndAbsBounds()); // Because window crop uses absolute position. cropRect.offsetTo(0, 0); cropRect.offset(cropOffsetX, cropOffsetY); final Rect cropRect = new Rect(mChange.getEndAbsBounds()); cropRect.offset(positionX - offset.x, positionY - offset.y); // Store the current offset of the surface top left from (0,0) in absolute coordinate. final int offsetX = cropRect.left; final int offsetY = cropRect.top; // Intersect to make sure the animation happens within the whole animation bounds. if (!cropRect.intersect(mWholeAnimationBounds)) { // Hide the surface when it is outside of the animation area. t.setAlpha(mLeash, 0); } // cropRect is in absolute coordinate, so we need to translate it to surface top left. cropRect.offset(-offsetX, -offsetY); t.setCrop(mLeash, cropRect); } Loading @@ -126,53 +147,6 @@ class ActivityEmbeddingAnimationAdapter { return mAnimation.computeDurationHint(); } /** * Should be used when the {@link TransitionInfo.Change} is in split with others, and wants to * animate together as one. This adapter will offset the animation leash to make the animate of * two windows look like a single window. */ static class SplitAdapter extends ActivityEmbeddingAnimationAdapter { private final boolean mIsLeftHalf; private final int mWholeAnimationWidth; /** * @param isLeftHalf whether this is the left half of the animation. * @param wholeAnimationWidth the whole animation windows width. */ SplitAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change, boolean isLeftHalf, int wholeAnimationWidth) { super(animation, change); mIsLeftHalf = isLeftHalf; mWholeAnimationWidth = wholeAnimationWidth; if (wholeAnimationWidth == 0) { throw new IllegalArgumentException("SplitAdapter must provide wholeAnimationWidth"); } } @Override void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) { final Point offset = mChange.getEndRelOffset(); float posX = offset.x; final float posY = offset.y; // This window is half of the whole animation window. Offset left/right to make it // look as one with the other half. mTransformation.getMatrix().getValues(mMatrix); final int changeWidth = mChange.getEndAbsBounds().width(); final float scaleX = mMatrix[MSCALE_X]; final float totalOffset = mWholeAnimationWidth * (1 - scaleX) / 2; final float curOffset = changeWidth * (1 - scaleX) / 2; final float offsetDiff = totalOffset - curOffset; if (mIsLeftHalf) { posX += offsetDiff; } else { posX -= offsetDiff; } mTransformation.getMatrix().postTranslate(posX, posY); t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix); t.setAlpha(mLeash, mTransformation.getAlpha()); } } /** * Should be used for the animation of the snapshot of a {@link TransitionInfo.Change} that has * size change. Loading @@ -181,7 +155,7 @@ class ActivityEmbeddingAnimationAdapter { SnapshotAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change, @NonNull SurfaceControl snapshotLeash) { super(animation, change, snapshotLeash); super(animation, change, snapshotLeash, change.getEndAbsBounds()); } @Override Loading
libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java +4 −22 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET; import android.animation.Animator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; import android.util.Log; Loading Loading @@ -169,15 +168,12 @@ class ActivityEmbeddingAnimationRunner { final Rect openingWholeScreenBounds = new Rect(); final Rect closingWholeScreenBounds = new Rect(); for (TransitionInfo.Change change : info.getChanges()) { final Rect bounds = new Rect(change.getEndAbsBounds()); final Point offset = change.getEndRelOffset(); bounds.offsetTo(offset.x, offset.y); if (Transitions.isOpeningType(change.getMode())) { openingChanges.add(change); openingWholeScreenBounds.union(bounds); openingWholeScreenBounds.union(change.getEndAbsBounds()); } else { closingChanges.add(change); closingWholeScreenBounds.union(bounds); closingWholeScreenBounds.union(change.getEndAbsBounds()); } } Loading Loading @@ -210,22 +206,8 @@ class ActivityEmbeddingAnimationRunner { @NonNull BiFunction<TransitionInfo.Change, Rect, Animation> animationProvider, @NonNull Rect wholeAnimationBounds) { final Animation animation = animationProvider.apply(change, wholeAnimationBounds); final Rect bounds = new Rect(change.getEndAbsBounds()); final Point offset = change.getEndRelOffset(); bounds.offsetTo(offset.x, offset.y); if (bounds.left == wholeAnimationBounds.left && bounds.right != wholeAnimationBounds.right) { // This is the left split of the whole animation window. return new ActivityEmbeddingAnimationAdapter.SplitAdapter(animation, change, true /* isLeftHalf */, wholeAnimationBounds.width()); } else if (bounds.left != wholeAnimationBounds.left && bounds.right == wholeAnimationBounds.right) { // This is the right split of the whole animation window. return new ActivityEmbeddingAnimationAdapter.SplitAdapter(animation, change, false /* isLeftHalf */, wholeAnimationBounds.width()); } // Open/close window that fills the whole animation. return new ActivityEmbeddingAnimationAdapter(animation, change); return new ActivityEmbeddingAnimationAdapter(animation, change, change.getLeash(), wholeAnimationBounds); } @NonNull Loading
libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java +8 −4 Original line number Diff line number Diff line Loading @@ -185,8 +185,10 @@ class ActivityEmbeddingAnimationSpec { animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter ? R.anim.task_fragment_open_enter : R.anim.task_fragment_open_exit); final Rect bounds = change.getEndAbsBounds(); animation.initialize(bounds.width(), bounds.height(), // Use the whole animation bounds instead of the change bounds, so that when multiple change // targets are opening at the same time, the animation applied to each will be the same. // Otherwise, we may see gap between the activities that are launching together. animation.initialize(wholeAnimationBounds.width(), wholeAnimationBounds.height(), wholeAnimationBounds.width(), wholeAnimationBounds.height()); animation.scaleCurrentDuration(mTransitionAnimationScaleSetting); return animation; Loading @@ -203,8 +205,10 @@ class ActivityEmbeddingAnimationSpec { animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter ? R.anim.task_fragment_close_enter : R.anim.task_fragment_close_exit); final Rect bounds = change.getEndAbsBounds(); animation.initialize(bounds.width(), bounds.height(), // Use the whole animation bounds instead of the change bounds, so that when multiple change // targets are closing at the same time, the animation applied to each will be the same. // Otherwise, we may see gap between the activities that are finishing together. animation.initialize(wholeAnimationBounds.width(), wholeAnimationBounds.height(), wholeAnimationBounds.width(), wholeAnimationBounds.height()); animation.scaleCurrentDuration(mTransitionAnimationScaleSetting); return animation; Loading