diff options
author | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2012-11-20 21:17:17 +0000 |
---|---|---|
committer | Ricardo Cerqueira <cyanogenmod@cerqueira.org> | 2012-11-24 14:09:39 +0000 |
commit | ad3c9416092f09213d32eee8b59287766eae5d19 (patch) | |
tree | 0bc1e318ca15560299c662e37c6c4fedf0bcf1e6 /libs | |
parent | 7d114fb838017d86ece76e18a7e1b0d8534595fa (diff) | |
download | frameworks_base-ad3c9416092f09213d32eee8b59287766eae5d19.zip frameworks_base-ad3c9416092f09213d32eee8b59287766eae5d19.tar.gz frameworks_base-ad3c9416092f09213d32eee8b59287766eae5d19.tar.bz2 |
Squashed commit of the theme engine support.
Updated 4.2 support for the old T-Mobile theme engine, as usual
needs the provider and switcher apps installed as well.
I'm finally dropping the 400+ commit history on this, since everybody
else keeps picking it up from CM as a single patch anyway... But
for the record, nothing of this would be possible without Josh, Ed,
and the rest of the TMo guys who wrote and maintained it until 2.2:
amit chabra <amit.chabra@t-mobile.com>
Amit Kohli <amit.kohli@t-mobile.com>
Chris Cogar <chriscogar@t-mobile.com>
Dirk Sigurdson <dirk.sigurdson@t-mobile.com>
Ed Carrigan <edward.carrigan@t-mobile.com>
Gaurav Sharma <gaurav.sharma3@t-mobile.com>
Hui Feng <hui.feng@t-mobile.com>
John Ritz <john.ritz1@t-mobile.com>
Josh Guilfoyle <josh.guilfoyle@t-mobile.com>
Mark Roberts <mark.roberts48@t-mobile.com>
Pankaj Kumar <Pankaj.kumar6@t-mobile.com>
Samuel Cheung <samuel.cheung@t-mobile.com>
Sergey Ten <sergey.ten6@t-mobile.com>
Change-Id: I7148d51be48f28a2dc4bdf9ec9018f04b268ffc4
Diffstat (limited to 'libs')
-rw-r--r-- | libs/androidfw/Android.mk | 3 | ||||
-rw-r--r-- | libs/androidfw/AssetManager.cpp | 211 | ||||
-rw-r--r-- | libs/androidfw/PackageRedirectionMap.cpp | 203 | ||||
-rw-r--r-- | libs/androidfw/ResourceTypes.cpp | 116 |
4 files changed, 458 insertions, 75 deletions
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk index 3ed75a2..7e53000 100644 --- a/libs/androidfw/Android.mk +++ b/libs/androidfw/Android.mk @@ -22,8 +22,11 @@ commonUtilsSources:= \ Asset.cpp \ AssetDir.cpp \ AssetManager.cpp \ + PackageRedirectionMap.cpp \ ObbFile.cpp \ ResourceTypes.cpp \ + ../../tools/aapt/ZipFile.cpp \ + ../../tools/aapt/ZipEntry.cpp \ StreamingZipInflater.cpp # formerly in libui diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp index 8bd805c..806e716 100644 --- a/libs/androidfw/AssetManager.cpp +++ b/libs/androidfw/AssetManager.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2006 The Android Open Source Project + * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -152,7 +153,7 @@ AssetManager::~AssetManager(void) delete[] mVendor; } -bool AssetManager::addAssetPath(const String8& path, void** cookie) +bool AssetManager::addAssetPath(const String8& path, void** cookie, bool asSkin) { AutoMutex _l(mLock); @@ -162,6 +163,7 @@ bool AssetManager::addAssetPath(const String8& path, void** cookie) if (kAppZipName) { realPath.appendPath(kAppZipName); } + ap.asSkin = asSkin; ap.type = ::getFileType(realPath.string()); if (ap.type == kFileTypeRegular) { ap.path = realPath; @@ -516,9 +518,13 @@ Asset* AssetManager::open(const char* fileName, AccessMode mode) size_t i = mAssetPaths.size(); while (i > 0) { i--; + const asset_path& ap = mAssetPaths.itemAt(i); + if (ap.asSkin) { + continue; + } ALOGV("Looking for asset '%s' in '%s'\n", - assetName.string(), mAssetPaths.itemAt(i).path.string()); - Asset* pAsset = openNonAssetInPathLocked(assetName.string(), mode, mAssetPaths.itemAt(i)); + assetName.string(), ap.path.string()); + Asset* pAsset = openNonAssetInPathLocked(assetName.string(), mode, ap); if (pAsset != NULL) { return pAsset != kExcludedAsset ? pAsset : NULL; } @@ -550,9 +556,13 @@ Asset* AssetManager::openNonAsset(const char* fileName, AccessMode mode) size_t i = mAssetPaths.size(); while (i > 0) { i--; - ALOGV("Looking for non-asset '%s' in '%s'\n", fileName, mAssetPaths.itemAt(i).path.string()); + const asset_path& ap = mAssetPaths.itemAt(i); + if (ap.asSkin) { + continue; + } + ALOGV("Looking for non-asset '%s' in '%s'\n", fileName, ap.path.string()); Asset* pAsset = openNonAssetInPathLocked( - fileName, mode, mAssetPaths.itemAt(i)); + fileName, mode, ap); if (pAsset != NULL) { return pAsset != kExcludedAsset ? pAsset : NULL; } @@ -631,76 +641,13 @@ const ResTable* AssetManager::getResTable(bool required) const if (mCacheMode != CACHE_OFF && !mCacheValid) const_cast<AssetManager*>(this)->loadFileNameCacheLocked(); + mResources = rt = new ResTable(); - const size_t N = mAssetPaths.size(); - for (size_t i=0; i<N; i++) { - Asset* ass = NULL; - ResTable* sharedRes = NULL; - bool shared = true; - const asset_path& ap = mAssetPaths.itemAt(i); - Asset* idmap = openIdmapLocked(ap); - ALOGV("Looking for resource asset in '%s'\n", ap.path.string()); - if (ap.type != kFileTypeDirectory) { - if (i == 0) { - // The first item is typically the framework resources, - // which we want to avoid parsing every time. - sharedRes = const_cast<AssetManager*>(this)-> - mZipSet.getZipResourceTable(ap.path); - } - if (sharedRes == NULL) { - ass = const_cast<AssetManager*>(this)-> - mZipSet.getZipResourceTableAsset(ap.path); - if (ass == NULL) { - ALOGV("loading resource table %s\n", ap.path.string()); - ass = const_cast<AssetManager*>(this)-> - openNonAssetInPathLocked("resources.arsc", - Asset::ACCESS_BUFFER, - ap); - if (ass != NULL && ass != kExcludedAsset) { - ass = const_cast<AssetManager*>(this)-> - mZipSet.setZipResourceTableAsset(ap.path, ass); - } - } - - if (i == 0 && ass != NULL) { - // If this is the first resource table in the asset - // manager, then we are going to cache it so that we - // can quickly copy it out for others. - ALOGV("Creating shared resources for %s", ap.path.string()); - sharedRes = new ResTable(); - sharedRes->add(ass, (void*)(i+1), false, idmap); - sharedRes = const_cast<AssetManager*>(this)-> - mZipSet.setZipResourceTable(ap.path, sharedRes); - } - } - } else { - ALOGV("loading resource table %s\n", ap.path.string()); - Asset* ass = const_cast<AssetManager*>(this)-> - openNonAssetInPathLocked("resources.arsc", - Asset::ACCESS_BUFFER, - ap); - shared = false; - } - if ((ass != NULL || sharedRes != NULL) && ass != kExcludedAsset) { - if (rt == NULL) { - mResources = rt = new ResTable(); - updateResourceParamsLocked(); - } - ALOGV("Installing resource asset %p in to table %p\n", ass, mResources); - if (sharedRes != NULL) { - ALOGV("Copying existing resources for %s", ap.path.string()); - rt->add(sharedRes); - } else { - ALOGV("Parsing resources for %s", ap.path.string()); - rt->add(ass, (void*)(i+1), !shared, idmap); - } - - if (!shared) { - delete ass; - } - } - if (idmap != NULL) { - delete idmap; + if (rt) { + const size_t N = mAssetPaths.size(); + for (size_t i=0; i<N; i++) { + const asset_path& ap = mAssetPaths.itemAt(i); + updateResTableFromAssetPath(rt, ap, (void*)(i+1)); } } @@ -708,9 +655,73 @@ const ResTable* AssetManager::getResTable(bool required) const if (!rt) { mResources = rt = new ResTable(); } + return rt; } +void AssetManager::updateResTableFromAssetPath(ResTable *rt, const asset_path& ap, void *cookie) const +{ + Asset* ass = NULL; + ResTable* sharedRes = NULL; + bool shared = true; + size_t cookiePos = (size_t)cookie; + ALOGV("Looking for resource asset in '%s'\n", ap.path.string()); + if (ap.type != kFileTypeDirectory) { + if (cookiePos == 1) { + // The first item is typically the framework resources, + // which we want to avoid parsing every time. + sharedRes = const_cast<AssetManager*>(this)-> + mZipSet.getZipResourceTable(ap.path); + } + if (sharedRes == NULL) { + ass = const_cast<AssetManager*>(this)-> + mZipSet.getZipResourceTableAsset(ap.path); + if (ass == NULL) { + ALOGV("loading resource table %s\n", ap.path.string()); + ass = const_cast<AssetManager*>(this)-> + openNonAssetInPathLocked("resources.arsc", + Asset::ACCESS_BUFFER, + ap); + if (ass != NULL && ass != kExcludedAsset) { + ass = const_cast<AssetManager*>(this)-> + mZipSet.setZipResourceTableAsset(ap.path, ass); + } + } + if (cookiePos == 0 && ass != NULL) { + // If this is the first resource table in the asset + // manager, then we are going to cache it so that we + // can quickly copy it out for others. + ALOGV("Creating shared resources for %s", ap.path.string()); + sharedRes = new ResTable(); + sharedRes->add(ass, cookie, false); + sharedRes = const_cast<AssetManager*>(this)-> + mZipSet.setZipResourceTable(ap.path, sharedRes); + } + } + } else { + ALOGV("loading resource table %s\n", ap.path.string()); + Asset* ass = const_cast<AssetManager*>(this)-> + openNonAssetInPathLocked("resources.arsc", + Asset::ACCESS_BUFFER, + ap); + shared = false; + } + if ((ass != NULL || sharedRes != NULL) && ass != kExcludedAsset) { + updateResourceParamsLocked(); + ALOGV("Installing resource asset %p in to table %p\n", ass, mResources); + if (sharedRes != NULL) { + ALOGV("Copying existing resources for %s", ap.path.string()); + rt->add(sharedRes); + } else { + ALOGV("Parsing resources for %s", ap.path.string()); + rt->add(ass, cookie, !shared); + } + if (!shared) { + delete ass; + } + } +} + void AssetManager::updateResourceParamsLocked() const { ResTable* res = mResources; @@ -1163,6 +1174,9 @@ AssetDir* AssetManager::openDir(const char* dirName) while (i > 0) { i--; const asset_path& ap = mAssetPaths.itemAt(i); + if (ap.asSkin) { + continue; + } if (ap.type == kFileTypeRegular) { ALOGV("Adding directory %s from zip %s", dirName, ap.path.string()); scanAndMergeZipLocked(pMergedInfo, ap, kAssetsRoot, dirName); @@ -2017,3 +2031,52 @@ int AssetManager::ZipSet::getIndex(const String8& zip) const return mZipPath.size()-1; } + +bool AssetManager::attachThemePath(const String8& path, void** cookie) +{ + bool res = addAssetPath(path, cookie, true); + ResTable* rt = mResources; + if (res && rt != NULL && ((size_t)*cookie == mAssetPaths.size())) { + AutoMutex _l(mLock); + const asset_path& ap = mAssetPaths.itemAt((size_t)*cookie - 1); + updateResTableFromAssetPath(rt, ap, *cookie); + } + return res; +} + +bool AssetManager::detachThemePath(const String8 &packageName, void* cookie) +{ + AutoMutex _l(mLock); + + const size_t which = ((size_t)cookie)-1; + if (which >= mAssetPaths.size()) { + return false; + } + + /* TODO: Ensure that this cookie is added with asSkin == true. */ + mAssetPaths.removeAt(which); + + ResTable* rt = mResources; + if (rt == NULL) { + ALOGV("ResTable must not be NULL"); + return false; + } + + rt->removeAssetsByCookie(packageName, (void *)cookie); + + return true; +} + +void AssetManager::addRedirections(PackageRedirectionMap* resMap) +{ + getResources(); + ResTable* rt = mResources; + rt->addRedirections(resMap); +} + +void AssetManager::clearRedirections() +{ + getResources(); + ResTable* rt = mResources; + rt->clearRedirections(); +} diff --git a/libs/androidfw/PackageRedirectionMap.cpp b/libs/androidfw/PackageRedirectionMap.cpp new file mode 100644 index 0000000..92cf312 --- /dev/null +++ b/libs/androidfw/PackageRedirectionMap.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// Provide access to read-only assets. +// + +#define LOG_TAG "packageresmap" + +#include <androidfw/PackageRedirectionMap.h> +#include <androidfw/ResourceTypes.h> +#include <utils/misc.h> + +using namespace android; + +PackageRedirectionMap::PackageRedirectionMap() + : mPackage(-1), mEntriesByType(NULL) +{ +} + +static void clearEntriesByType(uint32_t** entriesByType) +{ + SharedBuffer* buf = SharedBuffer::bufferFromData(entriesByType); + const size_t N = buf->size() / sizeof(entriesByType[0]); + for (size_t i = 0; i < N; i++) { + uint32_t* entries = entriesByType[i]; + if (entries != NULL) { + SharedBuffer::bufferFromData(entries)->release(); + } + } + buf->release(); +} + +PackageRedirectionMap::~PackageRedirectionMap() +{ + if (mEntriesByType != NULL) { + clearEntriesByType(mEntriesByType); + } +} + +unsigned int roundUpPower2(unsigned int val) +{ + val--; + val |= val >> 1; + val |= val >> 2; + val |= val >> 4; + val |= val >> 8; + val |= val >> 16; + val++; + + return val; +} +static void* ensureCapacity(void* data, size_t nmemb, size_t size) +{ + SharedBuffer* buf; + size_t currentSize; + + if (data != NULL) { + buf = SharedBuffer::bufferFromData(data); + currentSize = buf->size(); + } else { + buf = NULL; + currentSize = 0; + } + + size_t minSize = nmemb * size; + if (minSize > currentSize) { + unsigned int requestSize = roundUpPower2(minSize); + if (buf == NULL) { + buf = SharedBuffer::alloc(requestSize); + } else { + buf = buf->editResize(requestSize); + } + memset((unsigned char*)buf->data()+currentSize, 0, requestSize - currentSize); + } + + return buf->data(); +} + +bool PackageRedirectionMap::addRedirection(uint32_t fromIdent, uint32_t toIdent) +{ + const int package = Res_GETPACKAGE(fromIdent); + const int type = Res_GETTYPE(fromIdent); + const int entry = Res_GETENTRY(fromIdent); + + // The first time we add a redirection we can infer the package for all + // future redirections. + if (mPackage == -1) { + mPackage = package+1; + } else if (mPackage != (package+1)) { + ALOGW("cannot add redirection for conflicting package 0x%02x (expecting package 0x%02x)\n", package+1, mPackage); + return false; + } + + mEntriesByType = (uint32_t**)ensureCapacity(mEntriesByType, type + 1, sizeof(uint32_t*)); + uint32_t* entries = mEntriesByType[type]; + entries = (uint32_t*)ensureCapacity(entries, entry + 1, sizeof(uint32_t)); + entries[entry] = toIdent; + mEntriesByType[type] = entries; + + return true; +} + +uint32_t PackageRedirectionMap::lookupRedirection(uint32_t fromIdent) +{ + if (mPackage == -1 || mEntriesByType == NULL || fromIdent == 0) { + return 0; + } + + const int package = Res_GETPACKAGE(fromIdent); + const int type = Res_GETTYPE(fromIdent); + const int entry = Res_GETENTRY(fromIdent); + + if (package+1 != mPackage) { + return 0; + } + + size_t nTypes = getNumberOfTypes(); + if (type < 0 || type >= nTypes) { + return 0; + } + uint32_t* entries = mEntriesByType[type]; + if (entries == NULL) { + return 0; + } + size_t nEntries = getNumberOfEntries(type); + if (entry < 0 || entry >= nEntries) { + return 0; + } + return entries[entry]; +} + +int PackageRedirectionMap::getPackage() +{ + return mPackage; +} + +size_t PackageRedirectionMap::getNumberOfTypes() +{ + if (mEntriesByType == NULL) { + return 0; + } else { + return SharedBuffer::bufferFromData(mEntriesByType)->size() / + sizeof(mEntriesByType[0]); + } +} + +size_t PackageRedirectionMap::getNumberOfUsedTypes() +{ + uint32_t** entriesByType = mEntriesByType; + size_t N = getNumberOfTypes(); + size_t count = 0; + for (size_t i=0; i<N; i++) { + if (entriesByType[i] != NULL) { + count++; + } + } + return count; +} + +size_t PackageRedirectionMap::getNumberOfEntries(int type) +{ + uint32_t* entries = mEntriesByType[type]; + if (entries == NULL) { + return 0; + } else { + return SharedBuffer::bufferFromData(entries)->size() / + sizeof(entries[0]); + } +} + +size_t PackageRedirectionMap::getNumberOfUsedEntries(int type) +{ + size_t N = getNumberOfEntries(type); + uint32_t* entries = mEntriesByType[type]; + size_t count = 0; + for (size_t i=0; i<N; i++) { + if (entries[i] != 0) { + count++; + } + } + return count; +} + +uint32_t PackageRedirectionMap::getEntry(int type, int entry) +{ + uint32_t* entries = mEntriesByType[type]; + return entries[entry]; +} diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 0107da4..44316d4 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +26,7 @@ #include <utils/String16.h> #include <utils/String8.h> #include <utils/TextOutput.h> +#include <utils/misc.h> #include <stdlib.h> #include <string.h> @@ -43,6 +45,7 @@ #define TABLE_SUPER_NOISY(x) //x #define LOAD_TABLE_NOISY(x) //x #define TABLE_THEME(x) //x +#define REDIRECT_NOISY(x) //x namespace android { @@ -2487,6 +2490,13 @@ status_t ResTable::Theme::applyStyle(uint32_t resID, bool force) const bag_entry* bag; uint32_t bagTypeSpecFlags = 0; mTable.lock(); + uint32_t redirect = mTable.lookupRedirectionMap(resID); + if (redirect != 0 || resID == 0x01030005) { + REDIRECT_NOISY(ALOGW("applyStyle: PERFORMED REDIRECT OF ident=0x%08x FOR redirect=0x%08x\n", resID, redirect)); + } + if (redirect != 0) { + resID = redirect; + } const ssize_t N = mTable.getBagLocked(resID, &bag, &bagTypeSpecFlags); TABLE_NOISY(ALOGV("Applying style 0x%08x to theme %p, count=%d", resID, this, N)); if (N < 0) { @@ -2934,6 +2944,8 @@ void ResTable::uninit() mPackageGroups.clear(); mHeaders.clear(); + + clearRedirections(); } bool ResTable::getResourceName(uint32_t resID, resource_name* outName) const @@ -3191,6 +3203,24 @@ ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex, return blockIndex; } +uint32_t ResTable::lookupRedirectionMap(uint32_t resID) const +{ + if (mError != NO_ERROR) { + return 0; + } + + const int p = Res_GETPACKAGE(resID)+1; + + const size_t N = mRedirectionMap.size(); + for (size_t i=0; i<N; i++) { + PackageRedirectionMap* resMap = mRedirectionMap[i]; + if (resMap->getPackage() == p) { + return resMap->lookupRedirection(resID); + } + } + return 0; +} + const char16_t* ResTable::valueToString( const Res_value* value, size_t stringBlock, char16_t tmpBuffer[TMP_BUFFER_SIZE], size_t* outLen) @@ -3396,7 +3426,19 @@ ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag, if (parent) { const bag_entry* parentBag; uint32_t parentTypeSpecFlags = 0; - const ssize_t NP = getBagLocked(parent, &parentBag, &parentTypeSpecFlags); + uint32_t parentRedirect = lookupRedirectionMap(parent); + uint32_t parentActual = parent; + if (parentRedirect != 0 || parent == 0x01030005) { + if (parentRedirect == resID) { + REDIRECT_NOISY(ALOGW("applyStyle(parent): ignoring circular redirect from parent=0x%08x to parentRedirect=0x%08x\n", parent, parentRedirect)); + } else { + REDIRECT_NOISY(ALOGW("applyStyle(parent): PERFORMED REDIRECT OF parent=0x%08x FOR parentRedirect=0x%08x\n", parent, parentRedirect)); + if (parentRedirect != 0) { + parentActual = parentRedirect; + } + } + } + const ssize_t NP = getBagLocked(parentActual, &parentBag, &parentTypeSpecFlags); const size_t NT = ((NP >= 0) ? NP : 0) + N; set = (bag_set*)malloc(sizeof(bag_set)+sizeof(bag_entry)*NT); if (set == NULL) { @@ -5318,6 +5360,78 @@ bool ResTable::getIdmapInfo(const void* idmap, size_t sizeBytes, return true; } +void ResTable::removeAssetsByCookie(const String8 &packageName, void* cookie) +{ + mError = NO_ERROR; + + size_t N = mHeaders.size(); + for (size_t i = 0; i < N; i++) { + Header* header = mHeaders[i]; + if ((size_t)header->cookie == (size_t)cookie) { + if (header->ownedData != NULL) { + free(header->ownedData); + } + mHeaders.removeAt(i); + break; + } + } + size_t pgCount = mPackageGroups.size(); + for (size_t pgIndex = 0; pgIndex < pgCount; pgIndex++) { + PackageGroup* pg = mPackageGroups[pgIndex]; + + size_t pkgCount = pg->packages.size(); + size_t index = pkgCount; + for (size_t pkgIndex = 0; pkgIndex < pkgCount; pkgIndex++) { + const Package* pkg = pg->packages[pkgIndex]; + if (String8(String16(pkg->package->name)).compare(packageName) == 0) { + index = pkgIndex; + ALOGV("Delete Package %d id=%d name=%s\n", + (int)pkgIndex, pkg->package->id, + String8(String16(pkg->package->name)).string()); + break; + } + } + if (index < pkgCount) { + const Package* pkg = pg->packages[index]; + uint32_t id = dtohl(pkg->package->id); + if (id != 0 && id < 256) { + mPackageMap[id] = 0; + } + if (pkgCount == 1) { + ALOGV("Delete Package Group %d id=%d packageCount=%d name=%s\n", + (int)pgIndex, pg->id, (int)pg->packages.size(), + String8(pg->name).string()); + mPackageGroups.removeAt(pgIndex); + delete pg; + } else { + pg->packages.removeAt(index); + delete pkg; + } + return; + } + } +} + +/* + * Load the redirection map from the supplied map path. + * + * The path is expected to be a directory containing individual map cache files + * for each package that is to have resources redirected. Only those packages + * that are included in this ResTable will be loaded into the redirection map. + * For this reason, this method should be called only after all resource + * bundles have been added to the table. + */ +void ResTable::addRedirections(PackageRedirectionMap* resMap) +{ + // TODO: Replace an existing entry matching the same package. + mRedirectionMap.add(resMap); +} + +void ResTable::clearRedirections() +{ + /* This memory is being managed by strong references at the Java layer. */ + mRedirectionMap.clear(); +} #ifndef HAVE_ANDROID_OS #define CHAR16_TO_CSTR(c16, len) (String8(String16(c16,len)).string()) |