Loading core/java/android/view/View.java +1 −1 Original line number Diff line number Diff line Loading @@ -6493,7 +6493,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * Create a snapshot of the view into a bitmap. We should probably make * some form of this public, but should think about the API. */ Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor) { Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) { int width = mRight - mLeft; int height = mBottom - mTop; Loading core/java/android/view/ViewDebug.java +97 −20 Original line number Diff line number Diff line Loading @@ -23,9 +23,12 @@ import android.content.res.Resources; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; import android.os.Environment; import android.os.Debug; import android.os.RemoteException; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.BufferedWriter; import java.io.FileWriter; Loading Loading @@ -345,6 +348,7 @@ public class ViewDebug { private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE"; private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT"; private static final String REMOTE_PROFILE = "PROFILE"; private static final String REMOTE_COMMAND_CAPTURE_LAYERS = "CAPTURE_LAYERS"; private static HashMap<Class<?>, Field[]> sFieldsForClasses; private static HashMap<Class<?>, Method[]> sMethodsForClasses; Loading Loading @@ -846,6 +850,8 @@ public class ViewDebug { if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) { dump(view, clientStream); } else if (REMOTE_COMMAND_CAPTURE_LAYERS.equalsIgnoreCase(command)) { captureLayers(view, new DataOutputStream(clientStream)); } else { final String[] params = parameters.split(" "); if (REMOTE_COMMAND_CAPTURE.equalsIgnoreCase(command)) { Loading Loading @@ -1017,24 +1023,109 @@ public class ViewDebug { return duration[0]; } private static void captureLayers(View root, final DataOutputStream clientStream) throws IOException { try { Rect outRect = new Rect(); try { root.mAttachInfo.mSession.getDisplayFrame(root.mAttachInfo.mWindow, outRect); } catch (RemoteException e) { // Ignore } clientStream.writeInt(outRect.width()); clientStream.writeInt(outRect.height()); captureViewLayer(root, clientStream); clientStream.write(2); } finally { clientStream.close(); } } private static void captureViewLayer(View view, DataOutputStream clientStream) throws IOException { if ((view.mPrivateFlags & View.SKIP_DRAW) != View.SKIP_DRAW) { final int id = view.getId(); String name = view.getClass().getSimpleName(); if (id != View.NO_ID) { name = resolveId(view.getContext(), id).toString(); } clientStream.write(1); clientStream.writeUTF(name); clientStream.writeByte(view.getVisibility() == View.VISIBLE ? 1 : 0); int[] position = new int[2]; // XXX: Should happen on the UI thread view.getLocationInWindow(position); clientStream.writeInt(position[0]); clientStream.writeInt(position[1]); clientStream.flush(); Bitmap b = performViewCapture(view, true); if (b != null) { ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(b.getWidth() * b.getHeight() * 2); b.compress(Bitmap.CompressFormat.PNG, 100, arrayOut); clientStream.writeInt(arrayOut.size()); arrayOut.writeTo(clientStream); } clientStream.flush(); } if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; int count = group.getChildCount(); for (int i = 0; i < count; i++) { captureViewLayer(group.getChildAt(i), clientStream); } } } private static void capture(View root, final OutputStream clientStream, String parameter) throws IOException { final View captureView = findView(root, parameter); Bitmap b = performViewCapture(captureView, false); if (b != null) { BufferedOutputStream out = null; try { out = new BufferedOutputStream(clientStream, 32 * 1024); b.compress(Bitmap.CompressFormat.PNG, 100, out); out.flush(); } finally { if (out != null) { out.close(); } b.recycle(); } } else { Log.w("View", "Failed to create capture bitmap!"); clientStream.close(); } } private static Bitmap performViewCapture(final View captureView, final boolean skpiChildren) { if (captureView != null) { final CountDownLatch latch = new CountDownLatch(1); final Bitmap[] cache = new Bitmap[1]; root.post(new Runnable() { captureView.post(new Runnable() { public void run() { try { cache[0] = captureView.createSnapshot( Bitmap.Config.ARGB_8888, 0); Bitmap.Config.ARGB_8888, 0, skpiChildren); } catch (OutOfMemoryError e) { try { cache[0] = captureView.createSnapshot( Bitmap.Config.ARGB_4444, 0); Bitmap.Config.ARGB_4444, 0, skpiChildren); } catch (OutOfMemoryError e2) { Log.w("View", "Out of memory for bitmap"); } Loading @@ -1046,28 +1137,14 @@ public class ViewDebug { try { latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS); if (cache[0] != null) { BufferedOutputStream out = null; try { out = new BufferedOutputStream(clientStream, 32 * 1024); cache[0].compress(Bitmap.CompressFormat.PNG, 100, out); out.flush(); } finally { if (out != null) { out.close(); } cache[0].recycle(); } } else { Log.w("View", "Failed to create capture bitmap!"); clientStream.close(); } return cache[0]; } catch (InterruptedException e) { Log.w("View", "Could not complete the capture of the view " + captureView); Thread.currentThread().interrupt(); } } return null; } private static void dump(View root, OutputStream clientStream) throws IOException { Loading core/java/android/view/ViewGroup.java +13 −0 Original line number Diff line number Diff line Loading @@ -1272,6 +1272,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } @Override Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) { int oldCount = mChildrenCount; if (skipChildren) { mChildrenCount = 0; } Bitmap b = super.createSnapshot(quality, backgroundColor, skipChildren); mChildrenCount = oldCount; return b; } /** * {@inheritDoc} */ Loading Loading
core/java/android/view/View.java +1 −1 Original line number Diff line number Diff line Loading @@ -6493,7 +6493,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * Create a snapshot of the view into a bitmap. We should probably make * some form of this public, but should think about the API. */ Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor) { Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) { int width = mRight - mLeft; int height = mBottom - mTop; Loading
core/java/android/view/ViewDebug.java +97 −20 Original line number Diff line number Diff line Loading @@ -23,9 +23,12 @@ import android.content.res.Resources; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; import android.os.Environment; import android.os.Debug; import android.os.RemoteException; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.BufferedWriter; import java.io.FileWriter; Loading Loading @@ -345,6 +348,7 @@ public class ViewDebug { private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE"; private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT"; private static final String REMOTE_PROFILE = "PROFILE"; private static final String REMOTE_COMMAND_CAPTURE_LAYERS = "CAPTURE_LAYERS"; private static HashMap<Class<?>, Field[]> sFieldsForClasses; private static HashMap<Class<?>, Method[]> sMethodsForClasses; Loading Loading @@ -846,6 +850,8 @@ public class ViewDebug { if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) { dump(view, clientStream); } else if (REMOTE_COMMAND_CAPTURE_LAYERS.equalsIgnoreCase(command)) { captureLayers(view, new DataOutputStream(clientStream)); } else { final String[] params = parameters.split(" "); if (REMOTE_COMMAND_CAPTURE.equalsIgnoreCase(command)) { Loading Loading @@ -1017,24 +1023,109 @@ public class ViewDebug { return duration[0]; } private static void captureLayers(View root, final DataOutputStream clientStream) throws IOException { try { Rect outRect = new Rect(); try { root.mAttachInfo.mSession.getDisplayFrame(root.mAttachInfo.mWindow, outRect); } catch (RemoteException e) { // Ignore } clientStream.writeInt(outRect.width()); clientStream.writeInt(outRect.height()); captureViewLayer(root, clientStream); clientStream.write(2); } finally { clientStream.close(); } } private static void captureViewLayer(View view, DataOutputStream clientStream) throws IOException { if ((view.mPrivateFlags & View.SKIP_DRAW) != View.SKIP_DRAW) { final int id = view.getId(); String name = view.getClass().getSimpleName(); if (id != View.NO_ID) { name = resolveId(view.getContext(), id).toString(); } clientStream.write(1); clientStream.writeUTF(name); clientStream.writeByte(view.getVisibility() == View.VISIBLE ? 1 : 0); int[] position = new int[2]; // XXX: Should happen on the UI thread view.getLocationInWindow(position); clientStream.writeInt(position[0]); clientStream.writeInt(position[1]); clientStream.flush(); Bitmap b = performViewCapture(view, true); if (b != null) { ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(b.getWidth() * b.getHeight() * 2); b.compress(Bitmap.CompressFormat.PNG, 100, arrayOut); clientStream.writeInt(arrayOut.size()); arrayOut.writeTo(clientStream); } clientStream.flush(); } if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; int count = group.getChildCount(); for (int i = 0; i < count; i++) { captureViewLayer(group.getChildAt(i), clientStream); } } } private static void capture(View root, final OutputStream clientStream, String parameter) throws IOException { final View captureView = findView(root, parameter); Bitmap b = performViewCapture(captureView, false); if (b != null) { BufferedOutputStream out = null; try { out = new BufferedOutputStream(clientStream, 32 * 1024); b.compress(Bitmap.CompressFormat.PNG, 100, out); out.flush(); } finally { if (out != null) { out.close(); } b.recycle(); } } else { Log.w("View", "Failed to create capture bitmap!"); clientStream.close(); } } private static Bitmap performViewCapture(final View captureView, final boolean skpiChildren) { if (captureView != null) { final CountDownLatch latch = new CountDownLatch(1); final Bitmap[] cache = new Bitmap[1]; root.post(new Runnable() { captureView.post(new Runnable() { public void run() { try { cache[0] = captureView.createSnapshot( Bitmap.Config.ARGB_8888, 0); Bitmap.Config.ARGB_8888, 0, skpiChildren); } catch (OutOfMemoryError e) { try { cache[0] = captureView.createSnapshot( Bitmap.Config.ARGB_4444, 0); Bitmap.Config.ARGB_4444, 0, skpiChildren); } catch (OutOfMemoryError e2) { Log.w("View", "Out of memory for bitmap"); } Loading @@ -1046,28 +1137,14 @@ public class ViewDebug { try { latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS); if (cache[0] != null) { BufferedOutputStream out = null; try { out = new BufferedOutputStream(clientStream, 32 * 1024); cache[0].compress(Bitmap.CompressFormat.PNG, 100, out); out.flush(); } finally { if (out != null) { out.close(); } cache[0].recycle(); } } else { Log.w("View", "Failed to create capture bitmap!"); clientStream.close(); } return cache[0]; } catch (InterruptedException e) { Log.w("View", "Could not complete the capture of the view " + captureView); Thread.currentThread().interrupt(); } } return null; } private static void dump(View root, OutputStream clientStream) throws IOException { Loading
core/java/android/view/ViewGroup.java +13 −0 Original line number Diff line number Diff line Loading @@ -1272,6 +1272,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } @Override Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) { int oldCount = mChildrenCount; if (skipChildren) { mChildrenCount = 0; } Bitmap b = super.createSnapshot(quality, backgroundColor, skipChildren); mChildrenCount = oldCount; return b; } /** * {@inheritDoc} */ Loading