Loading core/java/android/content/res/Resources.java +17 −2 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.annotation.AttrRes; import android.annotation.ColorInt; import android.annotation.StyleRes; import android.annotation.StyleableRes; import com.android.internal.util.GrowingArrayUtils; import com.android.internal.util.XmlUtils; Loading Loading @@ -62,6 +61,7 @@ import android.util.Pools.SynchronizedPool; import android.util.Slog; import android.util.TypedValue; import android.view.ViewDebug; import android.view.ViewHierarchyEncoder; import java.io.IOException; import java.io.InputStream; Loading Loading @@ -1806,12 +1806,27 @@ public class Resources { for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) { final int resId = mKey.mResId[i]; final boolean forced = mKey.mForce[i]; try { themes[i] = getResourceName(resId); } catch (NotFoundException e) { themes[i] = Integer.toHexString(i); } themes[i + 1] = forced ? "forced" : "not forced"; } return themes; } /** @hide */ public void encode(@NonNull ViewHierarchyEncoder encoder) { encoder.beginObject(this); // TODO: revert after getTheme() is fixed String[] properties = new String[0]; // getTheme(); for (int i = 0; i < properties.length; i += 2) { encoder.addProperty(properties[i], properties[i+1]); } encoder.endObject(); } /** * Rebases the theme against the parent Resource object's current * configuration by re-applying the styles passed to Loading core/java/android/ddm/DdmHandleViewDebug.java +13 −3 Original line number Diff line number Diff line Loading @@ -229,15 +229,25 @@ public class DdmHandleViewDebug extends ChunkHandler { private Chunk dumpHierarchy(View rootView, ByteBuffer in) { boolean skipChildren = in.getInt() > 0; boolean includeProperties = in.getInt() > 0; boolean v2 = in.hasRemaining() && in.getInt() > 0; ByteArrayOutputStream b = new ByteArrayOutputStream(1024); long start = System.currentTimeMillis(); ByteArrayOutputStream b = new ByteArrayOutputStream(2*1024*1024); try { if (v2) { ViewDebug.dumpv2(rootView, b); } else { ViewDebug.dump(rootView, skipChildren, includeProperties, b); } catch (IOException e) { } } catch (IOException | InterruptedException e) { return createFailChunk(1, "Unexpected error while obtaining view hierarchy: " + e.getMessage()); } long end = System.currentTimeMillis(); Log.d(TAG, "Time to obtain view hierarchy (ms): " + (end - start)); byte[] data = b.toByteArray(); return new Chunk(CHUNK_VURT, data, 0, data.length); } Loading core/java/android/view/View.java +134 −0 Original line number Diff line number Diff line Loading @@ -22353,4 +22353,138 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final String output = bits + " " + name; found.put(key, output); } /** {@hide} */ void encode(@NonNull ViewHierarchyEncoder stream) { stream.beginObject(this); encodeProperties(stream); stream.endObject(); } /** {@hide} */ @CallSuper protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) { Object resolveId = ViewDebug.resolveId(getContext(), mID); if (resolveId instanceof String) { stream.addProperty("id", (String) resolveId); } else { stream.addProperty("id", mID); } stream.addProperty("misc:transformation.alpha", mTransformationInfo != null ? mTransformationInfo.mAlpha : 0); stream.addProperty("misc:transitionName", getTransitionName()); // layout stream.addProperty("layout:left", mLeft); stream.addProperty("layout:right", mRight); stream.addProperty("layout:top", mTop); stream.addProperty("layout:bottom", mBottom); stream.addProperty("layout:width", getWidth()); stream.addProperty("layout:height", getHeight()); stream.addProperty("layout:layoutDirection", getLayoutDirection()); stream.addProperty("layout:layoutRtl", isLayoutRtl()); stream.addProperty("layout:hasTransientState", hasTransientState()); stream.addProperty("layout:baseline", getBaseline()); // layout params ViewGroup.LayoutParams layoutParams = getLayoutParams(); if (layoutParams != null) { stream.addPropertyKey("layoutParams"); layoutParams.encode(stream); } // scrolling stream.addProperty("scrolling:scrollX", mScrollX); stream.addProperty("scrolling:scrollY", mScrollY); // padding stream.addProperty("padding:paddingLeft", mPaddingLeft); stream.addProperty("padding:paddingRight", mPaddingRight); stream.addProperty("padding:paddingTop", mPaddingTop); stream.addProperty("padding:paddingBottom", mPaddingBottom); stream.addProperty("padding:userPaddingRight", mUserPaddingRight); stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft); stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom); stream.addProperty("padding:userPaddingStart", mUserPaddingStart); stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd); // measurement stream.addProperty("measurement:minHeight", mMinHeight); stream.addProperty("measurement:minWidth", mMinWidth); stream.addProperty("measurement:measuredWidth", mMeasuredWidth); stream.addProperty("measurement:measuredHeight", mMeasuredHeight); // drawing stream.addProperty("drawing:elevation", getElevation()); stream.addProperty("drawing:translationX", getTranslationX()); stream.addProperty("drawing:translationY", getTranslationY()); stream.addProperty("drawing:translationZ", getTranslationZ()); stream.addProperty("drawing:rotation", getRotation()); stream.addProperty("drawing:rotationX", getRotationX()); stream.addProperty("drawing:rotationY", getRotationY()); stream.addProperty("drawing:scaleX", getScaleX()); stream.addProperty("drawing:scaleY", getScaleY()); stream.addProperty("drawing:pivotX", getPivotX()); stream.addProperty("drawing:pivotY", getPivotY()); stream.addProperty("drawing:opaque", isOpaque()); stream.addProperty("drawing:alpha", getAlpha()); stream.addProperty("drawing:transitionAlpha", getTransitionAlpha()); stream.addProperty("drawing:shadow", hasShadow()); stream.addProperty("drawing:solidColor", getSolidColor()); stream.addProperty("drawing:layerType", mLayerType); stream.addProperty("drawing:willNotDraw", willNotDraw()); stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated()); stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing()); stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled()); stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering()); // focus stream.addProperty("focus:hasFocus", hasFocus()); stream.addProperty("focus:isFocused", isFocused()); stream.addProperty("focus:isFocusable", isFocusable()); stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode()); stream.addProperty("misc:clickable", isClickable()); stream.addProperty("misc:pressed", isPressed()); stream.addProperty("misc:selected", isSelected()); stream.addProperty("misc:touchMode", isInTouchMode()); stream.addProperty("misc:hovered", isHovered()); stream.addProperty("misc:activated", isActivated()); stream.addProperty("misc:visibility", getVisibility()); stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows()); stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured()); stream.addProperty("misc:enabled", isEnabled()); stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled()); stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled()); // theme attributes Resources.Theme theme = getContext().getTheme(); if (theme != null) { stream.addPropertyKey("theme"); theme.encode(stream); } // view attribute information int n = mAttributes != null ? mAttributes.length : 0; stream.addProperty("meta:__attrCount__", n/2); for (int i = 0; i < n; i += 2) { stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]); } stream.addProperty("misc:scrollBarStyle", getScrollBarStyle()); // text stream.addProperty("text:textDirection", getTextDirection()); stream.addProperty("text:textAlignment", getTextAlignment()); // accessibility CharSequence contentDescription = getContentDescription(); stream.addProperty("accessibility:contentDescription", contentDescription == null ? "" : contentDescription.toString()); stream.addProperty("accessibility:labelFor", getLabelFor()); stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility()); } } core/java/android/view/ViewDebug.java +24 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.view; import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; Loading Loading @@ -800,6 +801,7 @@ public class ViewDebug { /** * Dumps the view hierarchy starting from the given view. * @deprecated See {@link #dumpv2(View, ByteArrayOutputStream)} below. * @hide */ public static void dump(View root, boolean skipChildren, boolean includeProperties, Loading @@ -824,6 +826,28 @@ public class ViewDebug { } } /** * Dumps the view hierarchy starting from the given view. * Rather than using reflection, it uses View's encode method to obtain all the properties. * @hide */ public static void dumpv2(@NonNull final View view, @NonNull ByteArrayOutputStream out) throws InterruptedException { final ViewHierarchyEncoder encoder = new ViewHierarchyEncoder(out); final CountDownLatch latch = new CountDownLatch(1); view.post(new Runnable() { @Override public void run() { view.encode(encoder); latch.countDown(); } }); latch.await(2, TimeUnit.SECONDS); encoder.endStream(); } /** * Dumps the theme attributes from the given View. * @hide Loading core/java/android/view/ViewGroup.java +44 −0 Original line number Diff line number Diff line Loading @@ -6861,6 +6861,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } return String.valueOf(size); } /** @hide */ void encode(@NonNull ViewHierarchyEncoder encoder) { encoder.beginObject(this); encodeProperties(encoder); encoder.endObject(); } /** @hide */ protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) { encoder.addProperty("width", width); encoder.addProperty("height", height); } } /** Loading Loading @@ -7329,6 +7342,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager bottomMargin, paint); } /** @hide */ @Override protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) { super.encodeProperties(encoder); encoder.addProperty("leftMargin", leftMargin); encoder.addProperty("topMargin", topMargin); encoder.addProperty("rightMargin", rightMargin); encoder.addProperty("bottomMargin", bottomMargin); encoder.addProperty("startMargin", startMargin); encoder.addProperty("endMargin", endMargin); } } /* Describes a touched view and the ids of the pointers that it has captured. Loading Loading @@ -7665,4 +7690,23 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager canvas.drawLines(sDebugLines, paint); } /** @hide */ @Override protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) { super.encodeProperties(encoder); encoder.addProperty("focus:descendantFocusability", getDescendantFocusability()); encoder.addProperty("drawing:clipChildren", getClipChildren()); encoder.addProperty("drawing:clipToPadding", getClipToPadding()); encoder.addProperty("drawing:childrenDrawingOrderEnabled", isChildrenDrawingOrderEnabled()); encoder.addProperty("drawing:persistentDrawingCache", getPersistentDrawingCache()); int n = getChildCount(); encoder.addProperty("meta:__childCount__", (short)n); for (int i = 0; i < n; i++) { encoder.addPropertyKey("meta:__child__" + i); getChildAt(i).encode(encoder); } } } Loading
core/java/android/content/res/Resources.java +17 −2 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.annotation.AttrRes; import android.annotation.ColorInt; import android.annotation.StyleRes; import android.annotation.StyleableRes; import com.android.internal.util.GrowingArrayUtils; import com.android.internal.util.XmlUtils; Loading Loading @@ -62,6 +61,7 @@ import android.util.Pools.SynchronizedPool; import android.util.Slog; import android.util.TypedValue; import android.view.ViewDebug; import android.view.ViewHierarchyEncoder; import java.io.IOException; import java.io.InputStream; Loading Loading @@ -1806,12 +1806,27 @@ public class Resources { for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) { final int resId = mKey.mResId[i]; final boolean forced = mKey.mForce[i]; try { themes[i] = getResourceName(resId); } catch (NotFoundException e) { themes[i] = Integer.toHexString(i); } themes[i + 1] = forced ? "forced" : "not forced"; } return themes; } /** @hide */ public void encode(@NonNull ViewHierarchyEncoder encoder) { encoder.beginObject(this); // TODO: revert after getTheme() is fixed String[] properties = new String[0]; // getTheme(); for (int i = 0; i < properties.length; i += 2) { encoder.addProperty(properties[i], properties[i+1]); } encoder.endObject(); } /** * Rebases the theme against the parent Resource object's current * configuration by re-applying the styles passed to Loading
core/java/android/ddm/DdmHandleViewDebug.java +13 −3 Original line number Diff line number Diff line Loading @@ -229,15 +229,25 @@ public class DdmHandleViewDebug extends ChunkHandler { private Chunk dumpHierarchy(View rootView, ByteBuffer in) { boolean skipChildren = in.getInt() > 0; boolean includeProperties = in.getInt() > 0; boolean v2 = in.hasRemaining() && in.getInt() > 0; ByteArrayOutputStream b = new ByteArrayOutputStream(1024); long start = System.currentTimeMillis(); ByteArrayOutputStream b = new ByteArrayOutputStream(2*1024*1024); try { if (v2) { ViewDebug.dumpv2(rootView, b); } else { ViewDebug.dump(rootView, skipChildren, includeProperties, b); } catch (IOException e) { } } catch (IOException | InterruptedException e) { return createFailChunk(1, "Unexpected error while obtaining view hierarchy: " + e.getMessage()); } long end = System.currentTimeMillis(); Log.d(TAG, "Time to obtain view hierarchy (ms): " + (end - start)); byte[] data = b.toByteArray(); return new Chunk(CHUNK_VURT, data, 0, data.length); } Loading
core/java/android/view/View.java +134 −0 Original line number Diff line number Diff line Loading @@ -22353,4 +22353,138 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final String output = bits + " " + name; found.put(key, output); } /** {@hide} */ void encode(@NonNull ViewHierarchyEncoder stream) { stream.beginObject(this); encodeProperties(stream); stream.endObject(); } /** {@hide} */ @CallSuper protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) { Object resolveId = ViewDebug.resolveId(getContext(), mID); if (resolveId instanceof String) { stream.addProperty("id", (String) resolveId); } else { stream.addProperty("id", mID); } stream.addProperty("misc:transformation.alpha", mTransformationInfo != null ? mTransformationInfo.mAlpha : 0); stream.addProperty("misc:transitionName", getTransitionName()); // layout stream.addProperty("layout:left", mLeft); stream.addProperty("layout:right", mRight); stream.addProperty("layout:top", mTop); stream.addProperty("layout:bottom", mBottom); stream.addProperty("layout:width", getWidth()); stream.addProperty("layout:height", getHeight()); stream.addProperty("layout:layoutDirection", getLayoutDirection()); stream.addProperty("layout:layoutRtl", isLayoutRtl()); stream.addProperty("layout:hasTransientState", hasTransientState()); stream.addProperty("layout:baseline", getBaseline()); // layout params ViewGroup.LayoutParams layoutParams = getLayoutParams(); if (layoutParams != null) { stream.addPropertyKey("layoutParams"); layoutParams.encode(stream); } // scrolling stream.addProperty("scrolling:scrollX", mScrollX); stream.addProperty("scrolling:scrollY", mScrollY); // padding stream.addProperty("padding:paddingLeft", mPaddingLeft); stream.addProperty("padding:paddingRight", mPaddingRight); stream.addProperty("padding:paddingTop", mPaddingTop); stream.addProperty("padding:paddingBottom", mPaddingBottom); stream.addProperty("padding:userPaddingRight", mUserPaddingRight); stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft); stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom); stream.addProperty("padding:userPaddingStart", mUserPaddingStart); stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd); // measurement stream.addProperty("measurement:minHeight", mMinHeight); stream.addProperty("measurement:minWidth", mMinWidth); stream.addProperty("measurement:measuredWidth", mMeasuredWidth); stream.addProperty("measurement:measuredHeight", mMeasuredHeight); // drawing stream.addProperty("drawing:elevation", getElevation()); stream.addProperty("drawing:translationX", getTranslationX()); stream.addProperty("drawing:translationY", getTranslationY()); stream.addProperty("drawing:translationZ", getTranslationZ()); stream.addProperty("drawing:rotation", getRotation()); stream.addProperty("drawing:rotationX", getRotationX()); stream.addProperty("drawing:rotationY", getRotationY()); stream.addProperty("drawing:scaleX", getScaleX()); stream.addProperty("drawing:scaleY", getScaleY()); stream.addProperty("drawing:pivotX", getPivotX()); stream.addProperty("drawing:pivotY", getPivotY()); stream.addProperty("drawing:opaque", isOpaque()); stream.addProperty("drawing:alpha", getAlpha()); stream.addProperty("drawing:transitionAlpha", getTransitionAlpha()); stream.addProperty("drawing:shadow", hasShadow()); stream.addProperty("drawing:solidColor", getSolidColor()); stream.addProperty("drawing:layerType", mLayerType); stream.addProperty("drawing:willNotDraw", willNotDraw()); stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated()); stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing()); stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled()); stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering()); // focus stream.addProperty("focus:hasFocus", hasFocus()); stream.addProperty("focus:isFocused", isFocused()); stream.addProperty("focus:isFocusable", isFocusable()); stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode()); stream.addProperty("misc:clickable", isClickable()); stream.addProperty("misc:pressed", isPressed()); stream.addProperty("misc:selected", isSelected()); stream.addProperty("misc:touchMode", isInTouchMode()); stream.addProperty("misc:hovered", isHovered()); stream.addProperty("misc:activated", isActivated()); stream.addProperty("misc:visibility", getVisibility()); stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows()); stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured()); stream.addProperty("misc:enabled", isEnabled()); stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled()); stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled()); // theme attributes Resources.Theme theme = getContext().getTheme(); if (theme != null) { stream.addPropertyKey("theme"); theme.encode(stream); } // view attribute information int n = mAttributes != null ? mAttributes.length : 0; stream.addProperty("meta:__attrCount__", n/2); for (int i = 0; i < n; i += 2) { stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]); } stream.addProperty("misc:scrollBarStyle", getScrollBarStyle()); // text stream.addProperty("text:textDirection", getTextDirection()); stream.addProperty("text:textAlignment", getTextAlignment()); // accessibility CharSequence contentDescription = getContentDescription(); stream.addProperty("accessibility:contentDescription", contentDescription == null ? "" : contentDescription.toString()); stream.addProperty("accessibility:labelFor", getLabelFor()); stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility()); } }
core/java/android/view/ViewDebug.java +24 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.view; import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; Loading Loading @@ -800,6 +801,7 @@ public class ViewDebug { /** * Dumps the view hierarchy starting from the given view. * @deprecated See {@link #dumpv2(View, ByteArrayOutputStream)} below. * @hide */ public static void dump(View root, boolean skipChildren, boolean includeProperties, Loading @@ -824,6 +826,28 @@ public class ViewDebug { } } /** * Dumps the view hierarchy starting from the given view. * Rather than using reflection, it uses View's encode method to obtain all the properties. * @hide */ public static void dumpv2(@NonNull final View view, @NonNull ByteArrayOutputStream out) throws InterruptedException { final ViewHierarchyEncoder encoder = new ViewHierarchyEncoder(out); final CountDownLatch latch = new CountDownLatch(1); view.post(new Runnable() { @Override public void run() { view.encode(encoder); latch.countDown(); } }); latch.await(2, TimeUnit.SECONDS); encoder.endStream(); } /** * Dumps the theme attributes from the given View. * @hide Loading
core/java/android/view/ViewGroup.java +44 −0 Original line number Diff line number Diff line Loading @@ -6861,6 +6861,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } return String.valueOf(size); } /** @hide */ void encode(@NonNull ViewHierarchyEncoder encoder) { encoder.beginObject(this); encodeProperties(encoder); encoder.endObject(); } /** @hide */ protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) { encoder.addProperty("width", width); encoder.addProperty("height", height); } } /** Loading Loading @@ -7329,6 +7342,18 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager bottomMargin, paint); } /** @hide */ @Override protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) { super.encodeProperties(encoder); encoder.addProperty("leftMargin", leftMargin); encoder.addProperty("topMargin", topMargin); encoder.addProperty("rightMargin", rightMargin); encoder.addProperty("bottomMargin", bottomMargin); encoder.addProperty("startMargin", startMargin); encoder.addProperty("endMargin", endMargin); } } /* Describes a touched view and the ids of the pointers that it has captured. Loading Loading @@ -7665,4 +7690,23 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager canvas.drawLines(sDebugLines, paint); } /** @hide */ @Override protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) { super.encodeProperties(encoder); encoder.addProperty("focus:descendantFocusability", getDescendantFocusability()); encoder.addProperty("drawing:clipChildren", getClipChildren()); encoder.addProperty("drawing:clipToPadding", getClipToPadding()); encoder.addProperty("drawing:childrenDrawingOrderEnabled", isChildrenDrawingOrderEnabled()); encoder.addProperty("drawing:persistentDrawingCache", getPersistentDrawingCache()); int n = getChildCount(); encoder.addProperty("meta:__childCount__", (short)n); for (int i = 0; i < n; i++) { encoder.addPropertyKey("meta:__child__" + i); getChildAt(i).encode(encoder); } } }