From cc5d4a3cb3a6b13b0f1fabb9ad9266d7b656a2c7 Mon Sep 17 00:00:00 2001 From: Julian Winkler Date: Sun, 12 May 2024 17:03:27 +0200 Subject: [PATCH] use libandroidfw for resource XML parsing androidfw is implemented in native code and has much better performance than ARSClib --- meson.build | 1 + .../android_content_res_AssetManager.c | 13 ++ .../content/android_content_res_XmlBlock.c | 127 ++++++++++++++++++ .../android_content_res_AssetManager.h | 8 ++ .../android_content_res_XmlBlock.h | 96 +++++++------ .../android/content/res/AssetManager.java | 55 ++++---- .../android/content/res/Resources.java | 4 +- .../android/content/res/TypedArray.java | 21 ++- .../android/content/res/XmlBlock.java | 70 +++++----- 9 files changed, 280 insertions(+), 115 deletions(-) create mode 100644 src/api-impl-jni/content/android_content_res_XmlBlock.c diff --git a/meson.build b/meson.build index 31a6c16a..b6ec2682 100644 --- a/meson.build +++ b/meson.build @@ -86,6 +86,7 @@ libtranslationlayer_so = shared_library('translation_layer_main', [ 'src/api-impl-jni/audio/android_media_SoundPool.c', 'src/api-impl-jni/content/android_content_ClipboardManager.c', 'src/api-impl-jni/content/android_content_Context.c', + 'src/api-impl-jni/content/android_content_res_XmlBlock.c', 'src/api-impl-jni/database/android_database_SQLiteCommon.c', 'src/api-impl-jni/database/android_database_SQLiteConnection.c', 'src/api-impl-jni/egl/com_google_android_gles_jni_EGLImpl.c', diff --git a/src/api-impl-jni/android_content_res_AssetManager.c b/src/api-impl-jni/android_content_res_AssetManager.c index 34b24a8e..f8b0b624 100644 --- a/src/api-impl-jni/android_content_res_AssetManager.c +++ b/src/api-impl-jni/android_content_res_AssetManager.c @@ -447,3 +447,16 @@ JNIEXPORT jobjectArray JNICALL Java_android_content_res_AssetManager_list(JNIEnv return array; } + +JNIEXPORT jlong JNICALL Java_android_content_res_AssetManager_openXmlAssetNative(JNIEnv *env, jobject this, jint cookie, jstring _file_name) +{ + struct AssetManager *asset_manager = _PTR(_GET_LONG_FIELD(this, "mObject")); + const char *file_name = (*env)->GetStringUTFChars(env, _file_name, NULL); + struct Asset *asset = AssetManager_openNonAsset(asset_manager, file_name, ACCESS_BUFFER); + (*env)->ReleaseStringUTFChars(env, _file_name, file_name); + + struct ResXMLTree *res_xml = ResXMLTree_new(); + ResXMLTree_setTo(res_xml, Asset_getBuffer(asset, true), Asset_getLength(asset), true); + Asset_delete(asset); + return _INTPTR(res_xml); +} diff --git a/src/api-impl-jni/content/android_content_res_XmlBlock.c b/src/api-impl-jni/content/android_content_res_XmlBlock.c new file mode 100644 index 00000000..bbafac1c --- /dev/null +++ b/src/api-impl-jni/content/android_content_res_XmlBlock.c @@ -0,0 +1,127 @@ +#include + +#include "../generated_headers/android_content_res_XmlBlock.h" + +#include "../defines.h" + +JNIEXPORT jlong JNICALL Java_android_content_res_XmlBlock_nativeCreateParseState(JNIEnv *env, jobject this, jlong block) +{ + struct ResXMLTree *tree = (struct ResXMLTree *)_PTR(block); + struct ResXMLParser *parser = ResXMLParser_new(tree); + ResXMLParser_restart(parser); + return _INTPTR(parser); +} + +JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeNext(JNIEnv *env, jobject this, jlong parser_ptr) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + enum event_code_t ret = ResXMLParser_next(parser); + if (ret > 0x100) + return ret - 0x100; + return ret; +} + +JNIEXPORT jstring JNICALL Java_android_content_res_XmlBlock_nativeGetPooledString(JNIEnv *env, jobject this, jlong parser_ptr, jint index) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + const struct ResStringPool *string_pool = ResXMLParser_getStrings(parser); + size_t len; + const char16_t *string = ResStringPool_stringAt(string_pool, index, &len); + if (!string) + return NULL; + return (*env)->NewString(env, string, len); +} + +JNIEXPORT jstring JNICALL Java_android_content_res_XmlBlock_nativeGetName(JNIEnv *env, jobject this, jlong parser_ptr) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + int idx = ResXMLParser_getElementNameID(parser); + if (idx < 0) + return NULL; + return Java_android_content_res_XmlBlock_nativeGetPooledString(env, this, parser_ptr, idx); +} + +JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeCount(JNIEnv *env, jobject this, jlong parser_ptr) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + return ResXMLParser_getAttributeCount(parser); +} + +JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeResource(JNIEnv *env, jobject this, jlong parser_ptr, jint index) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + return ResXMLParser_getAttributeNameResID(parser, index); +} + +JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeIndex(JNIEnv *env, jobject this, jlong parser_ptr, jstring namespace_str, jstring name_str) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + const char16_t *namespace = NULL; + int namespace_len = 0; + if (namespace_str) { + namespace = (*env)->GetStringChars(env, namespace_str, NULL); + namespace_len = (*env)->GetStringLength(env, namespace_str); + } + const char16_t *name = (*env)->GetStringChars(env, name_str, NULL); + int name_len = (*env)->GetStringLength(env, name_str); + int ret = ResXMLParser_indexOfAttribute(parser, namespace, namespace_len, name, name_len); + if (namespace_str) + (*env)->ReleaseStringChars(env, namespace_str, namespace); + (*env)->ReleaseStringChars(env, name_str, name); + return ret; +} + +JNIEXPORT jstring JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeStringValue(JNIEnv *env, jobject this, jlong parser_ptr, jint index) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + int idx = ResXMLParser_getAttributeValueStringID(parser, index); + if (idx < 0) + return NULL; + return Java_android_content_res_XmlBlock_nativeGetPooledString(env, this, parser_ptr, idx); +} + +JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetLineNumber(JNIEnv *env, jobject this, jlong parser_ptr) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + return ResXMLParser_getLineNumber(parser); +} + +JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeDataType(JNIEnv *env, jobject this, jlong parser_ptr, jint index) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + return ResXMLParser_getAttributeDataType(parser, index); +} + +JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeData(JNIEnv *env, jobject this, jlong parser_ptr, jint index) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + return ResXMLParser_getAttributeData(parser, index); +} + +JNIEXPORT void JNICALL Java_android_content_res_XmlBlock_nativeDestroyParseState(JNIEnv *env, jobject this, jlong parser_ptr) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + ResXMLParser_delete(parser); +} + +JNIEXPORT void JNICALL Java_android_content_res_XmlBlock_nativeDestroy(JNIEnv *env, jobject this, jlong block) +{ + struct ResXMLTree *tree = (struct ResXMLTree *)_PTR(block); + ResXMLTree_delete(tree); +} + +JNIEXPORT jstring JNICALL Java_android_content_res_XmlBlock_nativeGetClassAttribute(JNIEnv *env, jobject this, jlong parser_ptr) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + int idx = ResXMLParser_indexOfClass(parser); + return Java_android_content_res_XmlBlock_nativeGetAttributeStringValue(env, this, parser_ptr, idx); +} + +JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetStyleAttribute(JNIEnv *env, jobject this, jlong parser_ptr) +{ + struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr); + int idx = ResXMLParser_indexOfStyle(parser); + struct Res_value value; + ResXMLParser_getAttributeValue(parser, idx, &value); + return value.data; +} diff --git a/src/api-impl-jni/generated_headers/android_content_res_AssetManager.h b/src/api-impl-jni/generated_headers/android_content_res_AssetManager.h index 6d34a060..1356d992 100644 --- a/src/api-impl-jni/generated_headers/android_content_res_AssetManager.h +++ b/src/api-impl-jni/generated_headers/android_content_res_AssetManager.h @@ -329,6 +329,14 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadThemeAttributeV JNIEXPORT void JNICALL Java_android_content_res_AssetManager_dumpTheme (JNIEnv *, jclass, jlong, jint, jstring, jstring); +/* + * Class: android_content_res_AssetManager + * Method: openXmlAssetNative + * Signature: (ILjava/lang/String;)J + */ +JNIEXPORT jlong JNICALL Java_android_content_res_AssetManager_openXmlAssetNative + (JNIEnv *, jobject, jint, jstring); + /* * Class: android_content_res_AssetManager * Method: getArrayStringResource diff --git a/src/api-impl-jni/generated_headers/android_content_res_XmlBlock.h b/src/api-impl-jni/generated_headers/android_content_res_XmlBlock.h index 366c0f71..dda6d674 100644 --- a/src/api-impl-jni/generated_headers/android_content_res_XmlBlock.h +++ b/src/api-impl-jni/generated_headers/android_content_res_XmlBlock.h @@ -20,162 +20,170 @@ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeCreate /* * Class: android_content_res_XmlBlock * Method: nativeGetStringBlock - * Signature: (I)I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetStringBlock - (JNIEnv *, jclass, jint); + (JNIEnv *, jclass, jlong); /* * Class: android_content_res_XmlBlock * Method: nativeCreateParseState - * Signature: (I)I + * Signature: (J)J */ -JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeCreateParseState - (JNIEnv *, jclass, jint); +JNIEXPORT jlong JNICALL Java_android_content_res_XmlBlock_nativeCreateParseState + (JNIEnv *, jclass, jlong); /* * Class: android_content_res_XmlBlock * Method: nativeNext - * Signature: (I)I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeNext - (JNIEnv *, jclass, jint); + (JNIEnv *, jclass, jlong); /* * Class: android_content_res_XmlBlock * Method: nativeGetNamespace - * Signature: (I)I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetNamespace - (JNIEnv *, jclass, jint); + (JNIEnv *, jclass, jlong); /* * Class: android_content_res_XmlBlock * Method: nativeGetName - * Signature: (I)I + * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetName - (JNIEnv *, jclass, jint); +JNIEXPORT jstring JNICALL Java_android_content_res_XmlBlock_nativeGetName + (JNIEnv *, jclass, jlong); /* * Class: android_content_res_XmlBlock * Method: nativeGetText - * Signature: (I)I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetText - (JNIEnv *, jclass, jint); + (JNIEnv *, jclass, jlong); /* * Class: android_content_res_XmlBlock * Method: nativeGetLineNumber - * Signature: (I)I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetLineNumber - (JNIEnv *, jclass, jint); + (JNIEnv *, jclass, jlong); /* * Class: android_content_res_XmlBlock * Method: nativeGetAttributeCount - * Signature: (I)I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeCount - (JNIEnv *, jclass, jint); + (JNIEnv *, jclass, jlong); /* * Class: android_content_res_XmlBlock * Method: nativeGetAttributeNamespace - * Signature: (II)I + * Signature: (JI)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeNamespace - (JNIEnv *, jclass, jint, jint); + (JNIEnv *, jclass, jlong, jint); /* * Class: android_content_res_XmlBlock * Method: nativeGetAttributeName - * Signature: (II)I + * Signature: (JI)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeName - (JNIEnv *, jclass, jint, jint); + (JNIEnv *, jclass, jlong, jint); /* * Class: android_content_res_XmlBlock * Method: nativeGetAttributeResource - * Signature: (II)I + * Signature: (JI)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeResource - (JNIEnv *, jclass, jint, jint); + (JNIEnv *, jclass, jlong, jint); /* * Class: android_content_res_XmlBlock * Method: nativeGetAttributeDataType - * Signature: (II)I + * Signature: (JI)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeDataType - (JNIEnv *, jclass, jint, jint); + (JNIEnv *, jclass, jlong, jint); /* * Class: android_content_res_XmlBlock * Method: nativeGetAttributeData - * Signature: (II)I + * Signature: (JI)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeData - (JNIEnv *, jclass, jint, jint); + (JNIEnv *, jclass, jlong, jint); /* * Class: android_content_res_XmlBlock * Method: nativeGetAttributeStringValue - * Signature: (II)I + * Signature: (JI)Ljava/lang/String; */ -JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeStringValue - (JNIEnv *, jclass, jint, jint); +JNIEXPORT jstring JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeStringValue + (JNIEnv *, jclass, jlong, jint); /* * Class: android_content_res_XmlBlock * Method: nativeGetIdAttribute - * Signature: (I)I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetIdAttribute - (JNIEnv *, jclass, jint); + (JNIEnv *, jclass, jlong); /* * Class: android_content_res_XmlBlock * Method: nativeGetClassAttribute - * Signature: (I)I + * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetClassAttribute - (JNIEnv *, jclass, jint); +JNIEXPORT jstring JNICALL Java_android_content_res_XmlBlock_nativeGetClassAttribute + (JNIEnv *, jclass, jlong); /* * Class: android_content_res_XmlBlock * Method: nativeGetStyleAttribute - * Signature: (I)I + * Signature: (J)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetStyleAttribute - (JNIEnv *, jclass, jint); + (JNIEnv *, jclass, jlong); /* * Class: android_content_res_XmlBlock * Method: nativeGetAttributeIndex - * Signature: (ILjava/lang/String;Ljava/lang/String;)I + * Signature: (JLjava/lang/String;Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_android_content_res_XmlBlock_nativeGetAttributeIndex - (JNIEnv *, jclass, jint, jstring, jstring); + (JNIEnv *, jclass, jlong, jstring, jstring); /* * Class: android_content_res_XmlBlock * Method: nativeDestroyParseState - * Signature: (I)V + * Signature: (J)V */ JNIEXPORT void JNICALL Java_android_content_res_XmlBlock_nativeDestroyParseState - (JNIEnv *, jclass, jint); + (JNIEnv *, jclass, jlong); + +/* + * Class: android_content_res_XmlBlock + * Method: nativeGetPooledString + * Signature: (JI)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_android_content_res_XmlBlock_nativeGetPooledString + (JNIEnv *, jclass, jlong, jint); /* * Class: android_content_res_XmlBlock * Method: nativeDestroy - * Signature: (I)V + * Signature: (J)V */ JNIEXPORT void JNICALL Java_android_content_res_XmlBlock_nativeDestroy - (JNIEnv *, jclass, jint); + (JNIEnv *, jclass, jlong); #ifdef __cplusplus } diff --git a/src/api-impl/android/content/res/AssetManager.java b/src/api-impl/android/content/res/AssetManager.java index bfefcd79..b00735b8 100644 --- a/src/api-impl/android/content/res/AssetManager.java +++ b/src/api-impl/android/content/res/AssetManager.java @@ -466,20 +466,10 @@ public final class AssetManager { */ public final XmlResourceParser openXmlResourceParser(int cookie, String fileName) throws IOException { - /* XmlBlock block = openXmlBlockAsset(cookie, fileName); - XmlResourceParser rp = block.newParser(); - block.close(); - return rp;*/ - - InputStream inStream = ClassLoader.getSystemClassLoader().getResourceAsStream(fileName); - if (inStream == null) { - return null; - } - ResXmlDocument resXmlDocument = new ResXmlDocument(); - resXmlDocument.readBytes(inStream); - ResXmlPullParser xpp = new ResXmlPullParser(); - xpp.setResXmlDocument(resXmlDocument); - return xpp; + XmlBlock block = openXmlBlockAsset(cookie, fileName); + XmlResourceParser rp = block.newParser(); + block.close(); + return rp; } /** @@ -503,7 +493,7 @@ public final class AssetManager { * @param fileName Name of the asset to retrieve. */ /*package*/ final XmlBlock openXmlBlockAsset(int cookie, String fileName) throws IOException { - int xmlBlock; + long xmlBlock; synchronized (this) { if (!mOpen) { throw new RuntimeException("Assetmanager has been closed"); @@ -765,17 +755,21 @@ public final class AssetManager { int defStyleAttr, int defStyleRes, AttributeSet set, int[] inAttrs, int[] outValues, int[] outIndices) { TypedValue value = new TypedValue(); - ResXmlPullParser parser = (ResXmlPullParser)set; + XmlResourceParser parser = (XmlResourceParser)set; if (defStyleRes == 0 && theme != 0 && loadThemeAttributeValue(theme, defStyleAttr, value, true) >= 0) defStyleRes = value.data; if (defStyleRes == 0 && set != null) { - ValueItem valueItem = parser.getAttribute(null, "style"); - if (valueItem != null) { - value.type = valueItem.getType(); - value.data = valueItem.getData(); - if (theme != 0 && (value.type == TypedValue.TYPE_ATTRIBUTE)) - loadThemeAttributeValue(theme, value.data, value, true); - defStyleRes = value.data; + if (parser instanceof ResXmlPullParser) { + ValueItem valueItem = ((ResXmlPullParser)parser).getAttribute(null, "style"); + if (valueItem != null) { + value.type = valueItem.getType(); + value.data = valueItem.getData(); + if (theme != 0 && (value.type == TypedValue.TYPE_ATTRIBUTE)) + loadThemeAttributeValue(theme, value.data, value, true); + defStyleRes = value.data; + } + } else { + defStyleRes = parser.getStyleAttribute(); } } @@ -804,9 +798,14 @@ public final class AssetManager { value.assetCookie = -1; found = true; } else if (xmlCache.containsKey(resId)) { - ValueItem valueItem = parser.getResXmlAttributeAt(xmlCache.get(resId)); - value.type = valueItem.getType(); - value.data = valueItem.getData(); + if (parser instanceof ResXmlPullParser) { + ValueItem valueItem = ((ResXmlPullParser)parser).getResXmlAttributeAt(xmlCache.get(resId)); + value.type = valueItem.getType(); + value.data = valueItem.getData(); + } else { + value.type = XmlBlock.nativeGetAttributeDataType(((XmlBlock.Parser)parser).mParseState, xmlCache.get(resId)); + value.data = XmlBlock.nativeGetAttributeData(((XmlBlock.Parser)parser).mParseState, xmlCache.get(resId)); + } value.resourceId = 0; value.assetCookie = -1; if (value.type != TypedValue.TYPE_ATTRIBUTE) @@ -888,9 +887,7 @@ public final class AssetManager { boolean resolve); /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix); - private /*native*/ final int openXmlAssetNative(int cookie, String fileName) { - return openAsset("../" + fileName, 0); - } + private native final long openXmlAssetNative(int cookie, String fileName); private native final String[] getArrayStringResource(int arrayRes); private native final int[] getArrayStringInfo(int arrayRes); diff --git a/src/api-impl/android/content/res/Resources.java b/src/api-impl/android/content/res/Resources.java index 32a9a63e..aedaead1 100644 --- a/src/api-impl/android/content/res/Resources.java +++ b/src/api-impl/android/content/res/Resources.java @@ -1376,7 +1376,7 @@ public class Resources { // To support generic XML files we will need to manually parse // out the attributes from the XML file (applying type information // contained in the resources and such). - ResXmlPullParser parser = (ResXmlPullParser)set; + XmlResourceParser parser = (XmlResourceParser)set; mAssets.applyStyle(theme, defStyleAttr, defStyleRes, set, attrs, array.mData, array.mIndices); array.mRsrcs = attrs; @@ -1495,7 +1495,7 @@ public class Resources { // To support generic XML files we will need to manually parse // out the attributes from the XML file (applying type information // contained in the resources and such). - ResXmlPullParser parser = (ResXmlPullParser)set; + XmlResourceParser parser = (XmlResourceParser)set; mAssets.applyStyle(0, 0, 0, set, attrs, array.mData, array.mIndices); diff --git a/src/api-impl/android/content/res/TypedArray.java b/src/api-impl/android/content/res/TypedArray.java index 182410a9..b7cf1bf0 100644 --- a/src/api-impl/android/content/res/TypedArray.java +++ b/src/api-impl/android/content/res/TypedArray.java @@ -39,7 +39,7 @@ import java.util.Arrays; */ public class TypedArray { private final Resources mResources; - /*package*/ ResXmlPullParser mXml; + /*package*/ XmlResourceParser mXml; /*package*/ int[] mRsrcs; /*package*/ int[] mData; /*package*/ int[] mIndices; @@ -156,7 +156,12 @@ public class TypedArray { if (type == TypedValue.TYPE_STRING) { final int cookie = data[index + AssetManager.STYLE_ASSET_COOKIE]; if (cookie < 0) { - return mXml.getResXmlDocument().getStringPool().get(data[index + AssetManager.STYLE_DATA]).get(); + if (mXml instanceof ResXmlPullParser) + return ((ResXmlPullParser )mXml).getResXmlDocument().getStringPool().get(data[index + AssetManager.STYLE_DATA]).get(); + else { + Thread.dumpStack(); + System.exit(-1); + } } } return null; @@ -695,9 +700,15 @@ public class TypedArray { final int cookie = data[index + AssetManager.STYLE_ASSET_COOKIE]; if (cookie < 0) { if (mXml != null) { - ResXmlString xmlString = mXml.getResXmlDocument().getStringPool().get(data[index + AssetManager.STYLE_DATA]); - if (xmlString != null) - return xmlString.get(); + if (mXml instanceof ResXmlPullParser) { + ResXmlString xmlString = ((ResXmlPullParser)mXml).getResXmlDocument().getStringPool().get(data[index + AssetManager.STYLE_DATA]); + if (xmlString != null) + return xmlString.get(); + } else { + CharSequence string = ((XmlBlock.Parser)mXml).getPooledString(data[index + AssetManager.STYLE_DATA]); + if (string != null) + return string; + } } if (data[index + AssetManager.STYLE_RESOURCE_ID] != 0) { return mResources.mAssets.getResourceText(data[index + AssetManager.STYLE_RESOURCE_ID]); diff --git a/src/api-impl/android/content/res/XmlBlock.java b/src/api-impl/android/content/res/XmlBlock.java index b26cb1c6..b5375eef 100644 --- a/src/api-impl/android/content/res/XmlBlock.java +++ b/src/api-impl/android/content/res/XmlBlock.java @@ -72,7 +72,7 @@ final class XmlBlock { } /*package*/ final class Parser implements XmlResourceParser { - Parser(int parseState, XmlBlock block) { + Parser(long parseState, XmlBlock block) { mParseState = parseState; mBlock = block; block.mOpenCount++; @@ -168,8 +168,7 @@ final class XmlBlock { return id >= 0 ? mStrings.get(id).toString() : ""; } public String getName() { - int id = nativeGetName(mParseState); - return id >= 0 ? mStrings.get(id).toString() : null; + return nativeGetName(mParseState); } public String getAttributeNamespace(int index) { int id = nativeGetAttributeNamespace(mParseState, index); @@ -200,11 +199,9 @@ final class XmlBlock { return mEventType == START_TAG ? nativeGetAttributeCount(mParseState) : -1; } public String getAttributeValue(int index) { - int id = nativeGetAttributeStringValue(mParseState, index); - if (DEBUG) - System.out.println("getAttributeValue of " + index + " = " + id); - if (id >= 0) - return mStrings.get(id).toString(); + String value = nativeGetAttributeStringValue(mParseState, index); + if (value != null) + return value; // May be some other type... check and try to convert if so. int t = nativeGetAttributeDataType(mParseState, index); @@ -423,8 +420,7 @@ final class XmlBlock { return id >= 0 ? mStrings.get(id).toString() : null; } public String getClassAttribute() { - int id = nativeGetClassAttribute(mParseState); - return id >= 0 ? mStrings.get(id).toString() : null; + return nativeGetClassAttribute(mParseState); } public int getIdAttributeResourceValue(int defaultValue) { @@ -451,10 +447,12 @@ final class XmlBlock { } /*package*/ final CharSequence getPooledString(int id) { - return mStrings.get(id); + if (id < 0) + return null; + return nativeGetPooledString(mParseState, id); } - /*package*/ int mParseState; + /*package*/ long mParseState; private final XmlBlock mBlock; private boolean mStarted = false; private boolean mDecNextDepth = false; @@ -472,14 +470,15 @@ final class XmlBlock { * are doing! The given native object must exist for the entire lifetime * of this newly creating XmlBlock. */ - XmlBlock(AssetManager assets, int xmlBlock) { + XmlBlock(AssetManager assets, long xmlBlock) { mAssets = assets; mNative = xmlBlock; - mStrings = new StringBlock(nativeGetStringBlock(xmlBlock), false); + // mStrings = new StringBlock(nativeGetStringBlock(xmlBlock), false); + mStrings = null; } private final AssetManager mAssets; - private final int mNative; + private final long mNative; /*package*/ final StringBlock mStrings; private boolean mOpen = true; private int mOpenCount = 1; @@ -487,26 +486,27 @@ final class XmlBlock { private static final native int nativeCreate(byte[] data, int offset, int size); - private static final native int nativeGetStringBlock(int obj); + private static final native int nativeGetStringBlock(long obj); - private static final native int nativeCreateParseState(int obj); - /*package*/ static final native int nativeNext(int state); - private static final native int nativeGetNamespace(int state); - /*package*/ static final native int nativeGetName(int state); - private static final native int nativeGetText(int state); - private static final native int nativeGetLineNumber(int state); - private static final native int nativeGetAttributeCount(int state); - private static final native int nativeGetAttributeNamespace(int state, int idx); - private static final native int nativeGetAttributeName(int state, int idx); - private static final native int nativeGetAttributeResource(int state, int idx); - private static final native int nativeGetAttributeDataType(int state, int idx); - private static final native int nativeGetAttributeData(int state, int idx); - private static final native int nativeGetAttributeStringValue(int state, int idx); - private static final native int nativeGetIdAttribute(int state); - private static final native int nativeGetClassAttribute(int state); - private static final native int nativeGetStyleAttribute(int state); - private static final native int nativeGetAttributeIndex(int state, String namespace, String name); - private static final native void nativeDestroyParseState(int state); + private static final native long nativeCreateParseState(long obj); + /*package*/ static final native int nativeNext(long state); + private static final native int nativeGetNamespace(long state); + /*package*/ static final native String nativeGetName(long state); + private static final native int nativeGetText(long state); + private static final native int nativeGetLineNumber(long state); + private static final native int nativeGetAttributeCount(long state); + private static final native int nativeGetAttributeNamespace(long state, int idx); + private static final native int nativeGetAttributeName(long state, int idx); + private static final native int nativeGetAttributeResource(long state, int idx); + static final native int nativeGetAttributeDataType(long state, int idx); + static final native int nativeGetAttributeData(long state, int idx); + private static final native String nativeGetAttributeStringValue(long state, int idx); + private static final native int nativeGetIdAttribute(long state); + private static final native String nativeGetClassAttribute(long state); + private static final native int nativeGetStyleAttribute(long state); + private static final native int nativeGetAttributeIndex(long state, String namespace, String name); + private static final native void nativeDestroyParseState(long state); + private static final native String nativeGetPooledString(long state, int id); - private static final native void nativeDestroy(int obj); + private static final native void nativeDestroy(long obj); }