diff options
| -rw-r--r-- | core/java/android/content/res/AssetManager.java | 9 | ||||
| -rwxr-xr-x | core/java/android/content/res/Resources.java | 69 | ||||
| -rw-r--r-- | core/jni/android_util_AssetManager.cpp | 5 | ||||
| -rw-r--r-- | include/utils/ResourceTypes.h | 8 | ||||
| -rw-r--r-- | libs/utils/ResourceTypes.cpp | 44 |
5 files changed, 115 insertions, 20 deletions
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index 73d9458fbec3..e279f64fb7bc 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -149,7 +149,7 @@ public final class AssetManager { /*package*/ final CharSequence getResourceText(int ident) { synchronized (this) { TypedValue tmpValue = mValue; - int block = loadResourceValue(ident, tmpValue, true); + int block = loadResourceValue(ident, (short) 0, tmpValue, true); if (block >= 0) { if (tmpValue.type == TypedValue.TYPE_STRING) { return mStringBlocks[block].get(tmpValue.data); @@ -190,10 +190,11 @@ public final class AssetManager { /*package*/ final boolean getResourceValue(int ident, + int density, TypedValue outValue, boolean resolveRefs) { - int block = loadResourceValue(ident, outValue, resolveRefs); + int block = loadResourceValue(ident, (short) density, outValue, resolveRefs); if (block >= 0) { if (outValue.type != TypedValue.TYPE_STRING) { return true; @@ -681,8 +682,8 @@ public final class AssetManager { /** Returns true if the resource was found, filling in mRetStringBlock and * mRetData. */ - private native final int loadResourceValue(int ident, TypedValue outValue, - boolean resolve); + private native final int loadResourceValue(int ident, short density, TypedValue outValue, + boolean resolve); /** Returns true if the resource was found, filling in mRetStringBlock and * mRetData. */ private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue, diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 9b23c1ea8965..e6fd039c839f 100755 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -628,6 +628,50 @@ public class Resources { } /** + * Return a drawable object associated with a particular resource ID for the + * given screen density in DPI. This will set the drawable's density to be + * the device's density multiplied by the ratio of actual drawable density + * to requested density. This allows the drawable to be scaled up to the + * correct size if needed. Various types of objects will be returned + * depending on the underlying resource -- for example, a solid color, PNG + * image, scalable image, etc. The Drawable API hides these implementation + * details. + * + * @param id The desired resource identifier, as generated by the aapt tool. + * This integer encodes the package, type, and resource entry. + * The value 0 is an invalid identifier. + * @param density the desired screen density indicated by the resource as + * found in {@link DisplayMetrics}. + * @throws NotFoundException Throws NotFoundException if the given ID does + * not exist. + * @return Drawable An object that can be used to draw this resource. + * @hide + */ + public Drawable getDrawableForDensity(int id, int density) throws NotFoundException { + synchronized (mTmpValue) { + TypedValue value = mTmpValue; + getValueForDensity(id, density, value, true); + + /* + * Pretend the requested density is actually the display density. If + * the drawable returned is not the requested density, then force it + * to be scaled later by dividing its density by the ratio of + * requested density to actual device density. Drawables that have + * undefined density or no density don't need to be handled here. + */ + if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) { + if (value.density == density) { + value.density = DisplayMetrics.DENSITY_DEVICE; + } else { + value.density = (value.density * DisplayMetrics.DENSITY_DEVICE) / density; + } + } + + return loadDrawable(value, id); + } + } + + /** * Return a movie object associated with the particular resource ID. * @param id The desired resource identifier, as generated by the aapt * tool. This integer encodes the package, type, and resource @@ -930,7 +974,7 @@ public class Resources { */ public void getValue(int id, TypedValue outValue, boolean resolveRefs) throws NotFoundException { - boolean found = mAssets.getResourceValue(id, outValue, resolveRefs); + boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs); if (found) { return; } @@ -939,6 +983,29 @@ public class Resources { } /** + * Get the raw value associated with a resource with associated density. + * + * @param id resource identifier + * @param density density in DPI + * @param resolveRefs If true, a resource that is a reference to another + * resource will be followed so that you receive the actual final + * resource data. If false, the TypedValue will be filled in with + * the reference itself. + * @throws NotFoundException Throws NotFoundException if the given ID does + * not exist. + * @see #getValue(String, TypedValue, boolean) + * @hide + */ + public void getValueForDensity(int id, int density, TypedValue outValue, boolean resolveRefs) + throws NotFoundException { + boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs); + if (found) { + return; + } + throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)); + } + + /** * Return the raw data associated with a particular resource ID. * See getIdentifier() for information on how names are mapped to resource * IDs, and getString(int) for information on how string resources are diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index f3b935733b28..c4056a44ee79 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -701,6 +701,7 @@ static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jo static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz, jint ident, + jshort density, jobject outValue, jboolean resolve) { @@ -713,7 +714,7 @@ static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject Res_value value; ResTable_config config; uint32_t typeSpecFlags; - ssize_t block = res.getResource(ident, &value, false, &typeSpecFlags, &config); + ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config); #if THROW_ON_BAD_ID if (block == BAD_INDEX) { jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!"); @@ -1703,7 +1704,7 @@ static JNINativeMethod gAssetManagerMethods[] = { (void*) android_content_AssetManager_getResourceTypeName }, { "getResourceEntryName","(I)Ljava/lang/String;", (void*) android_content_AssetManager_getResourceEntryName }, - { "loadResourceValue","(ILandroid/util/TypedValue;Z)I", + { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I", (void*) android_content_AssetManager_loadResourceValue }, { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I", (void*) android_content_AssetManager_loadResourceBagValue }, diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h index da86da41006d..ed7f53d17128 100644 --- a/include/utils/ResourceTypes.h +++ b/include/utils/ResourceTypes.h @@ -1771,12 +1771,14 @@ public: * * @return ssize_t Either a >= 0 table index or a negative error code. */ - ssize_t getResource(uint32_t resID, Res_value* outValue, bool mayBeBag=false, - uint32_t* outSpecFlags=NULL, ResTable_config* outConfig=NULL) const; + ssize_t getResource(uint32_t resID, Res_value* outValue, bool mayBeBag = false, + uint16_t density = 0, + uint32_t* outSpecFlags = NULL, + ResTable_config* outConfig = NULL) const; inline ssize_t getResource(const ResTable_ref& res, Res_value* outValue, uint32_t* outSpecFlags=NULL) const { - return getResource(res.ident, outValue, false, outSpecFlags, NULL); + return getResource(res.ident, outValue, false, 0, outSpecFlags, NULL); } ssize_t resolveReference(Res_value* inOutValue, diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 91e7df3ef5b7..03d2e217a7fa 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -1896,7 +1896,7 @@ bool ResTable::getResourceName(uint32_t resID, resource_name* outName) const return false; } -ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag, +ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag, uint16_t density, uint32_t* outSpecFlags, ResTable_config* outConfig) const { if (mError != NO_ERROR) { @@ -1926,7 +1926,7 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag memset(&bestItem, 0, sizeof(bestItem)); // make the compiler shut up if (outSpecFlags != NULL) *outSpecFlags = 0; - + // Look through all resource packages, starting with the most // recently added. const PackageGroup* const grp = mPackageGroups[p]; @@ -1934,6 +1934,22 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag LOGW("Bad identifier when getting value for resource number 0x%08x", resID); return BAD_INDEX; } + + // Allow overriding density + const ResTable_config* desiredConfig = &mParams; + ResTable_config* overrideConfig = NULL; + if (density > 0) { + overrideConfig = (ResTable_config*) malloc(sizeof(ResTable_config)); + if (overrideConfig == NULL) { + LOGE("Couldn't malloc ResTable_config for overrides: %s", strerror(errno)); + return BAD_INDEX; + } + memcpy(overrideConfig, &mParams, sizeof(ResTable_config)); + overrideConfig->density = density; + desiredConfig = overrideConfig; + } + + ssize_t rc = BAD_INDEX; size_t ip = grp->packages.size(); while (ip > 0) { ip--; @@ -1943,12 +1959,13 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag const ResTable_type* type; const ResTable_entry* entry; const Type* typeClass; - ssize_t offset = getEntry(package, t, e, &mParams, &type, &entry, &typeClass); + ssize_t offset = getEntry(package, t, e, desiredConfig, &type, &entry, &typeClass); if (offset <= 0) { if (offset < 0) { LOGW("Failure getting entry for 0x%08x (t=%d e=%d) in package %zd (error %d)\n", resID, t, e, ip, (int)offset); - return offset; + rc = offset; + goto out; } continue; } @@ -1963,13 +1980,14 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag TABLE_NOISY(aout << "Resource type data: " << HexDump(type, dtohl(type->header.size)) << endl); - + if ((size_t)offset > (dtohl(type->header.size)-sizeof(Res_value))) { LOGW("ResTable_item at %d is beyond type chunk data %d", (int)offset, dtohl(type->header.size)); - return BAD_TYPE; + rc = BAD_TYPE; + goto out; } - + const Res_value* item = (const Res_value*)(((const uint8_t*)type) + offset); ResTable_config thisConfig; @@ -2011,10 +2029,16 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag outValue->data, &len)).string() : "", outValue->data)); - return bestPackage->header->index; + rc = bestPackage->header->index; + goto out; + } + +out: + if (overrideConfig != NULL) { + free(overrideConfig); } - return BAD_VALUE; + return rc; } ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex, @@ -2027,7 +2051,7 @@ ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex, if (outLastRef) *outLastRef = value->data; uint32_t lastRef = value->data; uint32_t newFlags = 0; - const ssize_t newIndex = getResource(value->data, value, true, &newFlags, + const ssize_t newIndex = getResource(value->data, value, true, 0, &newFlags, outConfig); if (newIndex == BAD_INDEX) { return BAD_INDEX; |