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

Commit 94502428 authored by Stefan Andonian's avatar Stefan Andonian Committed by Android (Google) Code Review
Browse files

Merge "Copying ViewCapture from last frame when possible." into tm-qpr-dev

parents c766a8c9 7308c390
Loading
Loading
Loading
Loading
+118 −42
Original line number Diff line number Diff line
@@ -67,6 +67,10 @@ public class ViewCapture {

    private static final String TAG = "ViewCapture";

    // These flags are copies of two private flags in the View class.
    private static final int PFLAG_INVALIDATED = 0x80000000;
    private static final int PFLAG_DIRTY_MASK = 0x00200000;

    // Number of frames to keep in memory
    private static final int MEMORY_SIZE = 2000;
    // Initial size of the reference pool. This is at least be 5 * total number of views in
@@ -187,6 +191,7 @@ public class ViewCapture {
        private final ViewRef mViewRef = new ViewRef();

        private int mFrameIndexBg = -1;
        private boolean mIsFirstFrame = true;
        private final long[] mFrameTimesBg = new long[MEMORY_SIZE];
        private final ViewPropertyRef[] mNodesBg = new ViewPropertyRef[MEMORY_SIZE];

@@ -205,6 +210,7 @@ public class ViewCapture {
            Message m = Message.obtain(mHandler);
            m.obj = mViewRef.next;
            mHandler.sendMessage(m);
            mIsFirstFrame = false;
            Trace.endSection();
        }

@@ -214,9 +220,9 @@ public class ViewCapture {
         */
        @WorkerThread
        private boolean captureViewPropertiesBg(Message msg) {
            ViewRef start = (ViewRef) msg.obj;
            ViewRef viewRefStart = (ViewRef) msg.obj;
            long time = msg.getWhen();
            if (start == null) {
            if (viewRefStart == null) {
                return false;
            }
            mFrameIndexBg++;
@@ -227,12 +233,11 @@ public class ViewCapture {

            ViewPropertyRef recycle = mNodesBg[mFrameIndexBg];

            ViewPropertyRef result = null;
            ViewPropertyRef resultStart = null;
            ViewPropertyRef resultEnd = null;

            ViewRef current = start;
            ViewRef last = start;
            while (current != null) {
            ViewRef viewRefEnd = viewRefStart;
            while (viewRefEnd != null) {
                ViewPropertyRef propertyRef = recycle;
                if (propertyRef == null) {
                    propertyRef = new ViewPropertyRef();
@@ -241,24 +246,64 @@ public class ViewCapture {
                    propertyRef.next = null;
                }

                propertyRef.transfer(current);
                last = current;
                current = current.next;
                ViewPropertyRef copy = null;
                if (viewRefEnd.childCount < 0) {
                    copy = findInLastFrame(viewRefEnd.view.hashCode());
                    viewRefEnd.childCount = (copy != null) ? copy.childCount : 0;
                }
                viewRefEnd.transferTo(propertyRef);

                if (resultStart == null) {
                    resultStart = propertyRef;
                    resultEnd = resultStart;
                } else {
                    resultEnd.next = propertyRef;
                    resultEnd = resultEnd.next;
                }

                if (copy != null) {
                    int pending = copy.childCount;
                    while (pending > 0) {
                        copy = copy.next;
                        pending = pending - 1 + copy.childCount;

                if (result == null) {
                    result = propertyRef;
                    resultEnd = result;
                        propertyRef = recycle;
                        if (propertyRef == null) {
                            propertyRef = new ViewPropertyRef();
                        } else {
                            recycle = recycle.next;
                            propertyRef.next = null;
                        }

                        copy.transferTo(propertyRef);

                        resultEnd.next = propertyRef;
                    resultEnd = propertyRef;
                        resultEnd = resultEnd.next;
                    }
                }

                if (viewRefEnd.next == null) {
                    // The compiler will complain about using a non-final variable from
                    // an outer class in a lambda if we pass in viewRefEnd directly.
                    final ViewRef finalViewRefEnd = viewRefEnd;
                    MAIN_EXECUTOR.execute(() -> addToPool(viewRefStart, finalViewRefEnd));
                    break;
                }
                viewRefEnd = viewRefEnd.next;
            }
            mNodesBg[mFrameIndexBg] = result;
            ViewRef end = last;
            MAIN_EXECUTOR.execute(() -> addToPool(start, end));
            mNodesBg[mFrameIndexBg] = resultStart;
            return true;
        }

        private ViewPropertyRef findInLastFrame(int hashCode) {
            int lastFrameIndex = (mFrameIndexBg == 0) ? MEMORY_SIZE - 1 : mFrameIndexBg - 1;
            ViewPropertyRef viewPropertyRef = mNodesBg[lastFrameIndex];
            while (viewPropertyRef != null && viewPropertyRef.hashCode != hashCode) {
                viewPropertyRef = viewPropertyRef.next;
            }
            return viewPropertyRef;
        }

        void attachToRoot() {
            if (mRoot.isAttachedToWindow()) {
                mRoot.getViewTreeObserver().addOnDrawListener(this);
@@ -314,8 +359,16 @@ public class ViewCapture {
            ref.view = view;
            start.next = ref;
            if (view instanceof ViewGroup) {
                ViewRef result = ref;
                ViewGroup parent = (ViewGroup) view;
                // If a view has not changed since the last frame, we will copy
                // its children from the last processed frame's data.
                if ((view.mPrivateFlags & (PFLAG_INVALIDATED | PFLAG_DIRTY_MASK)) == 0
                        && !mIsFirstFrame) {
                    // A negative child count is the signal to copy this view from the last frame.
                    ref.childCount = -parent.getChildCount();
                    return ref;
                }
                ViewRef result = ref;
                int childCount = ref.childCount = parent.getChildCount();
                for (int i = 0; i < childCount; i++) {
                    result = captureViewTree(parent.getChildAt(i), result);
@@ -349,31 +402,27 @@ public class ViewCapture {

        public ViewPropertyRef next;

        public void transfer(ViewRef viewRef) {
            childCount = viewRef.childCount;

            View view = viewRef.view;
            viewRef.view = null;

            clazz = view.getClass();
            hashCode = view.hashCode();
            id = view.getId();
            left = view.getLeft();
            top = view.getTop();
            right = view.getRight();
            bottom = view.getBottom();
            scrollX = view.getScrollX();
            scrollY = view.getScrollY();

            translateX = view.getTranslationX();
            translateY = view.getTranslationY();
            scaleX = view.getScaleX();
            scaleY = view.getScaleY();
            alpha = view.getAlpha();

            visibility = view.getVisibility();
            willNotDraw = view.willNotDraw();
            elevation = view.getElevation();
        public void transferTo(ViewPropertyRef out) {
            out.clazz = this.clazz;
            out.hashCode = this.hashCode;
            out.childCount = this.childCount;
            out.id = this.id;
            out.left = this.left;
            out.top = this.top;
            out.right = this.right;
            out.bottom = this.bottom;
            out.scrollX = this.scrollX;
            out.scrollY = this.scrollY;
            out.scaleX = this.scaleX;
            out.scaleY = this.scaleY;
            out.translateX = this.translateX;
            out.translateY = this.translateY;
            out.alpha = this.alpha;
            out.visibility = this.visibility;
            out.willNotDraw = this.willNotDraw;
            out.clipChildren = this.clipChildren;
            out.next = this.next;
            out.elevation = this.elevation;
        }

        /**
@@ -420,6 +469,33 @@ public class ViewCapture {
        public View view;
        public int childCount = 0;
        public ViewRef next;

        public void transferTo(ViewPropertyRef out) {
            out.childCount = this.childCount;

            View view = this.view;
            this.view = null;

            out.clazz = view.getClass();
            out.hashCode = view.hashCode();
            out.id = view.getId();
            out.left = view.getLeft();
            out.top = view.getTop();
            out.right = view.getRight();
            out.bottom = view.getBottom();
            out.scrollX = view.getScrollX();
            out.scrollY = view.getScrollY();

            out.translateX = view.getTranslationX();
            out.translateY = view.getTranslationY();
            out.scaleX = view.getScaleX();
            out.scaleY = view.getScaleY();
            out.alpha = view.getAlpha();
            out.elevation = view.getElevation();

            out.visibility = view.getVisibility();
            out.willNotDraw = view.willNotDraw();
        }
    }

    private static final class ViewIdProvider {