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 f72ef4ed..0056e58c 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 @@ -33,6 +33,14 @@ extern "C" { #define android_content_res_AssetManager_STYLE_CHANGING_CONFIGURATIONS 4L #undef android_content_res_AssetManager_STYLE_DENSITY #define android_content_res_AssetManager_STYLE_DENSITY 5L +/* + * Class: android_content_res_AssetManager + * Method: list + * Signature: (Ljava/lang/String;)[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_android_content_res_AssetManager_list + (JNIEnv *, jobject, jstring); + /* * Class: android_content_res_AssetManager * Method: addAssetPathNative @@ -65,22 +73,6 @@ JNIEXPORT void JNICALL Java_android_content_res_AssetManager_setLocale JNIEXPORT jobjectArray JNICALL Java_android_content_res_AssetManager_getLocales (JNIEnv *, jobject); -/* - * Class: android_content_res_AssetManager - * Method: setConfiguration - * Signature: (IILjava/lang/String;IIIIIIIIIIIIII)V - */ -JNIEXPORT void JNICALL Java_android_content_res_AssetManager_setConfiguration - (JNIEnv *, jobject, jint, jint, jstring, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint); - -/* - * Class: android_content_res_AssetManager - * Method: getResourceName - * Signature: (I)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_android_content_res_AssetManager_getResourceName - (JNIEnv *, jobject, jint); - /* * Class: android_content_res_AssetManager * Method: getResourcePackageName @@ -89,14 +81,6 @@ JNIEXPORT jstring JNICALL Java_android_content_res_AssetManager_getResourceName JNIEXPORT jstring JNICALL Java_android_content_res_AssetManager_getResourcePackageName (JNIEnv *, jobject, jint); -/* - * Class: android_content_res_AssetManager - * Method: getResourceTypeName - * Signature: (I)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_android_content_res_AssetManager_getResourceTypeName - (JNIEnv *, jobject, jint); - /* * Class: android_content_res_AssetManager * Method: getResourceEntryName @@ -193,14 +177,6 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceValue JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceBagValue (JNIEnv *, jobject, jint, jint, jobject, jboolean); -/* - * Class: android_content_res_AssetManager - * Method: applyStyle - * Signature: (IIII[I[I[I)Z - */ -JNIEXPORT jboolean JNICALL Java_android_content_res_AssetManager_applyStyle - (JNIEnv *, jclass, jint, jint, jint, jint, jintArray, jintArray, jintArray); - /* * Class: android_content_res_AssetManager * Method: retrieveAttributes @@ -281,6 +257,14 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_getGlobalAssetManag JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_newTheme (JNIEnv *, jobject); +/* + * Class: android_content_res_AssetManager + * Method: deleteTheme + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_android_content_res_AssetManager_deleteTheme + (JNIEnv *, jobject, jint); + /* * Class: android_content_res_AssetManager * Method: applyThemeStyle @@ -329,6 +313,14 @@ JNIEXPORT jobjectArray JNICALL Java_android_content_res_AssetManager_getArrayStr JNIEXPORT jintArray JNICALL Java_android_content_res_AssetManager_getArrayStringInfo (JNIEnv *, jobject, jint); +/* + * Class: android_content_res_AssetManager + * Method: destroy + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_android_content_res_AssetManager_destroy + (JNIEnv *, jobject); + #ifdef __cplusplus } #endif diff --git a/src/api-impl/android/content/Context.java b/src/api-impl/android/content/Context.java index 876a9779..b968d6fc 100644 --- a/src/api-impl/android/content/Context.java +++ b/src/api-impl/android/content/Context.java @@ -57,6 +57,7 @@ public class Context extends Object { static Configuration config; static Resources r; static ApplicationInfo application_info; + static Resources.Theme theme; static String apk_path = "/tmp/APK_PATH_SHOULD_HAVE_BEEN_FILLED_IN_BY_CODE_IN_main.c/"; @@ -74,6 +75,7 @@ public class Context extends Object { config = new Configuration(); r = new Resources(assets, dm, config); this_application = new Application(); // TODO: the application context is presumably not identical to the Activity context, what is the difference for us though? + theme = r.newTheme(); application_info = new ApplicationInfo(); InputStream inStream = ClassLoader.getSystemClassLoader().getResourceAsStream("AndroidManifest.xml"); @@ -93,7 +95,7 @@ public class Context extends Object { } public Resources.Theme getTheme() { - return r.newTheme(); + return theme; } public ApplicationInfo getApplicationInfo() { @@ -313,9 +315,20 @@ public class Context extends Object { System.out.println("------------------"); } - // these may not look like typical stubs, but they definitely are stubs - public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { return new TypedArray(r, new int[1000], new int[1000], 0); } - public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { return new TypedArray(r, new int[1000], new int[1000], 0); } - public final TypedArray obtainStyledAttributes(int resid, int[] attrs) { return new TypedArray(r, new int[1000], new int[1000], 0); } - public final TypedArray obtainStyledAttributes(int[] attrs) { return new TypedArray(r, new int[1000], new int[1000], 0); } + public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { + return getTheme().obtainStyledAttributes(set, attrs, 0, 0); + } + public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { + return getTheme().obtainStyledAttributes(set, attrs, defStyleAttr, defStyleRes); + } + public final TypedArray obtainStyledAttributes(int resid, int[] attrs) { + return getTheme().obtainStyledAttributes(resid, attrs); + } + public final TypedArray obtainStyledAttributes(int[] attrs) { + return getTheme().obtainStyledAttributes(attrs); + } + + public void setTheme(int resId) { + theme.applyStyle(resId, true); + } } diff --git a/src/api-impl/android/content/res/AssetManager.java b/src/api-impl/android/content/res/AssetManager.java index 01171f91..4c2187c1 100644 --- a/src/api-impl/android/content/res/AssetManager.java +++ b/src/api-impl/android/content/res/AssetManager.java @@ -19,16 +19,22 @@ package android.content.res; import android.content.Context; import android.os.ParcelFileDescriptor; import android.os.Trace; +import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; +import com.reandroid.arsc.array.ResValueMapArray; import com.reandroid.arsc.chunk.PackageBlock; import com.reandroid.arsc.chunk.TableBlock; import com.reandroid.arsc.chunk.xml.ResXmlDocument; import com.reandroid.arsc.chunk.xml.ResXmlPullParser; import com.reandroid.arsc.group.EntryGroup; +import com.reandroid.arsc.item.StringItem; +import com.reandroid.arsc.value.Entry; +import com.reandroid.arsc.value.EntryHeaderMap; import com.reandroid.arsc.value.ResValue; import com.reandroid.arsc.value.ResValueMap; +import com.reandroid.arsc.value.ValueItem; import com.reandroid.arsc.value.ValueType; import java.io.FileDescriptor; import java.io.FileNotFoundException; @@ -42,6 +48,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; +import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.xmlpull.v1.XmlPullParser; @@ -244,6 +251,7 @@ public final class AssetManager { ResValue resValue = entryGroup.pickOne().getResValue(); if (resValue == null) return false; // not found + outValue.resourceId = ident; outValue.type = resValue.getType(); outValue.data = resValue.getData(); if (outValue.type == TypedValue.TYPE_STRING) @@ -257,36 +265,63 @@ public final class AssetManager { * @param id Resource id of the string array */ /*package*/ final CharSequence[] getResourceTextArray(final int id) { - int[] rawInfoArray = getArrayStringInfo(id); - int rawInfoArrayLen = rawInfoArray.length; - final int infoArrayLen = rawInfoArrayLen / 2; - int block; - int index; - CharSequence[] retArray = new CharSequence[infoArrayLen]; - for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) { - block = rawInfoArray[i]; - index = rawInfoArray[i + 1]; - retArray[j] = index >= 0 ? mStringBlocks[block].get(index) : null; + ResValueMap children[] = tableBlock.search(id).pickOne().getResValueMapArray().getChildes(); + CharSequence values[] = new CharSequence[children.length]; + for (int i = 0; i < children.length; i++) { + StringItem stringItem = children[i].getDataAsPoolString(); + values[i] = (stringItem != null) ? stringItem.get() : ""; } - return retArray; + return values; + } + + public Map loadStyle(int resId) { + Map map = new HashMap<>(); + EntryGroup entryGroup = tableBlock.search(resId); + while (entryGroup != null) { + Entry entry = entryGroup.pickOne(); + ResValueMapArray array = entry.getResValueMapArray(); + for (int i = 0; i < array.childesCount(); i++) { + map.putIfAbsent(array.get(i).getName(), array.get(i)); + } + int parent_id = ((EntryHeaderMap)entry.getHeader()).getParentId(); + entryGroup = tableBlock.search(parent_id); + } + return map; } /*package*/ final boolean getThemeValue(int theme, int ident, TypedValue outValue, boolean resolveRefs) { - int block = loadThemeAttributeValue(theme, ident, outValue, resolveRefs); - if (block >= 0) { - if (outValue.type != TypedValue.TYPE_STRING) { - return true; + Map style = loadStyle(theme); + EntryGroup entryGroup = tableBlock.search(ident); + if (entryGroup == null) + return false; + Entry entry = entryGroup.pickOne(); + ValueItem valueItem = null; + while ("attr".equals(entry.getTypeName())) { + valueItem = null; + if (style.containsKey(ident)) + valueItem = style.get(ident); + if (valueItem != null && valueItem.getValueType() == ValueType.ATTRIBUTE) { + ident = valueItem.getData(); + entryGroup = tableBlock.search(ident); + if (entryGroup == null) { + break; + } + entry = entryGroup.pickOne(); + } else { + break; } - StringBlock[] blocks = mStringBlocks; - if (blocks == null) { - ensureStringBlocks(); - blocks = mStringBlocks; - } - outValue.string = blocks[block].get(outValue.data); - return true; } - return false; + if (valueItem == null) + return false; + outValue.resourceId = 0; + outValue.type = valueItem.getType(); + outValue.data = valueItem.getData(); + outValue.assetCookie = -1; + if (outValue.type == TypedValue.TYPE_STRING) { + outValue.string = valueItem.getDataAsPoolString().get(); + } + return true; } /*package*/ final void ensureStringBlocks() { @@ -318,7 +353,7 @@ public final class AssetManager { // System.out.println("Get pooled: block=" + block // + ", id=#" + Integer.toHexString(id) // + ", blocks=" + mStringBlocks); - return mStringBlocks[block - 1].get(id); + return tableBlock.getStringPool().get(id).get(); } /** @@ -584,7 +619,7 @@ public final class AssetManager { /*package*/ final void releaseTheme(int theme) { synchronized (this) { - deleteTheme(theme); + // deleteTheme(theme); decRefsLocked(theme); } } @@ -748,11 +783,11 @@ public final class AssetManager { * applications. * {@hide} */ - public native final void setConfiguration(int mcc, int mnc, String locale, + public /*native*/ final void setConfiguration(int mcc, int mnc, String locale, int orientation, int touchscreen, int density, int keyboard, int keyboardHidden, int navigation, int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, - int screenLayout, int uiMode, int majorVersion); + int screenLayout, int uiMode, int majorVersion) {} /** * Retrieve the resource identifier for the given resource name. @@ -769,9 +804,13 @@ public final class AssetManager { return -1; } - /*package*/ native final String getResourceName(int resid); + /*package*/ /*native*/ final String getResourceName(int resid) { + return tableBlock.search(resid).pickOne().getName(); + } /*package*/ native final String getResourcePackageName(int resid); - /*package*/ native final String getResourceTypeName(int resid); + /*package*/ /*native*/ final String getResourceTypeName(int resid) { + return tableBlock.search(resid).pickOne().getTypeName(); + } /*package*/ native final String getResourceEntryName(int resid); private native final int openAsset(String fileName, int accessMode); @@ -808,9 +847,82 @@ public final class AssetManager { /*package*/ static final int STYLE_RESOURCE_ID = 3; /*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4; /*package*/ static final int STYLE_DENSITY = 5; - /*package*/ native static final boolean applyStyle(int theme, - int defStyleAttr, int defStyleRes, int xmlParser, - int[] inAttrs, int[] outValues, int[] outIndices); + /*package*/ /*native*/ final boolean applyStyle(Map theme, + int defStyleAttr, int defStyleRes, AttributeSet set, + int[] inAttrs, int[] outValues, int[] outIndices) { + if (defStyleRes == 0 && theme.containsKey(defStyleAttr)) + defStyleRes = theme.get(defStyleAttr).getData(); + Map defStyle = loadStyle(defStyleRes); + + ResXmlPullParser parser = (ResXmlPullParser)set; + + for (int i = 0; i < inAttrs.length; i++) { + int d = i*AssetManager.STYLE_NUM_ENTRIES; + // reset values in case of cached array + outValues[d+AssetManager.STYLE_RESOURCE_ID] = 0; + outValues[d+AssetManager.STYLE_TYPE] = 0; + outValues[d+AssetManager.STYLE_DATA] = 0; + outValues[d+AssetManager.STYLE_ASSET_COOKIE] = 0; + int resId = inAttrs[i]; + EntryGroup entryGroup = tableBlock.search(resId); + if (entryGroup == null) + continue; + Entry entry = entryGroup.pickOne(); + ValueItem valueItem = null; + while ("attr".equals(entry.getTypeName())) { + valueItem = null; + if (set != null) { + for (int j=0; j themeMap = new HashMap<>(); /** * Place new attribute values into the theme. The style resource * specified by resid will be retrieved from this Theme's @@ -1205,7 +1211,7 @@ public class Resources { * if not already defined in the theme. */ public void applyStyle(int resid, boolean force) { - AssetManager.applyThemeStyle(mTheme, resid, force); + themeMap = mAssets.loadStyle(resid); } /** @@ -1218,7 +1224,7 @@ public class Resources { * @param other The existing Theme to copy from. */ public void setTo(Theme other) { - AssetManager.copyTheme(mTheme, other.mTheme); + themeMap = other.themeMap; } /** @@ -1244,8 +1250,7 @@ public class Resources { int len = attrs.length; TypedArray array = getCachedStyledAttributes(len); array.mRsrcs = attrs; - /* AssetManager.applyStyle(mTheme, 0, 0, 0, attrs, - array.mData, array.mIndices);*/ + mAssets.applyStyle(themeMap, 0, 0, null, attrs, array.mData, array.mIndices); return array; } @@ -1274,35 +1279,34 @@ public class Resources { int len = attrs.length; TypedArray array = getCachedStyledAttributes(len); array.mRsrcs = attrs; - /* - AssetManager.applyStyle(mTheme, 0, resid, 0, attrs, - array.mData, array.mIndices); - if (false) { - int[] data = array.mData; + mAssets.applyStyle(themeMap, 0, resid, null, attrs, + array.mData, array.mIndices); + if (false) { + int[] data = array.mData; - System.out.println("**********************************************************"); - System.out.println("**********************************************************"); - System.out.println("**********************************************************"); - System.out.println("Attributes:"); - String s = " Attrs:"; - int i; - for (i=0; i