Merge "Dump theme inheritance information in UnsupportedOperationException"

This commit is contained in:
TreeHugger Robot
2021-12-14 05:45:31 +00:00
committed by Android (Google) Code Review
6 changed files with 94 additions and 2 deletions

View File

@@ -791,6 +791,21 @@ public final class AssetManager implements AutoCloseable {
}
}
/**
* To get the parent theme resource id according to the parameter theme resource id.
* @param resId theme resource id.
* @return the parent theme resource id.
* @hide
*/
@StyleRes
int getParentThemeIdentifier(@StyleRes int resId) {
synchronized (this) {
ensureValidLocked();
// name is checked in JNI.
return nativeGetParentThemeIdentifier(mObject, resId);
}
}
/**
* Enable resource resolution logging to track the steps taken to resolve the last resource
* entry retrieved. Stores the configuration and package names for each step.
@@ -1600,6 +1615,8 @@ public final class AssetManager implements AutoCloseable {
private static native void nativeThemeDump(long ptr, long themePtr, int priority, String tag,
String prefix);
static native @NativeConfig int nativeThemeGetChangingConfigurations(long themePtr);
@StyleRes
private static native int nativeGetParentThemeIdentifier(long ptr, @StyleRes int styleId);
// AssetInputStream related native methods.
private static native void nativeAssetDestroy(long assetPtr);

View File

@@ -1508,6 +1508,12 @@ public class Resources {
* retrieve XML attributes with style and theme information applied.
*/
public final class Theme {
/**
* To trace parent themes needs to prevent a cycle situation.
* e.x. A's parent is B, B's parent is C, and C's parent is A.
*/
private static final int MAX_NUMBER_OF_TRACING_PARENT_THEME = 100;
private final Object mLock = new Object();
@GuardedBy("mLock")
@@ -1801,6 +1807,13 @@ public class Resources {
}
}
@StyleRes
/*package*/ int getParentThemeIdentifier(@StyleRes int resId) {
synchronized (mLock) {
return mThemeImpl.getParentThemeIdentifier(resId);
}
}
/**
* @hide
*/
@@ -1948,8 +1961,27 @@ public class Resources {
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append('{');
sb.append("id=0x").append(Integer.toHexString(getAppliedStyleResId())).append(", ");
sb.append("themes=").append(Arrays.deepToString(getTheme()));
int themeResId = getAppliedStyleResId();
int i = 0;
sb.append("InheritanceMap=[");
while (themeResId > 0) {
if (i > MAX_NUMBER_OF_TRACING_PARENT_THEME) {
sb.append(",...");
break;
}
if (i > 0) {
sb.append(", ");
}
sb.append("id=0x").append(Integer.toHexString(themeResId));
sb.append(getResourcePackageName(themeResId))
.append(":").append(getResourceTypeName(themeResId))
.append("/").append(getResourceEntryName(themeResId));
i++;
themeResId = getParentThemeIdentifier(themeResId);
}
sb.append("], Themes=").append(Arrays.deepToString(getTheme()));
sb.append('}');
return sb.toString();
}

View File

@@ -1310,6 +1310,14 @@ public class ResourcesImpl {
return mThemeResId;
}
@StyleRes
/*package*/ int getParentThemeIdentifier(@StyleRes int resId) {
if (resId > 0) {
return mAssets.getParentThemeIdentifier(resId);
}
return 0;
}
void applyStyle(int resId, boolean force) {
mAssets.applyStyleToTheme(mTheme, resId, force);
mThemeResId = resId;

View File

@@ -881,6 +881,12 @@ static jint NativeGetResourceArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jin
return static_cast<jint>(bag->entry_count);
}
static jint NativeGetParentThemeIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) {
ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
const auto parentThemeResId = assetmanager->GetParentThemeResourceId(resid);
return parentThemeResId.value_or(0);
}
static jint NativeGetResourceIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring name,
jstring def_type, jstring def_package) {
ScopedUtfChars name_utf8(env, name);
@@ -1464,6 +1470,8 @@ static const JNINativeMethod gAssetManagerMethods[] = {
{"nativeGetResourceIntArray", "(JI)[I", (void*)NativeGetResourceIntArray},
{"nativeGetResourceArraySize", "(JI)I", (void*)NativeGetResourceArraySize},
{"nativeGetResourceArray", "(JI[I)I", (void*)NativeGetResourceArray},
{"nativeGetParentThemeIdentifier", "(JI)I",
(void*)NativeGetParentThemeIdentifier},
// AssetManager resource name/ID methods.
{"nativeGetResourceIdentifier", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",

View File

@@ -902,6 +902,27 @@ std::string AssetManager2::GetLastResourceResolution() const {
return log_stream.str();
}
base::expected<uint32_t, NullOrIOError> AssetManager2::GetParentThemeResourceId(uint32_t resid)
const {
auto entry = FindEntry(resid, 0u /* density_override */,
false /* stop_at_first_match */,
false /* ignore_configuration */);
if (!entry.has_value()) {
return base::unexpected(entry.error());
}
auto entry_map = std::get_if<incfs::verified_map_ptr<ResTable_map_entry>>(&entry->entry);
if (entry_map == nullptr) {
// Not a bag, nothing to do.
return base::unexpected(std::nullopt);
}
auto map = *entry_map;
const uint32_t parent_resid = dtohl(map->parent.ident);
return parent_resid;
}
base::expected<AssetManager2::ResourceName, NullOrIOError> AssetManager2::GetResourceName(
uint32_t resid) const {
auto result = FindEntry(resid, 0u /* density_override */, true /* stop_at_first_match */,

View File

@@ -192,6 +192,12 @@ class AssetManager2 {
std::unique_ptr<Asset> OpenNonAsset(const std::string& filename, ApkAssetsCookie cookie,
Asset::AccessMode mode) const;
// Returns the resource id of parent style of the specified theme.
//
// Returns a null error if the name is missing/corrupt, or an I/O error if reading resource data
// failed.
base::expected<uint32_t, NullOrIOError> GetParentThemeResourceId(uint32_t resid) const;
// Returns the resource name of the specified resource ID.
//
// Utf8 strings are preferred, and only if they are unavailable are the Utf16 variants populated.