Skip to content

Commit

Permalink
Add perf stat for applying styles in binary resources
Browse files Browse the repository at this point in the history
Applying styles uses Robolectric ResXMLParser, which is suspected
of being quite slow. This occurs extensively when layouts are inflated.
Add a perf stat to track it.

PiperOrigin-RevId: 410883839
  • Loading branch information
hoisie authored and copybara-robolectric committed Nov 19, 2021
1 parent 0cb21aa commit 0a71492
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 16 deletions.
Expand Up @@ -8,6 +8,7 @@
import static android.os.Build.VERSION_CODES.N;
import static android.os.Build.VERSION_CODES.Q;
import static org.robolectric.RuntimeEnvironment.getApiLevel;
import static org.robolectric.util.reflector.Reflector.reflector;

import android.graphics.Rect;
import android.os.Bundle;
Expand Down Expand Up @@ -36,7 +37,9 @@
import org.robolectric.annotation.Resetter;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.util.ReflectionHelpers;
import org.robolectric.util.ReflectionHelpers.ClassParameter;
import org.robolectric.util.reflector.Accessor;
import org.robolectric.util.reflector.ForType;
import org.robolectric.util.reflector.Static;

/**
* Properties of {@link android.view.accessibility.AccessibilityNodeInfo} that are normally locked
Expand Down Expand Up @@ -191,8 +194,7 @@ public AccessibilityNodeInfo[] newArray(int size) {

@Implementation
protected void __constructor__() {
ReflectionHelpers.setStaticField(
AccessibilityNodeInfo.class, "CREATOR", ShadowAccessibilityNodeInfo.CREATOR);
reflector(AccessibilityNodeInfoReflector.class).setCreator(ShadowAccessibilityNodeInfo.CREATOR);
}

@Implementation
Expand Down Expand Up @@ -1223,11 +1225,7 @@ public static final class ShadowAccessibilityAction {

@Implementation
protected void __constructor__(int id, CharSequence label) {
if (((id
& (int)
ReflectionHelpers.getStaticField(
AccessibilityNodeInfo.class, "ACTION_TYPE_MASK"))
== 0)
if (((id & reflector(AccessibilityNodeInfoReflector.class).getActionTypeMask()) == 0)
&& Integer.bitCount(id) != 1) {
throw new IllegalArgumentException("Invalid standard action id");
}
Expand Down Expand Up @@ -1266,8 +1264,8 @@ public boolean equals(Object other) {

@Override
public String toString() {
String actionSybolicName = ReflectionHelpers.callStaticMethod(
AccessibilityNodeInfo.class, "getActionSymbolicName", ClassParameter.from(int.class, id));
String actionSybolicName =
reflector(AccessibilityNodeInfoReflector.class).getActionSymbolicName(id);
return "AccessibilityAction: " + actionSybolicName + " - " + label;
}
}
Expand All @@ -1292,19 +1290,16 @@ protected void writeToParcel(Parcel dest, int flags) {

private static int getActionTypeMaskFromFramework() {
// Get the mask to determine whether an int is a legit ID for an action, defined by Android
return (int)ReflectionHelpers.getStaticField(AccessibilityNodeInfo.class, "ACTION_TYPE_MASK");
return reflector(AccessibilityNodeInfoReflector.class).getActionTypeMask();
}

private static AccessibilityAction getActionFromIdFromFrameWork(int id) {
// Convert an action ID to Android standard Accessibility Action defined by Android
return ReflectionHelpers.callStaticMethod(
AccessibilityNodeInfo.class, "getActionSingleton", ClassParameter.from(int.class, id));
return reflector(AccessibilityNodeInfoReflector.class).getActionSingleton(id);
}

private static int getLastLegacyActionFromFrameWork() {
return (int)
ReflectionHelpers.getStaticField(
AccessibilityNodeInfo.class, "LAST_LEGACY_STANDARD_ACTION");
return reflector(AccessibilityNodeInfoReflector.class).getLastLegacyStandardAction();
}

/**
Expand All @@ -1331,4 +1326,25 @@ public String toString() {
+ className
+ "}";
}

@ForType(AccessibilityNodeInfo.class)
interface AccessibilityNodeInfoReflector {
@Static
@Accessor("CREATOR")
void setCreator(Parcelable.Creator<AccessibilityNodeInfo> creator);

@Static
@Accessor("ACTION_TYPE_MASK")
int getActionTypeMask();

@Static
@Accessor("LAST_LEGACY_STANDARD_ACTION")
int getLastLegacyStandardAction();

@Static
String getActionSymbolicName(int id);

@Static
AccessibilityAction getActionSingleton(int id);
}
}
Expand Up @@ -73,6 +73,7 @@
import org.robolectric.res.android.ResXMLTree;
import org.robolectric.res.android.ResourceTypes.Res_value;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.util.PerfStatsCollector;
import org.robolectric.util.ReflectionHelpers;
import org.robolectric.util.ReflectionHelpers.ClassParameter;
import org.robolectric.util.reflector.Direct;
Expand Down Expand Up @@ -1388,6 +1389,30 @@ protected static void nativeApplyStyle(
@NonNull int[] java_attrs,
long out_values_ptr,
long out_indices_ptr) {
PerfStatsCollector.getInstance()
.measure(
"applyStyle",
() ->
nativeApplyStyle_measured(
ptr,
theme_ptr,
def_style_attr,
def_style_resid,
xml_parser_ptr,
java_attrs,
out_values_ptr,
out_indices_ptr));
}

private static void nativeApplyStyle_measured(
long ptr,
long theme_ptr,
@AttrRes int def_style_attr,
@StyleRes int def_style_resid,
long xml_parser_ptr,
@NonNull int[] java_attrs,
long out_values_ptr,
long out_indices_ptr) {
CppAssetManager2 assetmanager = AssetManagerFromLong(ptr);
Theme theme = Registries.NATIVE_THEME9_REGISTRY.getNativeObject(theme_ptr);
CHECK(theme.GetAssetManager() == assetmanager);
Expand Down
Expand Up @@ -73,6 +73,7 @@
import org.robolectric.res.android.ResXMLTree;
import org.robolectric.res.android.ResourceTypes.Res_value;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.util.PerfStatsCollector;
import org.robolectric.util.ReflectionHelpers;
import org.robolectric.util.ReflectionHelpers.ClassParameter;
import org.robolectric.util.reflector.Direct;
Expand Down Expand Up @@ -1378,6 +1379,30 @@ protected static void nativeApplyStyle(
@NonNull int[] java_attrs,
long out_values_ptr,
long out_indices_ptr) {
PerfStatsCollector.getInstance()
.measure(
"applyStyle",
() ->
nativeApplyStyle_measured(
ptr,
theme_ptr,
def_style_attr,
def_style_resid,
xml_parser_ptr,
java_attrs,
out_values_ptr,
out_indices_ptr));
}

private static void nativeApplyStyle_measured(
long ptr,
long theme_ptr,
@AttrRes int def_style_attr,
@StyleRes int def_style_resid,
long xml_parser_ptr,
@NonNull int[] java_attrs,
long out_values_ptr,
long out_indices_ptr) {
CppAssetManager2 assetmanager = AssetManagerFromLong(ptr);
Theme theme = Registries.NATIVE_THEME9_REGISTRY.getNativeObject(theme_ptr);
CHECK(theme.GetAssetManager() == assetmanager);
Expand Down

0 comments on commit 0a71492

Please sign in to comment.