Loading core/java/android/view/ViewDebug.java +79 −88 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 { Loading Loading
core/java/android/view/ViewDebug.java +79 −88 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 { Loading