summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorSergey Ten <sergey.ten6@t-mobile.com>2009-09-07 10:33:56 -0700
committerSergey Ten <sergey.ten6@t-mobile.com>2009-09-23 08:15:59 -0700
commitfd2649b1b6f5c7750c9cb0f13a6cc80522d09678 (patch)
treea9327a292b69ac78f2bd1d7459fe7ba9db847abb /libs
parent3aa0e5063251d5f33c5f1b496f26b7d7fe7f9fb7 (diff)
downloadframeworks_base-fd2649b1b6f5c7750c9cb0f13a6cc80522d09678.zip
frameworks_base-fd2649b1b6f5c7750c9cb0f13a6cc80522d09678.tar.gz
frameworks_base-fd2649b1b6f5c7750c9cb0f13a6cc80522d09678.tar.bz2
Add support for modifying ResTable on fly.
This change allows to either delete or add asset path after a ResTable object has been created for a given AssetManager. In past, the lack of such support forced us to implement update configuration functionality suboptimally, by recreating new AssetManager object from scratch on theme change. With this change, we can simply remove the "old" theme asset path and add the new asset path. We also need to make sure the Resources object nukes internal caches. CR:JoshG.
Diffstat (limited to 'libs')
-rw-r--r--libs/utils/AssetManager.cpp145
-rw-r--r--libs/utils/ResourceTypes.cpp210
2 files changed, 303 insertions, 52 deletions
diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp
index 624fd7e..7681695 100644
--- a/libs/utils/AssetManager.cpp
+++ b/libs/utils/AssetManager.cpp
@@ -392,45 +392,13 @@ const ResTable* AssetManager::getResTable(bool required) const
if (mCacheMode != CACHE_OFF && !mCacheValid)
const_cast<AssetManager*>(this)->loadFileNameCacheLocked();
- const size_t N = mAssetPaths.size();
- for (size_t i=0; i<N; i++) {
- Asset* ass = NULL;
- bool shared = true;
- const asset_path& ap = mAssetPaths.itemAt(i);
- LOGV("Looking for resource asset in '%s'\n", ap.path.string());
- if (ap.type != kFileTypeDirectory) {
- ass = const_cast<AssetManager*>(this)->
- mZipSet.getZipResourceTable(ap.path);
- if (ass == NULL) {
- LOGV("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.setZipResourceTable(ap.path, ass);
- }
- }
- } else {
- LOGV("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 && ass != kExcludedAsset) {
- if (rt == NULL) {
- mResources = rt = new ResTable();
- updateResourceParamsLocked();
- }
- LOGV("Installing resource asset %p in to table %p\n", ass, mResources);
- rt->add(ass, (void*)(i+1), !shared);
+ mResources = rt = new ResTable();
- if (!shared) {
- delete ass;
- }
+ 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));
}
}
@@ -438,9 +406,48 @@ 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;
+ bool shared = true;
+ LOGV("Looking for resource asset in '%s'\n", ap.path.string());
+ if (ap.type != kFileTypeDirectory) {
+ ass = const_cast<AssetManager*>(this)->
+ mZipSet.getZipResourceTable(ap.path);
+ if (ass == NULL) {
+ LOGV("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.setZipResourceTable(ap.path, ass);
+ }
+ }
+ } else {
+ LOGV("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 && ass != kExcludedAsset) {
+ updateResourceParamsLocked();
+ LOGV("Installing resource asset %p in to table %p\n", ass, mResources);
+ rt->add(ass, cookie, !shared);
+
+ if (!shared) {
+ delete ass;
+ }
+ }
+}
+
void AssetManager::updateResourceParamsLocked() const
{
ResTable* res = mResources;
@@ -1635,22 +1642,58 @@ int AssetManager::ZipSet::getIndex(const String8& zip) const
return mZipPath.size()-1;
}
-/*
- * Mark asset path "stack" to support un-install from the mAssetPaths.
- */
-int AssetManager::markAssetPathStack()
+bool AssetManager::updateWithAssetPath(const String8& path, void** cookie)
{
- return (int)mAssetPaths.size();
+ bool res = addAssetPath(path, cookie);
+ 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;
}
-/*
- * Restore asset path "stack" by un-installing from the mAssetPaths
- * all assets installed after restoreIndex.
- */
-void AssetManager::restoreAssetPathStack(int restoreIndex)
+bool AssetManager::removeAssetPath(const String8 &packageName, const String8 &assetPath)
{
- int i = (int)mAssetPaths.size();
- while (i > restoreIndex) {
- mAssetPaths.removeAt(--i);
+ AutoMutex _l(mLock);
+
+ String8 realPath(assetPath);
+ if (kAppZipName) {
+ realPath.appendPath(kAppZipName);
+ }
+
+ // Check if the path exists.
+ size_t cookie = 0;
+ for (size_t i = 0; i < mAssetPaths.size(); i++) {
+ if (strcmp(mAssetPaths[i].path, realPath) == 0) {
+ mAssetPaths.removeAt(i);
+ cookie = i + 1;
+ break;
+ }
+ }
+
+ if (cookie == 0) {
+ return false;
+ }
+
+ ResTable* rt = mResources;
+ if (rt == NULL) {
+ LOGV("ResTable must not be NULL");
+ return false;
+ }
+
+ rt->removeAssetsByCookie(packageName, (void *)cookie);
+
+ return true;
+}
+
+void AssetManager::dumpRes()
+{
+ ResTable* rt = mResources;
+ if (rt == NULL) {
+ fprintf(stderr, "ResTable must not be NULL");
+ return;
}
+ rt->dump();
}
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 5910c86..cc3f5d9 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -62,6 +62,8 @@ namespace android {
#endif
#endif
+#define PACKAGE_RESOURCE_ID_TO_DUMP 10
+
static void printToLogFunc(void* cookie, const char* txt)
{
LOGV("%s", txt);
@@ -3847,9 +3849,61 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg,
return NO_ERROR;
}
-#ifndef HAVE_ANDROID_OS
+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;
+ LOGV("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;
+ }
+ pg->packages.removeAt(index);
+ delete pkg;
+ if (pkgCount == 1) {
+ LOGV("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;
+ return;
+ }
+ }
+}
+
#define CHAR16_TO_CSTR(c16, len) (String8(String16(c16,len)).string())
+#ifndef HAVE_ANDROID_OS
+
#define CHAR16_ARRAY_EQ(constant, var, len) \
((len == (sizeof(constant)/sizeof(constant[0]))) && (0 == memcmp((var), (constant), (len))))
@@ -4005,4 +4059,158 @@ void ResTable::print() const
#endif // HAVE_ANDROID_OS
+void ResTable::dump() const
+{
+ LOGI("mError=0x%x (%s)\n", mError, strerror(mError));
+#if 0
+ LOGI("mParams=%c%c-%c%c,\n",
+ mParams.language[0], mParams.language[1],
+ mParams.country[0], mParams.country[1]);
+#endif
+ size_t pgCount = mPackageGroups.size();
+ LOGI("Package Groups (%d)\n", (int)pgCount);
+ for (size_t pgIndex=0; pgIndex<pgCount; pgIndex++) {
+ const PackageGroup* pg = mPackageGroups[pgIndex];
+ LOGI("Package Group %d id=%d packageCount=%d name=%s\n",
+ (int)pgIndex, pg->id, (int)pg->packages.size(),
+ String8(pg->name).string());
+
+ size_t pkgCount = pg->packages.size();
+ for (size_t pkgIndex=0; pkgIndex<pkgCount; pkgIndex++) {
+ const Package* pkg = pg->packages[pkgIndex];
+ if (pkg->package->id != PACKAGE_RESOURCE_ID_TO_DUMP) continue; // HACK!
+ size_t count = 0;
+ size_t typeCount = pkg->types.size();
+ LOGI(" Package %d id=%d name=%s typeCount=%d\n", (int)pkgIndex,
+ pkg->package->id, String8(String16(pkg->package->name)).string(),
+ (int)typeCount);
+ for (size_t typeIndex=0; typeIndex<typeCount&&count<10; typeIndex++) {
+ const Type* typeConfigs = pkg->getType(typeIndex);
+ if (typeConfigs == NULL) {
+ LOGI(" type %d NULL\n", (int)typeIndex);
+ continue;
+ }
+ const size_t NTC = typeConfigs->configs.size();
+ LOGI(" type %d configCount=%d entryCount=%d\n",
+ (int)typeIndex, (int)NTC, (int)typeConfigs->entryCount);
+ if (typeConfigs->typeSpecFlags != NULL) {
+ for (size_t entryIndex=0; entryIndex<typeConfigs->entryCount&&count<10; entryIndex++) {
+ uint32_t resID = (0xff000000 & ((pkg->package->id)<<24))
+ | (0x00ff0000 & ((typeIndex+1)<<16))
+ | (0x0000ffff & (entryIndex));
+ resource_name resName;
+ this->getResourceName(resID, &resName);
+ count++;
+ LOGI(" spec resource 0x%08x %s:%s/%s: flags=0x%08x\n",
+ resID,
+ CHAR16_TO_CSTR(resName.package, resName.packageLen),
+ CHAR16_TO_CSTR(resName.type, resName.typeLen),
+ CHAR16_TO_CSTR(resName.name, resName.nameLen),
+ dtohl(typeConfigs->typeSpecFlags[entryIndex]));
+ }
+ }
+ for (size_t configIndex=0; configIndex<NTC&&count<10; configIndex++) {
+ const ResTable_type* type = typeConfigs->configs[configIndex];
+ if ((((uint64_t)type)&0x3) != 0) {
+ LOGI(" NON-INTEGER ResTable_type ADDRESS: %p\n", type);
+ continue;
+ }
+ count++;
+ LOGI(" config %d lang=%c%c cnt=%c%c orien=%d touch=%d density=%d key=%d infl=%d nav=%d w=%d h=%d\n",
+ (int)configIndex,
+ type->config.language[0] ? type->config.language[0] : '-',
+ type->config.language[1] ? type->config.language[1] : '-',
+ type->config.country[0] ? type->config.country[0] : '-',
+ type->config.country[1] ? type->config.country[1] : '-',
+ type->config.orientation,
+ type->config.touchscreen,
+ dtohs(type->config.density),
+ type->config.keyboard,
+ type->config.inputFlags,
+ type->config.navigation,
+ dtohs(type->config.screenWidth),
+ dtohs(type->config.screenHeight));
+ size_t entryCount = dtohl(type->entryCount);
+ uint32_t entriesStart = dtohl(type->entriesStart);
+ if ((entriesStart&0x3) != 0) {
+ LOGI(" NON-INTEGER ResTable_type entriesStart OFFSET: %p\n", (void*)entriesStart);
+ continue;
+ }
+ uint32_t typeSize = dtohl(type->header.size);
+ if ((typeSize&0x3) != 0) {
+ LOGI(" NON-INTEGER ResTable_type header.size: %p\n", (void*)typeSize);
+ continue;
+ }
+ for (size_t entryIndex=0; entryIndex<entryCount&&count<10; entryIndex++) {
+ const uint8_t* const end = ((const uint8_t*)type)
+ + dtohl(type->header.size);
+ const uint32_t* const eindex = (const uint32_t*)
+ (((const uint8_t*)type) + dtohs(type->header.headerSize));
+ uint32_t thisOffset = dtohl(eindex[entryIndex]);
+ if (thisOffset == ResTable_type::NO_ENTRY) {
+ continue;
+ }
+
+ uint32_t resID = (0xff000000 & ((pkg->package->id)<<24))
+ | (0x00ff0000 & ((typeIndex+1)<<16))
+ | (0x0000ffff & (entryIndex));
+ resource_name resName;
+ this->getResourceName(resID, &resName);
+ count++;
+ LOGI(" resource 0x%08x %s:%s/%s: ", resID,
+ CHAR16_TO_CSTR(resName.package, resName.packageLen),
+ CHAR16_TO_CSTR(resName.type, resName.typeLen),
+ CHAR16_TO_CSTR(resName.name, resName.nameLen));
+ if ((thisOffset&0x3) != 0) {
+ LOGI("NON-INTEGER OFFSET: %p\n", (void*)thisOffset);
+ continue;
+ }
+ if ((thisOffset+sizeof(ResTable_entry)) > typeSize) {
+ LOGI("OFFSET OUT OF BOUNDS: %p+%p (size is %p)\n",
+ (void*)entriesStart, (void*)thisOffset,
+ (void*)typeSize);
+ continue;
+ }
+
+ const ResTable_entry* ent = (const ResTable_entry*)
+ (((const uint8_t*)type) + entriesStart + thisOffset);
+ if (((entriesStart + thisOffset)&0x3) != 0) {
+ LOGI("NON-INTEGER ResTable_entry OFFSET: %p\n",
+ (void*)(entriesStart + thisOffset));
+ continue;
+ }
+ if ((dtohs(ent->flags)&ResTable_entry::FLAG_COMPLEX) != 0) {
+ LOGI("<bag>");
+ } else {
+ uint16_t esize = dtohs(ent->size);
+ if ((esize&0x3) != 0) {
+ LOGI("NON-INTEGER ResTable_entry SIZE: %p\n", (void*)esize);
+ continue;
+ }
+ if ((thisOffset+esize) > typeSize) {
+ LOGI("ResTable_entry OUT OF BOUNDS: %p+%p+%p (size is %p)\n",
+ (void*)entriesStart, (void*)thisOffset,
+ (void*)esize, (void*)typeSize);
+ continue;
+ }
+
+ const Res_value* value = (const Res_value*)
+ (((const uint8_t*)ent) + esize);
+ count++;
+ LOGI("t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)",
+ (int)value->dataType, (int)dtohl(value->data),
+ (int)dtohs(value->size), (int)value->res0);
+ }
+
+ if ((dtohs(ent->flags)&ResTable_entry::FLAG_PUBLIC) != 0) {
+ LOGI(" (PUBLIC)");
+ }
+ LOGI("\n");
+ }
+ }
+ }
+ }
+ }
+}
+
} // namespace android