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

Commit 08ff5c14 authored by George Mount's avatar George Mount Committed by Android (Google) Code Review
Browse files

Merge "Fixed OOM due to visibility transitions." into lmp-dev

parents 94e7e7ef 79b2781a
Loading
Loading
Loading
Loading
+5 −13
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.os.Parcelable;
import android.os.Parcelable;
import android.transition.TransitionUtils;
import android.view.View;
import android.view.View;


import java.util.List;
import java.util.List;
@@ -141,21 +142,12 @@ public abstract class SharedElementCallback {
     */
     */
    public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,
    public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,
            RectF screenBounds) {
            RectF screenBounds) {
        int bitmapWidth = Math.round(screenBounds.width());
        int bitmapHeight = Math.round(screenBounds.height());
        Bitmap bitmap = null;
        if (bitmapWidth > 0 && bitmapHeight > 0) {
        if (mTempMatrix == null) {
        if (mTempMatrix == null) {
                mTempMatrix = new Matrix();
            mTempMatrix = new Matrix(viewToGlobalMatrix);
            }
        } else {
            mTempMatrix.set(viewToGlobalMatrix);
            mTempMatrix.set(viewToGlobalMatrix);
            mTempMatrix.postTranslate(-screenBounds.left, -screenBounds.top);
            bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            canvas.concat(mTempMatrix);
            sharedElement.draw(canvas);
        }
        }
        return bitmap;
        return TransitionUtils.createViewBitmap(sharedElement, mTempMatrix, screenBounds);
    }
    }


    /**
    /**
+72 −0
Original line number Original line Diff line number Diff line
@@ -19,7 +19,14 @@ package android.transition;
import android.animation.Animator;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.AnimatorSet;
import android.animation.TypeEvaluator;
import android.animation.TypeEvaluator;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;


/**
/**
 * Static utility methods for Transitions.
 * Static utility methods for Transitions.
@@ -27,6 +34,7 @@ import android.graphics.Matrix;
 * @hide
 * @hide
 */
 */
public class TransitionUtils {
public class TransitionUtils {
    private static int MAX_IMAGE_SIZE = (1024 * 1024);


    static Animator mergeAnimators(Animator animator1, Animator animator2) {
    static Animator mergeAnimators(Animator animator1, Animator animator2) {
        if (animator1 == null) {
        if (animator1 == null) {
@@ -67,6 +75,70 @@ public class TransitionUtils {
        return transitionSet;
        return transitionSet;
    }
    }


    /**
     * Creates a View using the bitmap copy of <code>view</code>. If <code>view</code> is large,
     * the copy will use a scaled bitmap of the given view.
     *
     * @param sceneRoot The ViewGroup in which the view copy will be displayed.
     * @param view The view to create a copy of.
     * @param parent The parent of view.
     */
    public static View copyViewImage(ViewGroup sceneRoot, View view, View parent) {
        Matrix matrix = new Matrix();
        matrix.setTranslate(-parent.getScrollX(), -parent.getScrollY());
        view.transformMatrixToGlobal(matrix);
        sceneRoot.transformMatrixToLocal(matrix);
        RectF bounds = new RectF(0, 0, view.getWidth(), view.getHeight());
        matrix.mapRect(bounds);
        int left = Math.round(bounds.left);
        int top = Math.round(bounds.top);
        int right = Math.round(bounds.right);
        int bottom = Math.round(bounds.bottom);

        ImageView copy = new ImageView(view.getContext());
        copy.setScaleType(ImageView.ScaleType.CENTER_CROP);
        Bitmap bitmap = createViewBitmap(view, matrix, bounds);
        if (bitmap != null) {
            copy.setImageBitmap(bitmap);
        }
        int widthSpec = View.MeasureSpec.makeMeasureSpec(right - left, View.MeasureSpec.EXACTLY);
        int heightSpec = View.MeasureSpec.makeMeasureSpec(bottom - top, View.MeasureSpec.EXACTLY);
        copy.measure(widthSpec, heightSpec);
        copy.layout(left, top, right, bottom);
        return copy;
    }

    /**
     * Creates a Bitmap of the given view, using the Matrix matrix to transform to the local
     * coordinates. <code>matrix</code> will be modified during the bitmap creation.
     *
     * <p>If the bitmap is large, it will be scaled uniformly down to at most 1MB size.</p>
     * @param view The view to create a bitmap for.
     * @param matrix The matrix converting the view local coordinates to the coordinates that
     *               the bitmap will be displayed in. <code>matrix</code> will be modified before
     *               returning.
     * @param bounds The bounds of the bitmap in the destination coordinate system (where the
     *               view should be presented. Typically, this is matrix.mapRect(viewBounds);
     * @return A bitmap of the given view or null if bounds has no width or height.
     */
    public static Bitmap createViewBitmap(View view, Matrix matrix, RectF bounds) {
        Bitmap bitmap = null;
        int bitmapWidth = Math.round(bounds.width());
        int bitmapHeight = Math.round(bounds.height());
        if (bitmapWidth > 0 && bitmapHeight > 0) {
            float scale = Math.min(1f, ((float)MAX_IMAGE_SIZE) / (bitmapWidth * bitmapHeight));
            bitmapWidth *= scale;
            bitmapHeight *= scale;
            matrix.postTranslate(-bounds.left, -bounds.top);
            matrix.postScale(scale, scale);
            bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            canvas.concat(matrix);
            view.draw(canvas);
        }
        return bitmap;
    }

    public static class MatrixEvaluator implements TypeEvaluator<Matrix> {
    public static class MatrixEvaluator implements TypeEvaluator<Matrix> {


        float[] mTempStartValues = new float[9];
        float[] mTempStartValues = new float[9];
+8 −31
Original line number Original line Diff line number Diff line
@@ -224,11 +224,10 @@ public abstract class Visibility extends Transition {
                    }
                    }
                }
                }
            }
            }
        }
        } else if (startValues == null && visInfo.endVisibility == View.VISIBLE) {
        if (startValues == null) {
            visInfo.fadeIn = true;
            visInfo.fadeIn = true;
            visInfo.visibilityChange = true;
            visInfo.visibilityChange = true;
        } else if (endValues == null) {
        } else if (endValues == null && visInfo.startVisibility == View.VISIBLE) {
            visInfo.fadeIn = false;
            visInfo.fadeIn = false;
            visInfo.visibilityChange = true;
            visInfo.visibilityChange = true;
        }
        }
@@ -370,16 +369,14 @@ public abstract class Visibility extends Transition {
                    overlayView = startView;
                    overlayView = startView;
                } else if (startView.getParent() instanceof View) {
                } else if (startView.getParent() instanceof View) {
                    View startParent = (View) startView.getParent();
                    View startParent = (View) startView.getParent();
                    VisibilityInfo parentVisibilityInfo = null;
                    TransitionValues startParentValues = getTransitionValues(startParent, true);
                    TransitionValues endParentValues = getMatchedTransitionValues(startParent,
                    TransitionValues endParentValues = getMatchedTransitionValues(startParent,
                            true);
                            true);
                    if (endParentValues != null) {
                    VisibilityInfo parentVisibilityInfo =
                        TransitionValues startParentValues = getTransitionValues(startParent, true);
                        parentVisibilityInfo =
                            getVisibilityChangeInfo(startParentValues, endParentValues);
                            getVisibilityChangeInfo(startParentValues, endParentValues);
                    }
                    if (!parentVisibilityInfo.visibilityChange) {
                    if (parentVisibilityInfo == null || !parentVisibilityInfo.visibilityChange) {
                        overlayView = TransitionUtils.copyViewImage(sceneRoot, startView,
                        overlayView = copyViewImage(startView);
                                startParent);
                    } else if (startParent.getParent() == null) {
                    } else if (startParent.getParent() == null) {
                        int id = startParent.getId();
                        int id = startParent.getId();
                        if (id != View.NO_ID && sceneRoot.findViewById(id) != null
                        if (id != View.NO_ID && sceneRoot.findViewById(id) != null
@@ -485,26 +482,6 @@ public abstract class Visibility extends Transition {
        return null;
        return null;
    }
    }


    private View copyViewImage(View view) {
        int width = view.getWidth();
        int height = view.getHeight();
        if (width <= 0 || height <= 0) {
            return null;
        }
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        view.draw(canvas);
        final BitmapDrawable drawable = new BitmapDrawable(bitmap);

        View overlayView = new View(view.getContext());
        overlayView.setBackground(drawable);
        int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
        int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
        overlayView.measure(widthSpec, heightSpec);
        overlayView.layout(0, 0, width, height);
        return overlayView;
    }

    @Override
    @Override
    boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
    boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
        VisibilityInfo changeInfo = getVisibilityChangeInfo(oldValues, newValues);
        VisibilityInfo changeInfo = getVisibilityChangeInfo(oldValues, newValues);