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

Commit ca9b6775 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Using hardware canvas for profiling Views"

parents 37ed703d c1043207
Loading
Loading
Loading
Loading
+79 −88
Original line number Diff line number Diff line
@@ -528,18 +528,43 @@ public class ViewDebug {
    /** @hide */
    public static void profileViewAndChildren(final View view, BufferedWriter out)
            throws IOException {
        profileViewAndChildren(view, out, true);
        RenderNode node = RenderNode.create("ViewDebug", null);
        profileViewAndChildren(view, node, out, true);
        node.destroy();
    }

    private static void profileViewAndChildren(final View view, BufferedWriter out, boolean root)
            throws IOException {

    private static void profileViewAndChildren(View view, RenderNode node, BufferedWriter out,
            boolean root) throws IOException {
        long durationMeasure =
                (root || (view.mPrivateFlags & View.PFLAG_MEASURED_DIMENSION_SET) != 0)
                        ? profileViewOperation(view, new ViewOperation<Void>() {
                    public Void[] pre() {
                        ? profileViewMeasure(view) : 0;
        long durationLayout =
                (root || (view.mPrivateFlags & View.PFLAG_LAYOUT_REQUIRED) != 0)
                        ? profileViewLayout(view) : 0;
        long durationDraw =
                (root || !view.willNotDraw() || (view.mPrivateFlags & View.PFLAG_DRAWN) != 0)
                        ? profileViewDraw(view, node) : 0;

        out.write(String.valueOf(durationMeasure));
        out.write(' ');
        out.write(String.valueOf(durationLayout));
        out.write(' ');
        out.write(String.valueOf(durationDraw));
        out.newLine();
        if (view instanceof ViewGroup) {
            ViewGroup group = (ViewGroup) view;
            final int count = group.getChildCount();
            for (int i = 0; i < count; i++) {
                profileViewAndChildren(group.getChildAt(i), node, out, false);
            }
        }
    }

    private static long profileViewMeasure(final View view) {
        return profileViewOperation(view, new ViewOperation() {
            @Override
            public void pre() {
                forceLayout(view);
                        return null;
            }

            private void forceLayout(View view) {
@@ -553,98 +578,64 @@ public class ViewDebug {
                }
            }

                    public void run(Void... data) {
            @Override
            public void run() {
                view.measure(view.mOldWidthMeasureSpec, view.mOldHeightMeasureSpec);
            }

                    public void post(Void... data) {
                    }
                })
                        : 0;
        long durationLayout =
                (root || (view.mPrivateFlags & View.PFLAG_LAYOUT_REQUIRED) != 0)
                        ? profileViewOperation(view, new ViewOperation<Void>() {
                    public Void[] pre() {
                        return null;
                    }

                    public void run(Void... data) {
                        view.layout(view.mLeft, view.mTop, view.mRight, view.mBottom);
        });
    }

                    public void post(Void... data) {
                    }
                }) : 0;
        long durationDraw =
                (root || !view.willNotDraw() || (view.mPrivateFlags & View.PFLAG_DRAWN) != 0)
                        ? profileViewOperation(view, new ViewOperation<Object>() {
                    public Object[] pre() {
                        final DisplayMetrics metrics =
                                (view != null && view.getResources() != null) ?
                                        view.getResources().getDisplayMetrics() : null;
                        final Bitmap bitmap = metrics != null ?
                                Bitmap.createBitmap(metrics, metrics.widthPixels,
                                        metrics.heightPixels, Bitmap.Config.RGB_565) : null;
                        final Canvas canvas = bitmap != null ? new Canvas(bitmap) : null;
                        return new Object[] {
                                bitmap, canvas
                        };
    private static long profileViewLayout(View view) {
        return profileViewOperation(view,
                () -> view.layout(view.mLeft, view.mTop, view.mRight, view.mBottom));
    }

                    public void run(Object... data) {
                        if (data[1] != null) {
                            view.draw((Canvas) data[1]);
                        }
    private static long profileViewDraw(View view, RenderNode node) {
        DisplayMetrics dm = view.getResources().getDisplayMetrics();
        if (dm == null) {
            return 0;
        }

                    public void post(Object... data) {
                        if (data[1] != null) {
                            ((Canvas) data[1]).setBitmap(null);
                        }
                        if (data[0] != null) {
                            ((Bitmap) data[0]).recycle();
                        }
        if (view.isHardwareAccelerated()) {
            DisplayListCanvas canvas = node.start(dm.widthPixels, dm.heightPixels);
            try {
                return profileViewOperation(view, () -> view.draw(canvas));
            } finally {
                node.end(canvas);
            }
                }) : 0;
        out.write(String.valueOf(durationMeasure));
        out.write(' ');
        out.write(String.valueOf(durationLayout));
        out.write(' ');
        out.write(String.valueOf(durationDraw));
        out.newLine();
        if (view instanceof ViewGroup) {
            ViewGroup group = (ViewGroup) view;
            final int count = group.getChildCount();
            for (int i = 0; i < count; i++) {
                profileViewAndChildren(group.getChildAt(i), out, false);
        } else {
            Bitmap bitmap = Bitmap.createBitmap(
                    dm, dm.widthPixels, dm.heightPixels, Bitmap.Config.RGB_565);
            Canvas canvas = new Canvas(bitmap);
            try {
                return profileViewOperation(view, () -> view.draw(canvas));
            } finally {
                canvas.setBitmap(null);
                bitmap.recycle();
            }
        }
    }

    interface ViewOperation<T> {
        T[] pre();
        void run(T... data);
        void post(T... data);
    interface ViewOperation {
        default void pre() {}

        void run();
    }

    private static <T> long profileViewOperation(View view, final ViewOperation<T> operation) {
    private static long profileViewOperation(View view, final ViewOperation operation) {
        final CountDownLatch latch = new CountDownLatch(1);
        final long[] duration = new long[1];

        view.post(new Runnable() {
            public void run() {
        view.post(() -> {
            try {
                    T[] data = operation.pre();
                operation.pre();
                long start = Debug.threadCpuTimeNanos();
                //noinspection unchecked
                    operation.run(data);
                operation.run();
                duration[0] = Debug.threadCpuTimeNanos() - start;
                    //noinspection unchecked
                    operation.post(data);
            } finally {
                latch.countDown();
            }
            }
        });

        try {