Merge "Introduce a way to debug relayouts and slow measures/layout" into tm-qpr-dev am: c261087167
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21040074 Change-Id: I9ec6fd5d933f0e2f60f61b890396d251ee5d6e1d Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -110,7 +110,8 @@ public final class Trace {
|
|||||||
public static final long TRACE_TAG_THERMAL = 1L << 27;
|
public static final long TRACE_TAG_THERMAL = 1L << 27;
|
||||||
|
|
||||||
private static final long TRACE_TAG_NOT_READY = 1L << 63;
|
private static final long TRACE_TAG_NOT_READY = 1L << 63;
|
||||||
private static final int MAX_SECTION_NAME_LEN = 127;
|
/** @hide **/
|
||||||
|
public static final int MAX_SECTION_NAME_LEN = 127;
|
||||||
|
|
||||||
// Must be volatile to avoid word tearing.
|
// Must be volatile to avoid word tearing.
|
||||||
// This is only kept in case any apps get this by reflection but do not
|
// This is only kept in case any apps get this by reflection but do not
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package android.view;
|
package android.view;
|
||||||
|
|
||||||
import static android.content.res.Resources.ID_NULL;
|
import static android.content.res.Resources.ID_NULL;
|
||||||
|
import static android.os.Trace.TRACE_TAG_APP;
|
||||||
import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP;
|
import static android.view.ContentInfo.SOURCE_DRAG_AND_DROP;
|
||||||
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
|
import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
|
||||||
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
|
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_BOUNDS;
|
||||||
@@ -984,6 +985,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
*/
|
*/
|
||||||
private static boolean sAcceptZeroSizeDragShadow;
|
private static boolean sAcceptZeroSizeDragShadow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When true, measure and layout passes of all the newly attached views will be logged with
|
||||||
|
* {@link Trace}, so we can better debug jank due to complex view hierarchies.
|
||||||
|
*/
|
||||||
|
private static boolean sTraceLayoutSteps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When not null, emits a {@link Trace} instant event and the stacktrace every time a relayout
|
||||||
|
* of a class having this name happens.
|
||||||
|
*/
|
||||||
|
private static String sTraceRequestLayoutClass;
|
||||||
|
|
||||||
|
/** Used to avoid computing the full strings each time when layout tracing is enabled. */
|
||||||
|
@Nullable
|
||||||
|
private ViewTraversalTracingStrings mTracingStrings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prior to R, {@link #dispatchApplyWindowInsets} had an issue:
|
* Prior to R, {@link #dispatchApplyWindowInsets} had an issue:
|
||||||
* <p>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
|
* <p>The modified insets changed by {@link #onApplyWindowInsets} were passed to the
|
||||||
@@ -3532,6 +3549,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
* 1 PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE
|
* 1 PFLAG4_HAS_TRANSLATION_TRANSIENT_STATE
|
||||||
* 1 PFLAG4_DRAG_A11Y_STARTED
|
* 1 PFLAG4_DRAG_A11Y_STARTED
|
||||||
* 1 PFLAG4_AUTO_HANDWRITING_INITIATION_ENABLED
|
* 1 PFLAG4_AUTO_HANDWRITING_INITIATION_ENABLED
|
||||||
|
* 1 PFLAG4_TRAVERSAL_TRACING_ENABLED
|
||||||
|
* 1 PFLAG4_RELAYOUT_TRACING_ENABLED
|
||||||
* |-------|-------|-------|-------|
|
* |-------|-------|-------|-------|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -3612,6 +3631,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
* Indicates that the view enables auto handwriting initiation.
|
* Indicates that the view enables auto handwriting initiation.
|
||||||
*/
|
*/
|
||||||
private static final int PFLAG4_AUTO_HANDWRITING_ENABLED = 0x000010000;
|
private static final int PFLAG4_AUTO_HANDWRITING_ENABLED = 0x000010000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When set, measure and layout passes of this view will be logged with {@link Trace}, so we
|
||||||
|
* can better debug jank due to complex view hierarchies.
|
||||||
|
*/
|
||||||
|
private static final int PFLAG4_TRAVERSAL_TRACING_ENABLED = 0x000040000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When set, emits a {@link Trace} instant event and stacktrace every time a requestLayout of
|
||||||
|
* this class happens.
|
||||||
|
*/
|
||||||
|
private static final int PFLAG4_RELAYOUT_TRACING_ENABLED = 0x000080000;
|
||||||
|
|
||||||
/* End of masks for mPrivateFlags4 */
|
/* End of masks for mPrivateFlags4 */
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -6537,6 +6569,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
out.append(mRight);
|
out.append(mRight);
|
||||||
out.append(',');
|
out.append(',');
|
||||||
out.append(mBottom);
|
out.append(mBottom);
|
||||||
|
appendId(out);
|
||||||
|
if (mAutofillId != null) {
|
||||||
|
out.append(" aid="); out.append(mAutofillId);
|
||||||
|
}
|
||||||
|
out.append("}");
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void appendId(StringBuilder out) {
|
||||||
final int id = getId();
|
final int id = getId();
|
||||||
if (id != NO_ID) {
|
if (id != NO_ID) {
|
||||||
out.append(" #");
|
out.append(" #");
|
||||||
@@ -6568,11 +6609,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mAutofillId != null) {
|
|
||||||
out.append(" aid="); out.append(mAutofillId);
|
|
||||||
}
|
|
||||||
out.append("}");
|
|
||||||
return out.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20771,6 +20807,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
if (isFocused()) {
|
if (isFocused()) {
|
||||||
notifyFocusChangeToImeFocusController(true /* hasFocus */);
|
notifyFocusChangeToImeFocusController(true /* hasFocus */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sTraceLayoutSteps) {
|
||||||
|
setTraversalTracingEnabled(true);
|
||||||
|
}
|
||||||
|
if (sTraceRequestLayoutClass != null
|
||||||
|
&& sTraceRequestLayoutClass.equals(getClass().getSimpleName())) {
|
||||||
|
setRelayoutTracingEnabled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23670,6 +23714,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
|
return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable measure/layout debugging on traces.
|
||||||
|
*
|
||||||
|
* @see Trace
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static void setTraceLayoutSteps(boolean traceLayoutSteps) {
|
||||||
|
sTraceLayoutSteps = traceLayoutSteps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable request layout tracing classes with {@code s} simple name.
|
||||||
|
* <p>
|
||||||
|
* When set, a {@link Trace} instant event and a log with the stacktrace is emitted every
|
||||||
|
* time a requestLayout of a class matching {@code s} name happens.
|
||||||
|
* This applies only to views attached from this point onwards.
|
||||||
|
*
|
||||||
|
* @see Trace#instant(long, String)
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static void setTracedRequestLayoutClassClass(String s) {
|
||||||
|
sTraceRequestLayoutClass = s;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean setOpticalFrame(int left, int top, int right, int bottom) {
|
private boolean setOpticalFrame(int left, int top, int right, int bottom) {
|
||||||
Insets parentInsets = mParent instanceof View ?
|
Insets parentInsets = mParent instanceof View ?
|
||||||
((View) mParent).getOpticalInsets() : Insets.NONE;
|
((View) mParent).getOpticalInsets() : Insets.NONE;
|
||||||
@@ -23704,7 +23772,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
@SuppressWarnings({"unchecked"})
|
@SuppressWarnings({"unchecked"})
|
||||||
public void layout(int l, int t, int r, int b) {
|
public void layout(int l, int t, int r, int b) {
|
||||||
if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
|
if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
|
||||||
|
if (isTraversalTracingEnabled()) {
|
||||||
|
Trace.beginSection(mTracingStrings.onMeasureBeforeLayout);
|
||||||
|
}
|
||||||
onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
|
onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
|
||||||
|
if (isTraversalTracingEnabled()) {
|
||||||
|
Trace.endSection();
|
||||||
|
}
|
||||||
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
|
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23717,7 +23791,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
|
setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
|
||||||
|
|
||||||
if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
|
if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
|
||||||
|
if (isTraversalTracingEnabled()) {
|
||||||
|
Trace.beginSection(mTracingStrings.onLayout);
|
||||||
|
}
|
||||||
onLayout(changed, l, t, r, b);
|
onLayout(changed, l, t, r, b);
|
||||||
|
if (isTraversalTracingEnabled()) {
|
||||||
|
Trace.endSection();
|
||||||
|
}
|
||||||
|
|
||||||
if (shouldDrawRoundScrollbar()) {
|
if (shouldDrawRoundScrollbar()) {
|
||||||
if(mRoundScrollbarRenderer == null) {
|
if(mRoundScrollbarRenderer == null) {
|
||||||
@@ -26274,6 +26354,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
return (viewRoot != null && viewRoot.isInLayout());
|
return (viewRoot != null && viewRoot.isInLayout());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** To be used only for debugging purposes. */
|
||||||
|
private void printStackStrace(String name) {
|
||||||
|
Log.d(VIEW_LOG_TAG, "---- ST:" + name);
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
|
||||||
|
int startIndex = 1;
|
||||||
|
int endIndex = Math.min(stackTraceElements.length, startIndex + 20); // max 20 entries.
|
||||||
|
for (int i = startIndex; i < endIndex; i++) {
|
||||||
|
StackTraceElement s = stackTraceElements[i];
|
||||||
|
sb.append(s.getMethodName())
|
||||||
|
.append("(")
|
||||||
|
.append(s.getFileName())
|
||||||
|
.append(":")
|
||||||
|
.append(s.getLineNumber())
|
||||||
|
.append(") <- ");
|
||||||
|
}
|
||||||
|
Log.d(VIEW_LOG_TAG, name + ": " + sb);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Call this when something has changed which has invalidated the
|
* Call this when something has changed which has invalidated the
|
||||||
* layout of this view. This will schedule a layout pass of the view
|
* layout of this view. This will schedule a layout pass of the view
|
||||||
@@ -26287,6 +26386,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
*/
|
*/
|
||||||
@CallSuper
|
@CallSuper
|
||||||
public void requestLayout() {
|
public void requestLayout() {
|
||||||
|
if (isRelayoutTracingEnabled()) {
|
||||||
|
Trace.instantForTrack(TRACE_TAG_APP, "requestLayoutTracing",
|
||||||
|
mTracingStrings.classSimpleName);
|
||||||
|
printStackStrace(mTracingStrings.requestLayoutStacktracePrefix);
|
||||||
|
}
|
||||||
|
|
||||||
if (mMeasureCache != null) mMeasureCache.clear();
|
if (mMeasureCache != null) mMeasureCache.clear();
|
||||||
|
|
||||||
if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
|
if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
|
||||||
@@ -26380,8 +26485,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
|
|
||||||
int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
|
int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
|
||||||
if (cacheIndex < 0 || sIgnoreMeasureCache) {
|
if (cacheIndex < 0 || sIgnoreMeasureCache) {
|
||||||
|
if (isTraversalTracingEnabled()) {
|
||||||
|
Trace.beginSection(mTracingStrings.onMeasure);
|
||||||
|
}
|
||||||
// measure ourselves, this should set the measured dimension flag back
|
// measure ourselves, this should set the measured dimension flag back
|
||||||
onMeasure(widthMeasureSpec, heightMeasureSpec);
|
onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
if (isTraversalTracingEnabled()) {
|
||||||
|
Trace.endSection();
|
||||||
|
}
|
||||||
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
|
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
|
||||||
} else {
|
} else {
|
||||||
long value = mMeasureCache.valueAt(cacheIndex);
|
long value = mMeasureCache.valueAt(cacheIndex);
|
||||||
@@ -31551,6 +31662,38 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
== PFLAG4_AUTO_HANDWRITING_ENABLED;
|
== PFLAG4_AUTO_HANDWRITING_ENABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setTraversalTracingEnabled(boolean enabled) {
|
||||||
|
if (enabled) {
|
||||||
|
if (mTracingStrings == null) {
|
||||||
|
mTracingStrings = new ViewTraversalTracingStrings(this);
|
||||||
|
}
|
||||||
|
mPrivateFlags4 |= PFLAG4_TRAVERSAL_TRACING_ENABLED;
|
||||||
|
} else {
|
||||||
|
mPrivateFlags4 &= ~PFLAG4_TRAVERSAL_TRACING_ENABLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTraversalTracingEnabled() {
|
||||||
|
return (mPrivateFlags4 & PFLAG4_TRAVERSAL_TRACING_ENABLED)
|
||||||
|
== PFLAG4_TRAVERSAL_TRACING_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setRelayoutTracingEnabled(boolean enabled) {
|
||||||
|
if (enabled) {
|
||||||
|
if (mTracingStrings == null) {
|
||||||
|
mTracingStrings = new ViewTraversalTracingStrings(this);
|
||||||
|
}
|
||||||
|
mPrivateFlags4 |= PFLAG4_RELAYOUT_TRACING_ENABLED;
|
||||||
|
} else {
|
||||||
|
mPrivateFlags4 &= ~PFLAG4_RELAYOUT_TRACING_ENABLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRelayoutTracingEnabled() {
|
||||||
|
return (mPrivateFlags4 & PFLAG4_RELAYOUT_TRACING_ENABLED)
|
||||||
|
== PFLAG4_RELAYOUT_TRACING_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collects a {@link ViewTranslationRequest} which represents the content to be translated in
|
* Collects a {@link ViewTranslationRequest} which represents the content to be translated in
|
||||||
* the view.
|
* the view.
|
||||||
|
|||||||
63
core/java/android/view/ViewTraversalTracingStrings.java
Normal file
63
core/java/android/view/ViewTraversalTracingStrings.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.view;
|
||||||
|
|
||||||
|
import android.os.Trace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps and caches strings used to trace {@link View} traversals.
|
||||||
|
* <p>
|
||||||
|
* This is done to avoid expensive computations of them every time, which can improve performance.
|
||||||
|
*/
|
||||||
|
class ViewTraversalTracingStrings {
|
||||||
|
|
||||||
|
/** {@link Trace} tag used to mark {@link View#onMeasure(int, int)}. */
|
||||||
|
public final String onMeasure;
|
||||||
|
|
||||||
|
/** {@link Trace} tag used to mark {@link View#onLayout(boolean, int, int, int, int)}. */
|
||||||
|
public final String onLayout;
|
||||||
|
|
||||||
|
/** Caches the view simple name to avoid re-computations. */
|
||||||
|
public final String classSimpleName;
|
||||||
|
|
||||||
|
/** Prefix for request layout stacktraces output in logs. */
|
||||||
|
public final String requestLayoutStacktracePrefix;
|
||||||
|
|
||||||
|
/** {@link Trace} tag used to mark {@link View#onMeasure(int, int)} happening before layout. */
|
||||||
|
public final String onMeasureBeforeLayout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param v {@link View} from where to get the class name.
|
||||||
|
*/
|
||||||
|
ViewTraversalTracingStrings(View v) {
|
||||||
|
String className = v.getClass().getSimpleName();
|
||||||
|
classSimpleName = className;
|
||||||
|
onMeasureBeforeLayout = getTraceName("onMeasureBeforeLayout", className, v);
|
||||||
|
onMeasure = getTraceName("onMeasure", className, v);
|
||||||
|
onLayout = getTraceName("onLayout", className, v);
|
||||||
|
requestLayoutStacktracePrefix = "requestLayout " + className;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTraceName(String sectionName, String className, View v) {
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
out.append(sectionName);
|
||||||
|
out.append(" ");
|
||||||
|
out.append(className);
|
||||||
|
v.appendId(out);
|
||||||
|
return out.substring(0, Math.min(out.length() - 1, Trace.MAX_SECTION_NAME_LEN - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,6 +38,7 @@ import android.util.Log;
|
|||||||
import android.util.TimingsTraceLog;
|
import android.util.TimingsTraceLog;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.view.ThreadedRenderer;
|
import android.view.ThreadedRenderer;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import com.android.internal.protolog.common.ProtoLog;
|
import com.android.internal.protolog.common.ProtoLog;
|
||||||
import com.android.systemui.dagger.GlobalRootComponent;
|
import com.android.systemui.dagger.GlobalRootComponent;
|
||||||
@@ -112,6 +113,11 @@ public class SystemUIApplication extends Application implements
|
|||||||
// the theme set there.
|
// the theme set there.
|
||||||
setTheme(R.style.Theme_SystemUI);
|
setTheme(R.style.Theme_SystemUI);
|
||||||
|
|
||||||
|
View.setTraceLayoutSteps(
|
||||||
|
SystemProperties.getBoolean("persist.debug.trace_layouts", false));
|
||||||
|
View.setTracedRequestLayoutClassClass(
|
||||||
|
SystemProperties.get("persist.debug.trace_request_layout_class", null));
|
||||||
|
|
||||||
if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
|
if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
|
||||||
IntentFilter bootCompletedFilter = new
|
IntentFilter bootCompletedFilter = new
|
||||||
IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED);
|
IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED);
|
||||||
|
|||||||
Reference in New Issue
Block a user