Loading core/java/android/content/res/XmlBlock.java +30 −12 Original line number Diff line number Diff line Loading @@ -350,8 +350,11 @@ public final class XmlBlock implements AutoCloseable { } if (useLayoutReadwrite() && mUsesFeatureFlags && ev == START_TAG) { FlagInfo flag = nativeGetFlagInfo(mParseState); if (flag != null && flag.mNameIndex > 0) { AconfigFlags flags = ParsingPackageUtils.getAconfigFlags(); if (flags.skipCurrentElement(/* pkg= */ null, this)) { String flagName = getSequenceString(mStrings.getSequence(flag.mNameIndex)); if (flags.skip(/* pkg= */ null, flagName, flag.mNegated)) { int depth = 1; while (depth > 0) { int ev2 = nativeNext(mParseState); Loading @@ -366,6 +369,7 @@ public final class XmlBlock implements AutoCloseable { return next(); } } } if (mDecNextDepth) { mDepth--; mDecNextDepth = false; Loading Loading @@ -696,6 +700,17 @@ public final class XmlBlock implements AutoCloseable { private final boolean mUsesFeatureFlags; // This class only exists for JNI communication private static class FlagInfo { private int mNameIndex; private boolean mNegated; private FlagInfo(int nameIndex, boolean negated) { mNameIndex = nameIndex; mNegated = negated; } } private static final native long nativeCreate(byte[] data, int offset, int size); Loading Loading @@ -758,4 +773,7 @@ public final class XmlBlock implements AutoCloseable { @CriticalNative private static final native int nativeGetSourceResId(long state); @FastNative private static final native FlagInfo nativeGetFlagInfo(long state); } core/java/com/android/internal/pm/pkg/component/AconfigFlags.java +13 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.internal.pm.pkg.component; import static android.provider.flags.Flags.newStoragePublicApi; import static com.android.internal.pm.pkg.parsing.ParsingUtils.ANDROID_RES_NAMESPACE; import android.aconfig.DeviceProtos; Loading Loading @@ -320,6 +321,18 @@ public class AconfigFlags { negated = true; featureFlag = featureFlag.substring(1).strip(); } return skip(pkg, featureFlag, negated); } /** * Check if whatever is behind this flag should be skipped * * @param pkg The package being parsed * @param featureFlag The name of the flag being checked * @param negated Whether that flag is negated * @return true if the resource is disabled because of its feature flag */ public boolean skip(@Nullable ParsingPackage pkg, String featureFlag, boolean negated) { Boolean flagValue = getFlagValue(featureFlag); boolean isUndefined = false; if (flagValue == null) { Loading core/jni/android_util_XmlBlock.cpp +65 −54 Original line number Diff line number Diff line Loading @@ -16,22 +16,25 @@ */ #define LOG_TAG "XmlBlock" #include "jni.h" #include <nativehelper/JNIHelp.h> #include <core_jni_helpers.h> #include <androidfw/AssetManager.h> #include <androidfw/ResourceTypes.h> #include <core_jni_helpers.h> #include <nativehelper/JNIHelp.h> #include <stdio.h> #include <utils/Log.h> #include <utils/misc.h> #include <stdio.h> #include "jni.h" namespace android { constexpr int kNullDocument = UNEXPECTED_NULL; // The reason not to ResXMLParser::BAD_DOCUMENT which is -1 is that other places use the same value. constexpr int kBadDocument = BAD_VALUE; static struct flag_info_fields { jclass jClass; jmethodID jConstructor; } gFlagInfo; // ---------------------------------------------------------------------------- static jlong android_content_XmlBlock_nativeCreate(JNIEnv* env, jobject clazz, Loading Loading @@ -338,6 +341,21 @@ static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz, delete osb; } static jobject android_content_XmlBlock_nativeGetFlagInfo(JNIEnv* env, jobject clazz, jlong token) { ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); if (st == nullptr) { return nullptr; } if (auto info = st->getFlagInfo()) { return env->NewObject(gFlagInfo.jClass, gFlagInfo.jConstructor, static_cast<jint>(info->flagNameIndex), static_cast<jboolean>(info->flagNegated)); } else { return nullptr; } } // ---------------------------------------------------------------------------- /* Loading @@ -345,57 +363,50 @@ static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz, */ static const JNINativeMethod gXmlBlockMethods[] = { /* name, signature, funcPtr */ { "nativeCreate", "([BII)J", (void*) android_content_XmlBlock_nativeCreate }, { "nativeGetStringBlock", "(J)J", (void*) android_content_XmlBlock_nativeGetStringBlock }, { "nativeCreateParseState", "(JI)J", (void*) android_content_XmlBlock_nativeCreateParseState }, {"nativeCreate", "([BII)J", (void*)android_content_XmlBlock_nativeCreate}, {"nativeGetStringBlock", "(J)J", (void*)android_content_XmlBlock_nativeGetStringBlock}, {"nativeCreateParseState", "(JI)J", (void*)android_content_XmlBlock_nativeCreateParseState}, {"nativeDestroyParseState", "(J)V", (void*)android_content_XmlBlock_nativeDestroyParseState}, { "nativeDestroy", "(J)V", (void*) android_content_XmlBlock_nativeDestroy }, {"nativeDestroy", "(J)V", (void*)android_content_XmlBlock_nativeDestroy}, // ------------------- @FastNative ---------------------- { "nativeNext", "(J)I", (void*) android_content_XmlBlock_nativeNext }, { "nativeGetNamespace", "(J)I", (void*) android_content_XmlBlock_nativeGetNamespace }, { "nativeGetName", "(J)I", (void*) android_content_XmlBlock_nativeGetName }, { "nativeGetText", "(J)I", (void*) android_content_XmlBlock_nativeGetText }, { "nativeGetLineNumber", "(J)I", (void*) android_content_XmlBlock_nativeGetLineNumber }, {"nativeNext", "(J)I", (void*)android_content_XmlBlock_nativeNext}, {"nativeGetNamespace", "(J)I", (void*)android_content_XmlBlock_nativeGetNamespace}, {"nativeGetName", "(J)I", (void*)android_content_XmlBlock_nativeGetName}, {"nativeGetText", "(J)I", (void*)android_content_XmlBlock_nativeGetText}, {"nativeGetLineNumber", "(J)I", (void*)android_content_XmlBlock_nativeGetLineNumber}, {"nativeGetAttributeCount", "(J)I", (void*)android_content_XmlBlock_nativeGetAttributeCount}, {"nativeGetAttributeNamespace", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeNamespace}, { "nativeGetAttributeName", "(JI)I", (void*) android_content_XmlBlock_nativeGetAttributeName }, {"nativeGetAttributeName", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeName}, {"nativeGetAttributeResource", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeResource}, {"nativeGetAttributeDataType", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeDataType}, { "nativeGetAttributeData", "(JI)I", (void*) android_content_XmlBlock_nativeGetAttributeData }, {"nativeGetAttributeData", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeData}, {"nativeGetAttributeStringValue", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeStringValue}, {"nativeGetAttributeIndex", "(JLjava/lang/String;Ljava/lang/String;)I", (void*)android_content_XmlBlock_nativeGetAttributeIndex}, { "nativeGetIdAttribute", "(J)I", (void*) android_content_XmlBlock_nativeGetIdAttribute }, {"nativeGetIdAttribute", "(J)I", (void*)android_content_XmlBlock_nativeGetIdAttribute}, {"nativeGetClassAttribute", "(J)I", (void*)android_content_XmlBlock_nativeGetClassAttribute}, {"nativeGetStyleAttribute", "(J)I", (void*)android_content_XmlBlock_nativeGetStyleAttribute}, { "nativeGetSourceResId", "(J)I", (void*) android_content_XmlBlock_nativeGetSourceResId}, {"nativeGetSourceResId", "(J)I", (void*)android_content_XmlBlock_nativeGetSourceResId}, {"nativeGetFlagInfo", "(J)Landroid/content/res/XmlBlock$FlagInfo;", (void*)android_content_XmlBlock_nativeGetFlagInfo}, }; int register_android_content_XmlBlock(JNIEnv* env) { gFlagInfo.jClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/content/res/XmlBlock$FlagInfo")); gFlagInfo.jConstructor = GetMethodIDOrDie(env, gFlagInfo.jClass, "<init>", "(IZ)V"); return RegisterMethodsOrDie(env, "android/content/res/XmlBlock", gXmlBlockMethods, NELEM(gXmlBlockMethods)); } Loading libs/androidfw/ResourceTypes.cpp +23 −1 Original line number Diff line number Diff line Loading @@ -44,7 +44,7 @@ #include <utils/Log.h> #include <utils/String16.h> #include <utils/String8.h> #include <android-base/logging.h> #ifdef __ANDROID__ #include <binder/TextOutput.h> Loading Loading @@ -1407,6 +1407,28 @@ size_t ResXMLParser::getAttributeCount() const return 0; } std::optional<ResXMLParser::ResXMLFlagInfo> ResXMLParser::getFlagInfo() const { if (mEventCode == START_TAG) { const auto* attrExt = ((const ResXMLTree_attrExt*)mCurExt); uint16_t s1 = sizeof(ResXMLTree_attrExt); uint16_t s2 = sizeof(ResXMLTreeFlagExt); // Flag information is stored in an ResXMLTreeFlagExt. If there is a flag, this is // stored right after the ResXMLTree_attrExt. To determine if there is a flagExt we see // if the offset to where attributes start is big enough to store both a ResXMLTree_attrExt // and a ResXMLTreeFlagExt. if (attrExt->attributeStart == (s1 + s2)) { auto flag_ext = (const ResXMLTreeFlagExt*)(((const uint8_t*)mCurExt) + s1); if (flag_ext->descriptor == ResXMLTreeExtDescriptor::FLAG_INFO) { return ResXMLParser::ResXMLFlagInfo{flag_ext->flag_name.index, flag_ext->flag_negated}; } } } return {}; } int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const { if (mEventCode == START_TAG) { Loading libs/androidfw/include/androidfw/ResourceTypes.h +32 −1 Original line number Diff line number Diff line Loading @@ -715,6 +715,29 @@ struct ResXMLTree_attrExt uint16_t styleIndex; }; enum ResXMLTreeExtDescriptor : uint8_t { PADDING = 0x00, FLAG_INFO = 0x01, }; struct ResXMLTreeFlagExt { // defines the type of the extended element structure ResXMLTreeExtDescriptor descriptor; // if the flag condition is negated bool flag_negated; // a hole for 4-byte alignment uint16_t reserved; // The reference into the string pool that the flag name is stored at ResStringPool_ref flag_name; }; static_assert(sizeof(ResXMLTreeFlagExt) == 8); struct ResXMLTree_attribute { // Namespace of this attribute. Loading Loading @@ -758,6 +781,12 @@ public: const void* curExt; }; struct ResXMLFlagInfo { uint32_t flagNameIndex; bool flagNegated; }; void restart(); const ResStringPool& getStrings() const; Loading Loading @@ -794,6 +823,8 @@ public: size_t getAttributeCount() const; std::optional<ResXMLFlagInfo> getFlagInfo() const; // Returns -1 if no namespace, -2 if idx out of range. int32_t getAttributeNamespaceID(size_t idx) const; const char16_t* getAttributeNamespace(size_t idx, size_t* outLen) const; Loading Loading
core/java/android/content/res/XmlBlock.java +30 −12 Original line number Diff line number Diff line Loading @@ -350,8 +350,11 @@ public final class XmlBlock implements AutoCloseable { } if (useLayoutReadwrite() && mUsesFeatureFlags && ev == START_TAG) { FlagInfo flag = nativeGetFlagInfo(mParseState); if (flag != null && flag.mNameIndex > 0) { AconfigFlags flags = ParsingPackageUtils.getAconfigFlags(); if (flags.skipCurrentElement(/* pkg= */ null, this)) { String flagName = getSequenceString(mStrings.getSequence(flag.mNameIndex)); if (flags.skip(/* pkg= */ null, flagName, flag.mNegated)) { int depth = 1; while (depth > 0) { int ev2 = nativeNext(mParseState); Loading @@ -366,6 +369,7 @@ public final class XmlBlock implements AutoCloseable { return next(); } } } if (mDecNextDepth) { mDepth--; mDecNextDepth = false; Loading Loading @@ -696,6 +700,17 @@ public final class XmlBlock implements AutoCloseable { private final boolean mUsesFeatureFlags; // This class only exists for JNI communication private static class FlagInfo { private int mNameIndex; private boolean mNegated; private FlagInfo(int nameIndex, boolean negated) { mNameIndex = nameIndex; mNegated = negated; } } private static final native long nativeCreate(byte[] data, int offset, int size); Loading Loading @@ -758,4 +773,7 @@ public final class XmlBlock implements AutoCloseable { @CriticalNative private static final native int nativeGetSourceResId(long state); @FastNative private static final native FlagInfo nativeGetFlagInfo(long state); }
core/java/com/android/internal/pm/pkg/component/AconfigFlags.java +13 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.internal.pm.pkg.component; import static android.provider.flags.Flags.newStoragePublicApi; import static com.android.internal.pm.pkg.parsing.ParsingUtils.ANDROID_RES_NAMESPACE; import android.aconfig.DeviceProtos; Loading Loading @@ -320,6 +321,18 @@ public class AconfigFlags { negated = true; featureFlag = featureFlag.substring(1).strip(); } return skip(pkg, featureFlag, negated); } /** * Check if whatever is behind this flag should be skipped * * @param pkg The package being parsed * @param featureFlag The name of the flag being checked * @param negated Whether that flag is negated * @return true if the resource is disabled because of its feature flag */ public boolean skip(@Nullable ParsingPackage pkg, String featureFlag, boolean negated) { Boolean flagValue = getFlagValue(featureFlag); boolean isUndefined = false; if (flagValue == null) { Loading
core/jni/android_util_XmlBlock.cpp +65 −54 Original line number Diff line number Diff line Loading @@ -16,22 +16,25 @@ */ #define LOG_TAG "XmlBlock" #include "jni.h" #include <nativehelper/JNIHelp.h> #include <core_jni_helpers.h> #include <androidfw/AssetManager.h> #include <androidfw/ResourceTypes.h> #include <core_jni_helpers.h> #include <nativehelper/JNIHelp.h> #include <stdio.h> #include <utils/Log.h> #include <utils/misc.h> #include <stdio.h> #include "jni.h" namespace android { constexpr int kNullDocument = UNEXPECTED_NULL; // The reason not to ResXMLParser::BAD_DOCUMENT which is -1 is that other places use the same value. constexpr int kBadDocument = BAD_VALUE; static struct flag_info_fields { jclass jClass; jmethodID jConstructor; } gFlagInfo; // ---------------------------------------------------------------------------- static jlong android_content_XmlBlock_nativeCreate(JNIEnv* env, jobject clazz, Loading Loading @@ -338,6 +341,21 @@ static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz, delete osb; } static jobject android_content_XmlBlock_nativeGetFlagInfo(JNIEnv* env, jobject clazz, jlong token) { ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); if (st == nullptr) { return nullptr; } if (auto info = st->getFlagInfo()) { return env->NewObject(gFlagInfo.jClass, gFlagInfo.jConstructor, static_cast<jint>(info->flagNameIndex), static_cast<jboolean>(info->flagNegated)); } else { return nullptr; } } // ---------------------------------------------------------------------------- /* Loading @@ -345,57 +363,50 @@ static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz, */ static const JNINativeMethod gXmlBlockMethods[] = { /* name, signature, funcPtr */ { "nativeCreate", "([BII)J", (void*) android_content_XmlBlock_nativeCreate }, { "nativeGetStringBlock", "(J)J", (void*) android_content_XmlBlock_nativeGetStringBlock }, { "nativeCreateParseState", "(JI)J", (void*) android_content_XmlBlock_nativeCreateParseState }, {"nativeCreate", "([BII)J", (void*)android_content_XmlBlock_nativeCreate}, {"nativeGetStringBlock", "(J)J", (void*)android_content_XmlBlock_nativeGetStringBlock}, {"nativeCreateParseState", "(JI)J", (void*)android_content_XmlBlock_nativeCreateParseState}, {"nativeDestroyParseState", "(J)V", (void*)android_content_XmlBlock_nativeDestroyParseState}, { "nativeDestroy", "(J)V", (void*) android_content_XmlBlock_nativeDestroy }, {"nativeDestroy", "(J)V", (void*)android_content_XmlBlock_nativeDestroy}, // ------------------- @FastNative ---------------------- { "nativeNext", "(J)I", (void*) android_content_XmlBlock_nativeNext }, { "nativeGetNamespace", "(J)I", (void*) android_content_XmlBlock_nativeGetNamespace }, { "nativeGetName", "(J)I", (void*) android_content_XmlBlock_nativeGetName }, { "nativeGetText", "(J)I", (void*) android_content_XmlBlock_nativeGetText }, { "nativeGetLineNumber", "(J)I", (void*) android_content_XmlBlock_nativeGetLineNumber }, {"nativeNext", "(J)I", (void*)android_content_XmlBlock_nativeNext}, {"nativeGetNamespace", "(J)I", (void*)android_content_XmlBlock_nativeGetNamespace}, {"nativeGetName", "(J)I", (void*)android_content_XmlBlock_nativeGetName}, {"nativeGetText", "(J)I", (void*)android_content_XmlBlock_nativeGetText}, {"nativeGetLineNumber", "(J)I", (void*)android_content_XmlBlock_nativeGetLineNumber}, {"nativeGetAttributeCount", "(J)I", (void*)android_content_XmlBlock_nativeGetAttributeCount}, {"nativeGetAttributeNamespace", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeNamespace}, { "nativeGetAttributeName", "(JI)I", (void*) android_content_XmlBlock_nativeGetAttributeName }, {"nativeGetAttributeName", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeName}, {"nativeGetAttributeResource", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeResource}, {"nativeGetAttributeDataType", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeDataType}, { "nativeGetAttributeData", "(JI)I", (void*) android_content_XmlBlock_nativeGetAttributeData }, {"nativeGetAttributeData", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeData}, {"nativeGetAttributeStringValue", "(JI)I", (void*)android_content_XmlBlock_nativeGetAttributeStringValue}, {"nativeGetAttributeIndex", "(JLjava/lang/String;Ljava/lang/String;)I", (void*)android_content_XmlBlock_nativeGetAttributeIndex}, { "nativeGetIdAttribute", "(J)I", (void*) android_content_XmlBlock_nativeGetIdAttribute }, {"nativeGetIdAttribute", "(J)I", (void*)android_content_XmlBlock_nativeGetIdAttribute}, {"nativeGetClassAttribute", "(J)I", (void*)android_content_XmlBlock_nativeGetClassAttribute}, {"nativeGetStyleAttribute", "(J)I", (void*)android_content_XmlBlock_nativeGetStyleAttribute}, { "nativeGetSourceResId", "(J)I", (void*) android_content_XmlBlock_nativeGetSourceResId}, {"nativeGetSourceResId", "(J)I", (void*)android_content_XmlBlock_nativeGetSourceResId}, {"nativeGetFlagInfo", "(J)Landroid/content/res/XmlBlock$FlagInfo;", (void*)android_content_XmlBlock_nativeGetFlagInfo}, }; int register_android_content_XmlBlock(JNIEnv* env) { gFlagInfo.jClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/content/res/XmlBlock$FlagInfo")); gFlagInfo.jConstructor = GetMethodIDOrDie(env, gFlagInfo.jClass, "<init>", "(IZ)V"); return RegisterMethodsOrDie(env, "android/content/res/XmlBlock", gXmlBlockMethods, NELEM(gXmlBlockMethods)); } Loading
libs/androidfw/ResourceTypes.cpp +23 −1 Original line number Diff line number Diff line Loading @@ -44,7 +44,7 @@ #include <utils/Log.h> #include <utils/String16.h> #include <utils/String8.h> #include <android-base/logging.h> #ifdef __ANDROID__ #include <binder/TextOutput.h> Loading Loading @@ -1407,6 +1407,28 @@ size_t ResXMLParser::getAttributeCount() const return 0; } std::optional<ResXMLParser::ResXMLFlagInfo> ResXMLParser::getFlagInfo() const { if (mEventCode == START_TAG) { const auto* attrExt = ((const ResXMLTree_attrExt*)mCurExt); uint16_t s1 = sizeof(ResXMLTree_attrExt); uint16_t s2 = sizeof(ResXMLTreeFlagExt); // Flag information is stored in an ResXMLTreeFlagExt. If there is a flag, this is // stored right after the ResXMLTree_attrExt. To determine if there is a flagExt we see // if the offset to where attributes start is big enough to store both a ResXMLTree_attrExt // and a ResXMLTreeFlagExt. if (attrExt->attributeStart == (s1 + s2)) { auto flag_ext = (const ResXMLTreeFlagExt*)(((const uint8_t*)mCurExt) + s1); if (flag_ext->descriptor == ResXMLTreeExtDescriptor::FLAG_INFO) { return ResXMLParser::ResXMLFlagInfo{flag_ext->flag_name.index, flag_ext->flag_negated}; } } } return {}; } int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const { if (mEventCode == START_TAG) { Loading
libs/androidfw/include/androidfw/ResourceTypes.h +32 −1 Original line number Diff line number Diff line Loading @@ -715,6 +715,29 @@ struct ResXMLTree_attrExt uint16_t styleIndex; }; enum ResXMLTreeExtDescriptor : uint8_t { PADDING = 0x00, FLAG_INFO = 0x01, }; struct ResXMLTreeFlagExt { // defines the type of the extended element structure ResXMLTreeExtDescriptor descriptor; // if the flag condition is negated bool flag_negated; // a hole for 4-byte alignment uint16_t reserved; // The reference into the string pool that the flag name is stored at ResStringPool_ref flag_name; }; static_assert(sizeof(ResXMLTreeFlagExt) == 8); struct ResXMLTree_attribute { // Namespace of this attribute. Loading Loading @@ -758,6 +781,12 @@ public: const void* curExt; }; struct ResXMLFlagInfo { uint32_t flagNameIndex; bool flagNegated; }; void restart(); const ResStringPool& getStrings() const; Loading Loading @@ -794,6 +823,8 @@ public: size_t getAttributeCount() const; std::optional<ResXMLFlagInfo> getFlagInfo() const; // Returns -1 if no namespace, -2 if idx out of range. int32_t getAttributeNamespaceID(size_t idx) const; const char16_t* getAttributeNamespace(size_t idx, size_t* outLen) const; Loading