summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorRicardo Cerqueira <cyanogenmod@cerqueira.org>2012-11-20 21:17:17 +0000
committerRicardo Cerqueira <cyanogenmod@cerqueira.org>2012-11-24 14:09:39 +0000
commitad3c9416092f09213d32eee8b59287766eae5d19 (patch)
tree0bc1e318ca15560299c662e37c6c4fedf0bcf1e6 /libs
parent7d114fb838017d86ece76e18a7e1b0d8534595fa (diff)
downloadframeworks_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.mk3
-rw-r--r--libs/androidfw/AssetManager.cpp211
-rw-r--r--libs/androidfw/PackageRedirectionMap.cpp203
-rw-r--r--libs/androidfw/ResourceTypes.cpp116
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())