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

Commit aa7fa013 authored by Winson Chung's avatar Winson Chung
Browse files

DO NOT MERGE Updating AnimationSpec and related internal APIs to use GraphicBuffer.



- This reduces the copy of the hardware bitmap when it is
  parceled/unparceled.

Bug: 38507414
Bug: 62021436
Test: Launch Overview to/from app, ensure that the header bar shows
Test: go/wm-smoke

Change-Id: I85a9a59a0a3699d1642158061d10fddef34393c3
Signed-off-by: default avatarWinson Chung <winsonc@google.com>
parent 91092767
Loading
Loading
Loading
Loading
+23 −5
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import android.annotation.TestApi;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
@@ -826,7 +828,11 @@ public class ActivityOptions {
            case ANIM_THUMBNAIL_SCALE_DOWN:
            case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
            case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
                mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
                // Unpackage the GraphicBuffer from the parceled thumbnail
                final GraphicBuffer buffer = opts.getParcelable(KEY_ANIM_THUMBNAIL);
                if (buffer != null) {
                    mThumbnail = Bitmap.createHardwareBitmap(buffer);
                }
                mStartX = opts.getInt(KEY_ANIM_START_X, 0);
                mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
                mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
@@ -919,9 +925,14 @@ public class ActivityOptions {
        return mCustomInPlaceResId;
    }

    /** @hide */
    public Bitmap getThumbnail() {
        return mThumbnail;
    /**
     * The thumbnail is copied into a hardware bitmap when it is bundled and sent to the system, so
     * it should always be backed by a GraphicBuffer on the other end.
     *
     * @hide
     */
    public GraphicBuffer getThumbnail() {
        return mThumbnail.createGraphicBufferHandle();
    }

    /** @hide */
@@ -1230,7 +1241,14 @@ public class ActivityOptions {
            case ANIM_THUMBNAIL_SCALE_DOWN:
            case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
            case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
                b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
                // Once we parcel the thumbnail for transfering over to the system, create a copy of
                // the bitmap to a hardware bitmap and pass through the GraphicBuffer
                if (mThumbnail == null) {
                    b.putParcelable(KEY_ANIM_THUMBNAIL, null);
                } else {
                    final Bitmap hwBitmap = mThumbnail.copy(Config.HARDWARE, true /* immutable */);
                    b.putParcelable(KEY_ANIM_THUMBNAIL, hwBitmap.createGraphicBufferHandle());
                }
                b.putInt(KEY_ANIM_START_X, mStartX);
                b.putInt(KEY_ANIM_START_Y, mStartY);
                b.putInt(KEY_ANIM_WIDTH, mWidth);
+7 −8
Original line number Diff line number Diff line
package android.view;

import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
@@ -15,19 +15,19 @@ import android.os.Parcelable;
 */
public class AppTransitionAnimationSpec implements Parcelable {
    public final int taskId;
    public final Bitmap bitmap;
    public final GraphicBuffer buffer;
    public final Rect rect;

    public AppTransitionAnimationSpec(int taskId, Bitmap bitmap, Rect rect) {
    public AppTransitionAnimationSpec(int taskId, GraphicBuffer buffer, Rect rect) {
        this.taskId = taskId;
        this.bitmap = bitmap;
        this.rect = rect;
        this.buffer = buffer;
    }

    public AppTransitionAnimationSpec(Parcel in) {
        taskId = in.readInt();
        bitmap = in.readParcelable(null);
        rect = in.readParcelable(null);
        buffer = in.readParcelable(null);
    }

    @Override
@@ -38,9 +38,8 @@ public class AppTransitionAnimationSpec implements Parcelable {
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(taskId);
        dest.writeParcelable(bitmap, 0 /* flags */);
        dest.writeParcelable(rect, 0 /* flags */);

        dest.writeParcelable(buffer, 0);
    }

    public static final Parcelable.Creator<AppTransitionAnimationSpec> CREATOR
@@ -56,6 +55,6 @@ public class AppTransitionAnimationSpec implements Parcelable {

    @Override
    public String toString() {
        return "{taskId: " + taskId + ", bitmap: " + bitmap + ", rect: " + rect + "}";
        return "{taskId: " + taskId + ", buffer: " + buffer + ", rect: " + rect + "}";
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import com.android.internal.policy.IShortcutService;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
@@ -96,9 +97,9 @@ interface IWindowManager
            int startHeight);
    void overridePendingAppTransitionClipReveal(int startX, int startY,
            int startWidth, int startHeight);
    void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
    void overridePendingAppTransitionThumb(in GraphicBuffer srcThumb, int startX, int startY,
            IRemoteCallback startedCallback, boolean scaleUp);
    void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
    void overridePendingAppTransitionAspectScaledThumb(in GraphicBuffer srcThumb, int startX,
            int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
            boolean scaleUp);
    /**
+13 −24
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
@@ -239,8 +240,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
        }
    });

    protected Bitmap mThumbTransitionBitmapCache;

    public RecentsImpl(Context context) {
        mContext = context;
        mHandler = new Handler();
@@ -775,14 +774,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
                }
                mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight);
            }

            // Update the transition bitmap to match the new header bar height
            if (mThumbTransitionBitmapCache == null ||
                    (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) ||
                    (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) {
                mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth,
                        mTaskBarHeight, Bitmap.Config.ARGB_8888);
            }
        }
    }

@@ -864,8 +855,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
                    mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task,
                            stackScroller.getStackScroll(), mTmpTransform, null,
                            windowOverrideRect);
                    Bitmap thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform,
                            mThumbTransitionBitmapCache);
                    GraphicBuffer thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform);
                    Rect toTaskRect = new Rect();
                    mTmpTransform.rect.round(toTaskRect);
                    specs.add(new AppTransitionAnimationSpec(task.key.id, thumbnail, toTaskRect));
@@ -887,8 +877,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
                            () -> {
                        Rect rect = new Rect();
                        toTaskRect.round(rect);
                        Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
                                mThumbTransitionBitmapCache);
                        GraphicBuffer thumbnail = drawThumbnailTransitionBitmap(toTask,
                                toTransform);
                        return Lists.newArrayList(new AppTransitionAnimationSpec(
                                toTask.key.id, thumbnail, rect));
                    });
@@ -924,19 +914,19 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
    /**
     * Draws the header of a task used for the window animation into a bitmap.
     */
    private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform,
            Bitmap thumbnail) {
    private GraphicBuffer drawThumbnailTransitionBitmap(Task toTask,
            TaskViewTransform toTransform) {
        SystemServicesProxy ssp = Recents.getSystemServices();
        if (toTransform != null && toTask.key != null) {
            synchronized (mHeaderBarLock) {
                boolean disabledInSafeMode = !toTask.isSystemApp && ssp.isInSafeMode();
                mHeaderBar.onTaskViewSizeChanged((int) toTransform.rect.width(),
                        (int) toTransform.rect.height());
                int width = (int) toTransform.rect.width();
                int height = (int) toTransform.rect.height();
                mHeaderBar.onTaskViewSizeChanged(width, height);
                if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
                    thumbnail.eraseColor(0xFFff0000);
                    return RecentsTransitionHelper.drawViewIntoGraphicBuffer(width, mTaskBarHeight,
                            null, 1f, 0xFFff0000);
                } else {
                    thumbnail.eraseColor(0);
                    Canvas c = new Canvas(thumbnail);
                    // Workaround for b/27815919, reset the callback so that we do not trigger an
                    // invalidate on the header bar as a result of updating the icon
                    Drawable icon = mHeaderBar.getIconView().getDrawable();
@@ -947,11 +937,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
                            disabledInSafeMode);
                    mHeaderBar.onTaskDataLoaded();
                    mHeaderBar.setDimAlpha(toTransform.dimAlpha);
                    mHeaderBar.draw(c);
                    c.setBitmap(null);
                    return RecentsTransitionHelper.drawViewIntoGraphicBuffer(width, mTaskBarHeight,
                            mHeaderBar, 1f, 0);
                }
            }
            return thumbnail.createAshmemBitmap();
        }
        return null;
    }
+31 −29
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
@@ -41,6 +42,7 @@ import android.view.DisplayListCanvas;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.RenderNode;
import android.view.ThreadedRenderer;
import android.view.View;

import com.android.internal.annotations.GuardedBy;
import com.android.systemui.recents.Recents;
@@ -267,8 +269,8 @@ public class RecentsTransitionHelper {
            Rect bounds) {
        mTmpTransform.fillIn(taskView);
        Task task = taskView.getTask();
        Bitmap thumbnail = RecentsTransitionHelper.composeTaskBitmap(taskView, mTmpTransform);
        return Collections.singletonList(new AppTransitionAnimationSpec(task.key.id, thumbnail,
        GraphicBuffer buffer = RecentsTransitionHelper.composeTaskBitmap(taskView, mTmpTransform);
        return Collections.singletonList(new AppTransitionAnimationSpec(task.key.id, buffer,
                bounds));
    }

@@ -349,7 +351,7 @@ public class RecentsTransitionHelper {
        return new AppTransitionAnimationSpec(task.key.id, null, taskRect);
    }

    public static Bitmap composeTaskBitmap(TaskView taskView, TaskViewTransform transform) {
    public static GraphicBuffer composeTaskBitmap(TaskView taskView, TaskViewTransform transform) {
        float scale = transform.scale;
        int fromWidth = (int) (transform.rect.width() * scale);
        int fromHeight = (int) (transform.rect.height() * scale);
@@ -357,31 +359,17 @@ public class RecentsTransitionHelper {
            Log.e(TAG, "Could not compose thumbnail for task: " + taskView.getTask() +
                    " at transform: " + transform);

            Bitmap b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
            b.eraseColor(Color.TRANSPARENT);
            return b;
            return drawViewIntoGraphicBuffer(1, 1, null, 1f, 0x00ffffff);
        } else {
            if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
                Bitmap b = Bitmap.createBitmap(fromWidth, fromHeight, Bitmap.Config.ARGB_8888);
                b.eraseColor(0xFFff0000);
                return b.createAshmemBitmap();
                return drawViewIntoGraphicBuffer(fromWidth, fromHeight, null, 1f, 0xFFff0000);
            } else {

                // Create a hardware bitmap to render the TaskView into because it may be bound to a
                // snapshot that is backed by a GraphicBuffer
                RenderNode node = RenderNode.create("RecentsTransitionHelper", null);
                node.setLeftTopRightBottom(0, 0, fromWidth, fromHeight);
                node.setClipToBounds(false);
                DisplayListCanvas c = node.start(fromWidth, fromHeight);
                c.scale(scale, scale);
                taskView.draw(c);
                node.end(c);
                return ThreadedRenderer.createHardwareBitmap(node, fromWidth, fromHeight);
                return drawViewIntoGraphicBuffer(fromWidth, fromHeight, taskView, scale, 0);
            }
        }
    }

    private static Bitmap composeHeaderBitmap(TaskView taskView,
    private static GraphicBuffer composeHeaderBitmap(TaskView taskView,
            TaskViewTransform transform) {
        float scale = transform.scale;
        int headerWidth = (int) (transform.rect.width());
@@ -390,16 +378,30 @@ public class RecentsTransitionHelper {
            return null;
        }

        Bitmap b = Bitmap.createBitmap(headerWidth, headerHeight, Bitmap.Config.ARGB_8888);
        if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
            b.eraseColor(0xFFff0000);
            return drawViewIntoGraphicBuffer(headerWidth, headerHeight, null, 1f, 0xFFff0000);
        } else {
            Canvas c = new Canvas(b);
            return drawViewIntoGraphicBuffer(headerWidth, headerHeight, taskView.mHeaderView,
                    scale, 0);
        }
    }

    public static GraphicBuffer drawViewIntoGraphicBuffer(int bufferWidth, int bufferHeight,
            View view, float scale, int eraseColor) {
        RenderNode node = RenderNode.create("RecentsTransition", null);
        node.setLeftTopRightBottom(0, 0, bufferWidth, bufferHeight);
        node.setClipToBounds(false);
        DisplayListCanvas c = node.start(bufferWidth, bufferHeight);
        c.scale(scale, scale);
            taskView.mHeaderView.draw(c);
            c.setBitmap(null);
        if (eraseColor != 0) {
            c.drawColor(eraseColor);
        }
        return b.createAshmemBitmap();
        if (view != null) {
            view.draw(c);
        }
        node.end(c);
        return ThreadedRenderer.createHardwareBitmap(node, bufferWidth, bufferHeight)
                .createGraphicBufferHandle();
    }

    /**
@@ -407,7 +409,7 @@ public class RecentsTransitionHelper {
     */
    private static AppTransitionAnimationSpec composeAnimationSpec(TaskStackView stackView,
            TaskView taskView, TaskViewTransform transform, boolean addHeaderBitmap) {
        Bitmap b = null;
        GraphicBuffer b = null;
        if (addHeaderBitmap) {
            b = composeHeaderBitmap(taskView, transform);
            if (b == null) {
Loading