Merge "Add helper methods for View attribute debugging"
diff --git a/api/current.txt b/api/current.txt
index b7577d1..98d30a3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12330,8 +12330,10 @@
public final class Resources.Theme {
method public void applyStyle(int, boolean);
method public void dump(int, String, String);
+ method public int[] getAttributeResolutionStack(@AttrRes int, @StyleRes int, @StyleRes int);
method public int getChangingConfigurations();
method public android.graphics.drawable.Drawable getDrawable(@DrawableRes int) throws android.content.res.Resources.NotFoundException;
+ method @StyleRes public int getExplicitStyle(@Nullable android.util.AttributeSet);
method public android.content.res.Resources getResources();
method @NonNull public android.content.res.TypedArray obtainStyledAttributes(@NonNull @StyleableRes int[]);
method @NonNull public android.content.res.TypedArray obtainStyledAttributes(@StyleRes int, @NonNull @StyleableRes int[]) throws android.content.res.Resources.NotFoundException;
@@ -50301,6 +50303,8 @@
method @android.view.ViewDebug.ExportedProperty(category="drawing") public float getAlpha();
method public android.view.animation.Animation getAnimation();
method public android.os.IBinder getApplicationWindowToken();
+ method @NonNull public java.util.List<java.lang.Integer> getAttributeResolutionStack();
+ method @NonNull public java.util.Map<java.lang.Integer,java.lang.Integer> getAttributeSourceResourceMap();
method @android.view.ViewDebug.ExportedProperty @Nullable public String[] getAutofillHints();
method public final android.view.autofill.AutofillId getAutofillId();
method public int getAutofillType();
@@ -50331,6 +50335,7 @@
method public void getDrawingRect(android.graphics.Rect);
method public long getDrawingTime();
method @android.view.ViewDebug.ExportedProperty(category="drawing") public float getElevation();
+ method @StyleRes public int getExplicitStyle();
method @android.view.ViewDebug.ExportedProperty public boolean getFilterTouchesWhenObscured();
method @android.view.ViewDebug.ExportedProperty public boolean getFitsSystemWindows();
method @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.View.NOT_FOCUSABLE, to="NOT_FOCUSABLE"), @android.view.ViewDebug.IntToString(from=android.view.View.FOCUSABLE, to="FOCUSABLE"), @android.view.ViewDebug.IntToString(from=android.view.View.FOCUSABLE_AUTO, to="FOCUSABLE_AUTO")}, category="focus") public int getFocusable();
@@ -50625,6 +50630,7 @@
method public static int resolveSizeAndState(int, int, int);
method public boolean restoreDefaultFocus();
method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
+ method public final void saveAttributeDataForStyleable(@NonNull android.content.Context, @NonNull int[], @Nullable android.util.AttributeSet, @NonNull android.content.res.TypedArray, int, int);
method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
method public void scheduleDrawable(@NonNull android.graphics.drawable.Drawable, @NonNull Runnable, long);
method public void scrollBy(int, int);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 21d66e5..cc419b8 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4565,16 +4565,25 @@
}
private void onCoreSettingsChange() {
- boolean debugViewAttributes =
- mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
- if (debugViewAttributes != View.mDebugViewAttributes) {
- View.mDebugViewAttributes = debugViewAttributes;
-
+ if (updateDebugViewAttributeState()) {
// request all activities to relaunch for the changes to take place
relaunchAllActivities();
}
}
+ private boolean updateDebugViewAttributeState() {
+ boolean previousState = View.sDebugViewAttributes;
+
+ View.sDebugViewAttributesApplicationPackage = mCoreSettings.getString(
+ Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, "");
+ String currentPackage = (mBoundApplication != null && mBoundApplication.appInfo != null)
+ ? mBoundApplication.appInfo.packageName : "";
+ View.sDebugViewAttributes =
+ mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0
+ || View.sDebugViewAttributesApplicationPackage.equals(currentPackage);
+ return previousState != View.sDebugViewAttributes;
+ }
+
private void relaunchAllActivities() {
for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
final Activity activity = entry.getValue().activity;
@@ -5950,8 +5959,7 @@
// true : use 24 hour format.
DateFormat.set24HourTimePref(is24Hr);
- View.mDebugViewAttributes =
- mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
+ updateDebugViewAttributeState();
StrictMode.initThreadDefaults(data.appInfo);
StrictMode.initVmDefaults(data.appInfo);
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 9e0a9ba..faf17e0 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -1051,6 +1051,14 @@
}
}
+ int[] getAttributeResolutionStack(long themePtr, @AttrRes int defStyleAttr,
+ @StyleRes int defStyleRes, @StyleRes int xmlStyle) {
+ synchronized (this) {
+ return nativeAttributeResolutionStack(
+ mObject, themePtr, xmlStyle, defStyleAttr, defStyleRes);
+ }
+ }
+
@UnsupportedAppUsage
boolean resolveAttrs(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes,
@Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues,
@@ -1419,6 +1427,8 @@
private static native @Nullable String nativeGetLastResourceResolution(long ptr);
// Style attribute retrieval native methods.
+ private static native int[] nativeAttributeResolutionStack(long ptr, long themePtr,
+ @StyleRes int xmlStyleRes, @AttrRes int defStyleAttr, @StyleRes int defStyleRes);
private static native void nativeApplyStyle(long ptr, long themePtr, @AttrRes int defStyleAttr,
@StyleRes int defStyleRes, long xmlParserPtr, @NonNull int[] inAttrs,
long outValuesAddress, long outIndicesAddress);
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 59db49e..a2ae994 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1725,6 +1725,68 @@
public void rebase() {
mThemeImpl.rebase();
}
+
+ /**
+ * Returns the resource ID for the style specified using {@code style="..."} in the
+ * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
+ * specified or otherwise not applicable.
+ * <p>
+ * Each {@link android.view.View} can have an explicit style specified in the layout file.
+ * This style is used first during the {@link android.view.View} attribute resolution, then
+ * if an attribute is not defined there the resource system looks at default style and theme
+ * as fallbacks.
+ *
+ * @param set The base set of attribute values.
+ *
+ * @return The resource ID for the style specified using {@code style="..."} in the
+ * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
+ * if not specified or otherwise not applicable.
+ */
+ @StyleRes
+ public int getExplicitStyle(@Nullable AttributeSet set) {
+ if (set == null) {
+ return ID_NULL;
+ }
+ int styleAttr = set.getStyleAttribute();
+ if (styleAttr == ID_NULL) {
+ return ID_NULL;
+ }
+ String styleAttrType = getResources().getResourceTypeName(styleAttr);
+ if ("attr".equals(styleAttrType)) {
+ TypedValue explicitStyle = new TypedValue();
+ boolean resolved = resolveAttribute(styleAttr, explicitStyle, true);
+ if (resolved) {
+ return explicitStyle.resourceId;
+ }
+ } else if ("style".equals(styleAttrType)) {
+ return styleAttr;
+ }
+ return ID_NULL;
+ }
+
+ /**
+ * Returns the ordered list of resource ID that are considered when resolving attribute
+ * values when making an equivalent call to
+ * {@link #obtainStyledAttributes(AttributeSet, int[], int, int)} . The list will include
+ * a set of explicit styles ({@code explicitStyleRes} and it will include the default styles
+ * ({@code defStyleAttr} and {@code defStyleRes}).
+ *
+ * @param defStyleAttr An attribute in the current theme that contains a
+ * reference to a style resource that supplies
+ * defaults values for the TypedArray. Can be
+ * 0 to not look for defaults.
+ * @param defStyleRes A resource identifier of a style resource that
+ * supplies default values for the TypedArray,
+ * used only if defStyleAttr is 0 or can not be found
+ * in the theme. Can be 0 to not look for defaults.
+ * @param explicitStyleRes A resource identifier of an explicit style resource.
+ * @return ordered list of resource ID that are considered when resolving attribute values.
+ */
+ public int[] getAttributeResolutionStack(@AttrRes int defStyleAttr,
+ @StyleRes int defStyleRes, @StyleRes int explicitStyleRes) {
+ return mThemeImpl.getAttributeResolutionStack(
+ defStyleAttr, defStyleRes, explicitStyleRes);
+ }
}
static class ThemeKey implements Cloneable {
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 9898079..da064c9 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -1488,6 +1488,32 @@
}
}
}
+
+ /**
+ * Returns the ordered list of resource ID that are considered when resolving attribute
+ * values when making an equivalent call to
+ * {@link #obtainStyledAttributes(Resources.Theme, AttributeSet, int[], int, int)}. The list
+ * will include a set of explicit styles ({@code explicitStyleRes} and it will include the
+ * default styles ({@code defStyleAttr} and {@code defStyleRes}).
+ *
+ * @param defStyleAttr An attribute in the current theme that contains a
+ * reference to a style resource that supplies
+ * defaults values for the TypedArray. Can be
+ * 0 to not look for defaults.
+ * @param defStyleRes A resource identifier of a style resource that
+ * supplies default values for the TypedArray,
+ * used only if defStyleAttr is 0 or can not be found
+ * in the theme. Can be 0 to not look for defaults.
+ * @param explicitStyleRes A resource identifier of an explicit style resource.
+ * @return ordered list of resource ID that are considered when resolving attribute values.
+ */
+ public int[] getAttributeResolutionStack(@AttrRes int defStyleAttr,
+ @StyleRes int defStyleRes, @StyleRes int explicitStyleRes) {
+ synchronized (mKey) {
+ return mAssets.getAttributeResolutionStack(
+ mTheme, defStyleAttr, defStyleRes, explicitStyleRes);
+ }
+ }
}
private static class LookupStack {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a8976aa..e95d6046 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9300,6 +9300,13 @@
public static final String DEBUG_VIEW_ATTRIBUTES = "debug_view_attributes";
/**
+ * Which application package is allowed to save View attribute data.
+ * @hide
+ */
+ public static final String DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE =
+ "debug_view_attributes_application_package";
+
+ /**
* Whether assisted GPS should be enabled or not.
* @hide
*/
@@ -14022,6 +14029,7 @@
INSTANT_APP_SETTINGS.add(TRANSITION_ANIMATION_SCALE);
INSTANT_APP_SETTINGS.add(ANIMATOR_DURATION_SCALE);
INSTANT_APP_SETTINGS.add(DEBUG_VIEW_ATTRIBUTES);
+ INSTANT_APP_SETTINGS.add(DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE);
INSTANT_APP_SETTINGS.add(WTF_IS_FATAL);
INSTANT_APP_SETTINGS.add(SEND_ACTION_APP_ERROR);
INSTANT_APP_SETTINGS.add(ZEN_MODE);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cb8f703..c641552 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -35,6 +35,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
+import android.annotation.StyleRes;
import android.annotation.TestApi;
import android.annotation.UiThread;
import android.annotation.UnsupportedAppUsage;
@@ -91,6 +92,7 @@
import android.util.Pools.SynchronizedPool;
import android.util.Property;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.util.StateSet;
import android.util.SuperNotCalledException;
import android.util.TypedValue;
@@ -821,7 +823,14 @@
*
* @hide
*/
- public static boolean mDebugViewAttributes = false;
+ public static boolean sDebugViewAttributes = false;
+
+ /**
+ * When set to this application package view will save its attribute data.
+ *
+ * @hide
+ */
+ public static String sDebugViewAttributesApplicationPackage;
/**
* Used to mark a View that has no ID.
@@ -5079,6 +5088,15 @@
@LayoutRes
private int mSourceLayoutId = ID_NULL;
+ @Nullable
+ private SparseIntArray mAttributeSourceResId;
+
+ @Nullable
+ private int[] mAttributeResolutionStack;
+
+ @StyleRes
+ private int mExplicitStyle;
+
/**
* Cached reference to the {@link ContentCaptureSession}, is reset on {@link #invalidate()}.
*/
@@ -5254,7 +5272,11 @@
final TypedArray a = context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
- if (mDebugViewAttributes) {
+ retrieveExplicitStyle(context.getTheme(), attrs);
+ saveAttributeDataForStyleable(context, com.android.internal.R.styleable.View, attrs, a,
+ defStyleAttr, defStyleRes);
+
+ if (sDebugViewAttributes) {
saveAttributeData(attrs, a);
}
@@ -5916,6 +5938,84 @@
}
/**
+ * Returns the ordered list of resource ID that are considered when resolving attribute values
+ * for this {@link View}. The list will include layout resource ID if the View is inflated from
+ * XML. It will also include a set of explicit styles if specified in XML using
+ * {@code style="..."}. Finally, it will include the default styles resolved from the theme.
+ *
+ * <p>
+ * <b>Note:</b> this method will only return actual values if the view attribute debugging
+ * is enabled in Android developer options.
+ *
+ * @return ordered list of resource ID that are considered when resolving attribute values for
+ * this {@link View}.
+ */
+ @NonNull
+ public List<Integer> getAttributeResolutionStack() {
+ ArrayList<Integer> stack = new ArrayList<>();
+ if (!sDebugViewAttributes) {
+ return stack;
+ }
+ if (mSourceLayoutId != ID_NULL) {
+ stack.add(mSourceLayoutId);
+ }
+ for (int i = 0; i < mAttributeResolutionStack.length; i++) {
+ stack.add(mAttributeResolutionStack[i]);
+ }
+ return stack;
+ }
+
+ /**
+ * Returns the mapping of attribute resource ID to source resource ID where the attribute value
+ * was set. Source resource ID can either be a layout resource ID, if the value was set in XML
+ * within the View tag, or a style resource ID, if the attribute was set in a style. The source
+ * resource value will be one of the resource IDs from {@link #getAttributeSourceResourceMap()}.
+ *
+ * <p>
+ * <b>Note:</b> this method will only return actual values if the view attribute debugging
+ * is enabled in Android developer options.
+ *
+ * @return mapping of attribute resource ID to source resource ID where the attribute value
+ * was set.
+ */
+ @NonNull
+ public Map<Integer, Integer> getAttributeSourceResourceMap() {
+ HashMap<Integer, Integer> map = new HashMap<>();
+ if (!sDebugViewAttributes) {
+ return map;
+ }
+ for (int i = 0; i < mAttributeSourceResId.size(); i++) {
+ map.put(mAttributeSourceResId.keyAt(i), mAttributeSourceResId.valueAt(i));
+ }
+ return map;
+ }
+
+ /**
+ * Returns the resource ID for the style specified using {@code style="..."} in the
+ * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise if not
+ * specified or otherwise not applicable.
+ * <p>
+ * Each {@link View} can have an explicit style specified in the layout file.
+ * This style is used first during the {@link View} attribute resolution, then if an attribute
+ * is not defined there the resource system looks at default style and theme as fallbacks.
+ *
+ * <p>
+ * <b>Note:</b> this method will only return actual values if the view attribute debugging
+ * is enabled in Android developer options.
+ *
+ * @return The resource ID for the style specified using {@code style="..."} in the
+ * {@link AttributeSet}'s backing XML element or {@link Resources#ID_NULL} otherwise
+ * if not specified or otherwise not applicable.
+ */
+ @StyleRes
+ public int getExplicitStyle() {
+ if (!sDebugViewAttributes) {
+ return ID_NULL;
+ }
+ return mExplicitStyle;
+ }
+
+ /**
* An implementation of OnClickListener that attempts to lazily load a
* named click handling method from a parent or ancestor context.
*/
@@ -6001,6 +6101,46 @@
return mAttributeMap;
}
+ private void retrieveExplicitStyle(@NonNull Resources.Theme theme,
+ @Nullable AttributeSet attrs) {
+ if (!sDebugViewAttributes) {
+ return;
+ }
+ mExplicitStyle = theme.getExplicitStyle(attrs);
+ }
+
+ /**
+ * Stores debugging information about attributes. This should be called in a constructor by
+ * every custom {@link View} that uses a custom styleable.
+ * @param context Context under which this view is created.
+ * @param styleable A reference to styleable array R.styleable.Foo
+ * @param attrs AttributeSet used to construct this view.
+ * @param t Resolved {@link TypedArray} returned by a call to
+ * {@link Resources#obtainAttributes(AttributeSet, int[])}.
+ * @param defStyleAttr Default style attribute passed into the view constructor.
+ * @param defStyleRes Default style resource passed into the view constructor.
+ */
+ public final void saveAttributeDataForStyleable(@NonNull Context context,
+ @NonNull int[] styleable, @Nullable AttributeSet attrs, @NonNull TypedArray t,
+ int defStyleAttr, int defStyleRes) {
+ if (!sDebugViewAttributes) {
+ return;
+ }
+
+ mAttributeResolutionStack = context.getTheme().getAttributeResolutionStack(
+ defStyleAttr, defStyleRes, mExplicitStyle);
+
+ if (mAttributeSourceResId == null) {
+ mAttributeSourceResId = new SparseIntArray();
+ }
+
+ final int indexCount = t.getIndexCount();
+ for (int j = 0; j < indexCount; ++j) {
+ final int index = t.getIndex(j);
+ mAttributeSourceResId.append(styleable[index], t.getSourceResourceId(index, 0));
+ }
+ }
+
private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
final int indexCount = t.getIndexCount();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0f4e23d..d876001 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1055,6 +1055,8 @@
int inputType = EditorInfo.TYPE_NULL;
a = theme.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.TextView, defStyleAttr, defStyleRes);
+ saveAttributeDataForStyleable(context, com.android.internal.R.styleable.TextView, attrs, a,
+ defStyleAttr, defStyleRes);
int firstBaselineToTopHeight = -1;
int lastBaselineToBottomHeight = -1;
int lineHeight = -1;
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 4101c04..d493ddf 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1105,6 +1105,46 @@
return array;
}
+static jintArray NativeAttributeResolutionStack(
+ JNIEnv* env, jclass /*clazz*/, jlong ptr,
+ jlong theme_ptr, jint xml_style_res,
+ jint def_style_attr, jint def_style_resid) {
+
+ ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
+ Theme* theme = reinterpret_cast<Theme*>(theme_ptr);
+ CHECK(theme->GetAssetManager() == &(*assetmanager));
+ (void) assetmanager;
+
+ // Load default style from attribute, if specified...
+ uint32_t def_style_flags = 0u;
+ if (def_style_attr != 0) {
+ Res_value value;
+ if (theme->GetAttribute(def_style_attr, &value, &def_style_flags) != kInvalidCookie) {
+ if (value.dataType == Res_value::TYPE_REFERENCE) {
+ def_style_resid = value.data;
+ }
+ }
+ }
+
+ auto style_stack = assetmanager->GetBagResIdStack(xml_style_res);
+ auto def_style_stack = assetmanager->GetBagResIdStack(def_style_resid);
+
+ jintArray array = env->NewIntArray(style_stack.size() + def_style_stack.size());
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
+
+ for (uint32_t i = 0; i < style_stack.size(); i++) {
+ jint attr_resid = style_stack[i];
+ env->SetIntArrayRegion(array, i, 1, &attr_resid);
+ }
+ for (uint32_t i = 0; i < def_style_stack.size(); i++) {
+ jint attr_resid = def_style_stack[i];
+ env->SetIntArrayRegion(array, style_stack.size() + i, 1, &attr_resid);
+ }
+ return array;
+}
+
static void NativeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr,
jint def_style_attr, jint def_style_resid, jlong xml_parser_ptr,
jintArray java_attrs, jlong out_values_ptr, jlong out_indices_ptr) {
@@ -1456,6 +1496,7 @@
(void*)NativeGetSizeConfigurations},
// Style attribute related methods.
+ {"nativeAttributeResolutionStack", "(JJIII)[I", (void*)NativeAttributeResolutionStack},
{"nativeApplyStyle", "(JJIIJ[IJJ)V", (void*)NativeApplyStyle},
{"nativeResolveAttrs", "(JJII[I[I[I[I)Z", (void*)NativeResolveAttrs},
{"nativeRetrieveAttributes", "(JJ[I[I[I)Z", (void*)NativeRetrieveAttributes},
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index a160451..d577653 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -259,6 +259,8 @@
optional SettingProto app = 1;
// Whether views are allowed to save their attribute data.
optional SettingProto view_attributes = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Which application package is allowed to save view attribute data.
+ optional SettingProto view_attributes_application_package = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional Debug debug = 37;
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 2cb925a..ec57f79 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -210,6 +210,7 @@
Settings.Global.DATA_STALL_VALID_DNS_TIME_THRESHOLD,
Settings.Global.DEBUG_APP,
Settings.Global.DEBUG_VIEW_ATTRIBUTES,
+ Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE,
Settings.Global.DEFAULT_DNS_SERVER,
Settings.Global.DEFAULT_INSTALL_LOCATION,
Settings.Global.DEFAULT_RESTRICT_BACKGROUND_DATA,
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 20303eb..81afd93 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -704,9 +704,29 @@
return cookie;
}
+const std::vector<uint32_t> AssetManager2::GetBagResIdStack(uint32_t resid) {
+ auto cached_iter = cached_bag_resid_stacks_.find(resid);
+ if (cached_iter != cached_bag_resid_stacks_.end()) {
+ return cached_iter->second;
+ } else {
+ auto found_resids = std::vector<uint32_t>();
+ GetBag(resid, found_resids);
+ // Cache style stacks if they are not already cached.
+ cached_bag_resid_stacks_[resid] = found_resids;
+ return found_resids;
+ }
+}
+
const ResolvedBag* AssetManager2::GetBag(uint32_t resid) {
auto found_resids = std::vector<uint32_t>();
- return GetBag(resid, found_resids);
+ auto bag = GetBag(resid, found_resids);
+
+ // Cache style stacks if they are not already cached.
+ auto cached_iter = cached_bag_resid_stacks_.find(resid);
+ if (cached_iter == cached_bag_resid_stacks_.end()) {
+ cached_bag_resid_stacks_[resid] = found_resids;
+ }
+ return bag;
}
const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>& child_resids) {
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index f29769b..d862182 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -237,6 +237,8 @@
// resource has been resolved yet.
std::string GetLastResourceResolution() const;
+ const std::vector<uint32_t> GetBagResIdStack(uint32_t resid);
+
// Retrieves the best matching bag/map resource with ID `resid`.
// This method will resolve all parent references for this bag and merge keys with the child.
// To iterate over the keys, use the following idiom:
@@ -355,6 +357,10 @@
// which involves some calculation.
std::unordered_map<uint32_t, util::unique_cptr<ResolvedBag>> cached_bags_;
+ // Cached set of bag resid stacks for each bag. These are cached because they might be requested
+ // a number of times for each view during View inspection.
+ std::unordered_map<uint32_t, std::vector<uint32_t>> cached_bag_resid_stacks_;
+
// Whether or not to save resource resolution steps
bool resource_resolution_logging_enabled_ = false;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index fad93cb..6152b8c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -457,6 +457,9 @@
dumpSetting(s, p,
Settings.Global.DEBUG_VIEW_ATTRIBUTES,
GlobalSettingsProto.Debug.VIEW_ATTRIBUTES);
+ dumpSetting(s, p,
+ Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE,
+ GlobalSettingsProto.Debug.VIEW_ATTRIBUTES_APPLICATION_PACKAGE);
p.end(debugToken);
final long defaultToken = p.start(GlobalSettingsProto.DEFAULT);
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 360d296..0194624 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -56,6 +56,8 @@
sGlobalSettingToTypeMap.put(Settings.Global.DEBUG_VIEW_ATTRIBUTES, int.class);
sGlobalSettingToTypeMap.put(
+ Settings.Global.DEBUG_VIEW_ATTRIBUTES_APPLICATION_PACKAGE, String.class);
+ sGlobalSettingToTypeMap.put(
Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE, String.class);
sGlobalSettingToTypeMap.put(
Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, String.class);