diff options
author | Nick Kralevich <nnk@google.com> | 2014-02-12 14:05:30 -0800 |
---|---|---|
committer | Nick Kralevich <nnk@google.com> | 2014-02-12 14:08:06 -0800 |
commit | 1cbea39fe1740d7d1c3e4aa0e4771a99a56c79ef (patch) | |
tree | 609e7c7ad6a58d44191de97af33a11d9a5e1c78d /libs/androidfw | |
parent | 7594767e55e011101ed9341f01d40730fdbd4cc7 (diff) | |
parent | dd3d95f182a634acdcc1b1e8e4954234d048eb54 (diff) | |
download | frameworks_base-1cbea39fe1740d7d1c3e4aa0e4771a99a56c79ef.zip frameworks_base-1cbea39fe1740d7d1c3e4aa0e4771a99a56c79ef.tar.gz frameworks_base-1cbea39fe1740d7d1c3e4aa0e4771a99a56c79ef.tar.bz2 |
resolved conflicts for merge of dd3d95f1 to klp-volantis-dev
Change-Id: I96c0f0da852a0b3cf8aef9158678d38aa30f456f
Diffstat (limited to 'libs/androidfw')
-rw-r--r-- | libs/androidfw/AssetManager.cpp | 314 | ||||
-rw-r--r-- | libs/androidfw/ResourceTypes.cpp | 76 |
2 files changed, 218 insertions, 172 deletions
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp index 058126f..5069958 100644 --- a/libs/androidfw/AssetManager.cpp +++ b/libs/androidfw/AssetManager.cpp @@ -41,10 +41,8 @@ #include <assert.h> #include <dirent.h> #include <errno.h> -#include <fcntl.h> +#include <string.h> // strerror #include <strings.h> -#include <sys/stat.h> -#include <unistd.h> #ifndef TEMP_FAILURE_RETRY /* Used to retry syscalls that can return EINTR. */ @@ -75,7 +73,7 @@ static const char* kDefaultVendor = "default"; static const char* kAssetsRoot = "assets"; static const char* kAppZipName = NULL; //"classes.jar"; static const char* kSystemAssets = "framework/framework-res.apk"; -static const char* kIdmapCacheDir = "resource-cache"; +static const char* kResourceCache = "resource-cache"; static const char* kExcludeExtension = ".EXCLUDE"; @@ -84,15 +82,19 @@ static Asset* const kExcludedAsset = (Asset*) 0xd000000d; static volatile int32_t gCount = 0; const char* AssetManager::RESOURCES_FILENAME = "resources.arsc"; +const char* AssetManager::IDMAP_BIN = "/system/bin/idmap"; +const char* AssetManager::OVERLAY_DIR = "/vendor/overlay"; +const char* AssetManager::TARGET_PACKAGE_NAME = "android"; +const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk"; +const char* AssetManager::IDMAP_DIR = "/data/resource-cache"; namespace { - // Transform string /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap String8 idmapPathForPackagePath(const String8& pkgPath) { const char* root = getenv("ANDROID_DATA"); LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set"); String8 path(root); - path.appendPath(kIdmapCacheDir); + path.appendPath(kResourceCache); char buf[256]; // 256 chars should be enough for anyone... strncpy(buf, pkgPath.string(), 255); @@ -210,203 +212,99 @@ bool AssetManager::addAssetPath(const String8& path, int32_t* cookie) *cookie = static_cast<int32_t>(mAssetPaths.size()); } - // add overlay packages for /system/framework; apps are handled by the - // (Java) package manager - if (strncmp(path.string(), "/system/framework/", 18) == 0) { - // When there is an environment variable for /vendor, this - // should be changed to something similar to how ANDROID_ROOT - // and ANDROID_DATA are used in this file. - String8 overlayPath("/vendor/overlay/framework/"); - overlayPath.append(path.getPathLeaf()); - if (TEMP_FAILURE_RETRY(access(overlayPath.string(), R_OK)) == 0) { - asset_path oap; - oap.path = overlayPath; - oap.type = ::getFileType(overlayPath.string()); - bool addOverlay = (oap.type == kFileTypeRegular); // only .apks supported as overlay - if (addOverlay) { - oap.idmap = idmapPathForPackagePath(overlayPath); - - if (isIdmapStaleLocked(ap.path, oap.path, oap.idmap)) { - addOverlay = createIdmapFileLocked(ap.path, oap.path, oap.idmap); - } - } - if (addOverlay) { - mAssetPaths.add(oap); - } else { - ALOGW("failed to add overlay package %s\n", overlayPath.string()); - } - } +#ifdef HAVE_ANDROID_OS + // Load overlays, if any + asset_path oap; + for (size_t idx = 0; mZipSet.getOverlay(ap.path, idx, &oap); idx++) { + mAssetPaths.add(oap); } +#endif return true; } -bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApkPath, - uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize) +bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie) { - AutoMutex _l(mLock); - const String8 paths[2] = { String8(targetApkPath), String8(overlayApkPath) }; - ResTable tables[2]; + const String8 idmapPath = idmapPathForPackagePath(packagePath); - for (int i = 0; i < 2; ++i) { - asset_path ap; - ap.type = kFileTypeRegular; - ap.path = paths[i]; - Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap); - if (ass == NULL) { - ALOGW("failed to find resources.arsc in %s\n", ap.path.string()); - return false; - } - tables[i].add(ass, 1, false); - } + AutoMutex _l(mLock); - return tables[0].createIdmap(tables[1], targetCrc, overlayCrc, - targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR; -} + for (size_t i = 0; i < mAssetPaths.size(); ++i) { + if (mAssetPaths[i].idmap == idmapPath) { + *cookie = static_cast<int32_t>(i + 1); + return true; + } + } -bool AssetManager::isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath, - const String8& idmapPath) -{ - struct stat st; - if (TEMP_FAILURE_RETRY(stat(idmapPath.string(), &st)) == -1) { - if (errno == ENOENT) { - return true; // non-existing idmap is always stale - } else { - ALOGW("failed to stat file %s: %s\n", idmapPath.string(), strerror(errno)); - return false; - } - } - if (st.st_size < ResTable::IDMAP_HEADER_SIZE_BYTES) { - ALOGW("file %s has unexpectedly small size=%zd\n", idmapPath.string(), (size_t)st.st_size); + Asset* idmap = NULL; + if ((idmap = openAssetFromFileLocked(idmapPath, Asset::ACCESS_BUFFER)) == NULL) { + ALOGW("failed to open idmap file %s\n", idmapPath.string()); return false; } - int fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_RDONLY)); - if (fd == -1) { - ALOGW("failed to open file %s: %s\n", idmapPath.string(), strerror(errno)); - return false; - } - char buf[ResTable::IDMAP_HEADER_SIZE_BYTES]; - ssize_t bytesLeft = ResTable::IDMAP_HEADER_SIZE_BYTES; - for (;;) { - ssize_t r = TEMP_FAILURE_RETRY(read(fd, buf + ResTable::IDMAP_HEADER_SIZE_BYTES - bytesLeft, - bytesLeft)); - if (r < 0) { - TEMP_FAILURE_RETRY(close(fd)); - return false; - } - bytesLeft -= r; - if (bytesLeft == 0) { - break; - } - } - TEMP_FAILURE_RETRY(close(fd)); - uint32_t cachedOriginalCrc, cachedOverlayCrc; - if (!ResTable::getIdmapInfo(buf, ResTable::IDMAP_HEADER_SIZE_BYTES, - &cachedOriginalCrc, &cachedOverlayCrc)) { + String8 targetPath; + String8 overlayPath; + if (!ResTable::getIdmapInfo(idmap->getBuffer(false), idmap->getLength(), + NULL, NULL, &targetPath, &overlayPath)) { + ALOGW("failed to read idmap file %s\n", idmapPath.string()); + delete idmap; return false; } + delete idmap; - uint32_t actualOriginalCrc, actualOverlayCrc; - if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &actualOriginalCrc)) { + if (overlayPath != packagePath) { + ALOGW("idmap file %s inconcistent: expected path %s does not match actual path %s\n", + idmapPath.string(), packagePath.string(), overlayPath.string()); return false; } - if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &actualOverlayCrc)) { + if (access(targetPath.string(), R_OK) != 0) { + ALOGW("failed to access file %s: %s\n", targetPath.string(), strerror(errno)); return false; } - return cachedOriginalCrc != actualOriginalCrc || cachedOverlayCrc != actualOverlayCrc; -} - -bool AssetManager::getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename, - uint32_t* pCrc) -{ - asset_path ap; - ap.path = zipPath; - const ZipFileRO* zip = getZipFileLocked(ap); - if (zip == NULL) { + if (access(idmapPath.string(), R_OK) != 0) { + ALOGW("failed to access file %s: %s\n", idmapPath.string(), strerror(errno)); return false; } - const ZipEntryRO entry = zip->findEntryByName(entryFilename); - if (entry == NULL) { + if (access(overlayPath.string(), R_OK) != 0) { + ALOGW("failed to access file %s: %s\n", overlayPath.string(), strerror(errno)); return false; } - const bool gotInfo = zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, (long*)pCrc); - zip->releaseEntry(entry); + asset_path oap; + oap.path = overlayPath; + oap.type = ::getFileType(overlayPath.string()); + oap.idmap = idmapPath; +#if 0 + ALOGD("Overlay added: targetPath=%s overlayPath=%s idmapPath=%s\n", + targetPath.string(), overlayPath.string(), idmapPath.string()); +#endif + mAssetPaths.add(oap); + *cookie = static_cast<int32_t>(mAssetPaths.size()); - return gotInfo; -} + return true; + } -bool AssetManager::createIdmapFileLocked(const String8& originalPath, const String8& overlayPath, - const String8& idmapPath) +bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApkPath, + uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize) { - ALOGD("%s: originalPath=%s overlayPath=%s idmapPath=%s\n", - __FUNCTION__, originalPath.string(), overlayPath.string(), idmapPath.string()); + AutoMutex _l(mLock); + const String8 paths[2] = { String8(targetApkPath), String8(overlayApkPath) }; ResTable tables[2]; - const String8* paths[2] = { &originalPath, &overlayPath }; - uint32_t originalCrc, overlayCrc; - bool retval = false; - ssize_t offset = 0; - int fd = 0; - uint32_t* data = NULL; - size_t size; for (int i = 0; i < 2; ++i) { asset_path ap; ap.type = kFileTypeRegular; - ap.path = *paths[i]; + ap.path = paths[i]; Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap); if (ass == NULL) { ALOGW("failed to find resources.arsc in %s\n", ap.path.string()); - goto error; + return false; } tables[i].add(ass, 1, false /* copyData */, NULL /* idMap */); } - if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &originalCrc)) { - ALOGW("failed to retrieve crc for resources.arsc in %s\n", originalPath.string()); - goto error; - } - if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &overlayCrc)) { - ALOGW("failed to retrieve crc for resources.arsc in %s\n", overlayPath.string()); - goto error; - } - - if (tables[0].createIdmap(tables[1], originalCrc, overlayCrc, - (void**)&data, &size) != NO_ERROR) { - ALOGW("failed to generate idmap data for file %s\n", idmapPath.string()); - goto error; - } - - // This should be abstracted (eg replaced by a stand-alone - // application like dexopt, triggered by something equivalent to - // installd). - fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_WRONLY | O_CREAT | O_TRUNC, 0644)); - if (fd == -1) { - ALOGW("failed to write idmap file %s (open: %s)\n", idmapPath.string(), strerror(errno)); - goto error_free; - } - for (;;) { - ssize_t written = TEMP_FAILURE_RETRY(write(fd, data + offset, size)); - if (written < 0) { - ALOGW("failed to write idmap file %s (write: %s)\n", idmapPath.string(), - strerror(errno)); - goto error_close; - } - size -= (size_t)written; - offset += written; - if (size == 0) { - break; - } - } - - retval = true; -error_close: - TEMP_FAILURE_RETRY(close(fd)); -error_free: - free(data); -error: - return retval; + return tables[0].createIdmap(tables[1], targetCrc, overlayCrc, + targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR; } bool AssetManager::addDefaultAssets() @@ -685,6 +583,10 @@ const ResTable* AssetManager::getResTable(bool required) const // which we want to avoid parsing every time. sharedRes = const_cast<AssetManager*>(this)-> mZipSet.getZipResourceTable(ap.path); + if (sharedRes != NULL) { + // skip ahead the number of system overlay packages preloaded + i += sharedRes->getTableCount() - 1; + } } if (sharedRes == NULL) { ass = const_cast<AssetManager*>(this)-> @@ -708,6 +610,14 @@ const ResTable* AssetManager::getResTable(bool required) const ALOGV("Creating shared resources for %s", ap.path.string()); sharedRes = new ResTable(); sharedRes->add(ass, i + 1, false, idmap); +#ifdef HAVE_ANDROID_OS + const char* data = getenv("ANDROID_DATA"); + LOG_ALWAYS_FATAL_IF(data == NULL, "ANDROID_DATA not set"); + String8 overlaysListPath(data); + overlaysListPath.appendPath(kResourceCache); + overlaysListPath.appendPath("overlays.list"); + addSystemOverlays(overlaysListPath.string(), ap.path, sharedRes, i); +#endif sharedRes = const_cast<AssetManager*>(this)-> mZipSet.setZipResourceTable(ap.path, sharedRes); } @@ -791,6 +701,46 @@ Asset* AssetManager::openIdmapLocked(const struct asset_path& ap) const return ass; } +void AssetManager::addSystemOverlays(const char* pathOverlaysList, + const String8& targetPackagePath, ResTable* sharedRes, size_t offset) const +{ + FILE* fin = fopen(pathOverlaysList, "r"); + if (fin == NULL) { + return; + } + + char buf[1024]; + while (fgets(buf, sizeof(buf), fin)) { + // format of each line: + // <path to apk><space><path to idmap><newline> + char* space = strchr(buf, ' '); + char* newline = strchr(buf, '\n'); + asset_path oap; + + if (space == NULL || newline == NULL || newline < space) { + continue; + } + + oap.path = String8(buf, space - buf); + oap.type = kFileTypeRegular; + oap.idmap = String8(space + 1, newline - space - 1); + + Asset* oass = const_cast<AssetManager*>(this)-> + openNonAssetInPathLocked("resources.arsc", + Asset::ACCESS_BUFFER, + oap); + + if (oass != NULL) { + Asset* oidmap = openIdmapLocked(oap); + offset++; + sharedRes->add(oass, offset + 1, false, oidmap); + const_cast<AssetManager*>(this)->mAssetPaths.add(oap); + const_cast<AssetManager*>(this)->mZipSet.addOverlay(targetPackagePath, oap); + } + } + fclose(fin); +} + const ResTable& AssetManager::getResources(bool required) const { const ResTable* rt = getResTable(required); @@ -1849,7 +1799,8 @@ AssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen) } } -sp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path) +sp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path, + bool createIfNotPresent) { AutoMutex _l(gLock); time_t modWhen = getFileModDate(path); @@ -1857,6 +1808,9 @@ sp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path) if (zip != NULL && zip->mModWhen == modWhen) { return zip; } + if (zip == NULL && !createIfNotPresent) { + return NULL; + } zip = new SharedZip(path, modWhen); gOpen.add(path, zip); return zip; @@ -1915,6 +1869,20 @@ bool AssetManager::SharedZip::isUpToDate() return mModWhen == modWhen; } +void AssetManager::SharedZip::addOverlay(const asset_path& ap) +{ + mOverlays.add(ap); +} + +bool AssetManager::SharedZip::getOverlay(size_t idx, asset_path* out) const +{ + if (idx >= mOverlays.size()) { + return false; + } + *out = mOverlays[idx]; + return true; +} + AssetManager::SharedZip::~SharedZip() { //ALOGI("Destroying SharedZip %p %s\n", this, (const char*)mPath); @@ -2038,6 +2006,22 @@ bool AssetManager::ZipSet::isUpToDate() return true; } +void AssetManager::ZipSet::addOverlay(const String8& path, const asset_path& overlay) +{ + int idx = getIndex(path); + sp<SharedZip> zip = mZipFile[idx]; + zip->addOverlay(overlay); +} + +bool AssetManager::ZipSet::getOverlay(const String8& path, size_t idx, asset_path* out) const +{ + sp<SharedZip> zip = SharedZip::get(path, false); + if (zip == NULL) { + return false; + } + return zip->getOverlay(idx, out); +} + /* * Compute the zip file's index. * diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 609ad19..8cc98af 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -284,11 +284,37 @@ static status_t getIdmapPackageId(const uint32_t* map, size_t mapSize, uint32_t if (!assertIdmapHeader(map, mapSize)) { return UNKNOWN_ERROR; } + if (mapSize <= IDMAP_HEADER_SIZE + 1) { + ALOGW("corrupt idmap: map size %d too short\n", mapSize); + return UNKNOWN_ERROR; + } + uint32_t typeCount = *(map + IDMAP_HEADER_SIZE); + if (typeCount == 0) { + ALOGW("corrupt idmap: no types\n"); + return UNKNOWN_ERROR; + } + if (IDMAP_HEADER_SIZE + 1 + typeCount > mapSize) { + ALOGW("corrupt idmap: number of types %d extends past idmap size %d\n", typeCount, mapSize); + return UNKNOWN_ERROR; + } const uint32_t* p = map + IDMAP_HEADER_SIZE + 1; + // find first defined type while (*p == 0) { ++p; + if (--typeCount == 0) { + ALOGW("corrupt idmap: types declared, none found\n"); + return UNKNOWN_ERROR; + } + } + + // determine package id from first entry of first type + const uint32_t offset = *p + IDMAP_HEADER_SIZE + 2; + if (offset > mapSize) { + ALOGW("corrupt idmap: entry offset %d points outside map size %d\n", offset, mapSize); + return UNKNOWN_ERROR; } - *outId = (map[*p + IDMAP_HEADER_SIZE + 2] >> 24) & 0x000000ff; + *outId = (map[offset] >> 24) & 0x000000ff; + return NO_ERROR; } @@ -5334,23 +5360,30 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg, return NO_ERROR; } -status_t ResTable::createIdmap(const ResTable& overlay, uint32_t originalCrc, uint32_t overlayCrc, - void** outData, size_t* outSize) const +status_t ResTable::createIdmap(const ResTable& overlay, + uint32_t targetCrc, uint32_t overlayCrc, + const char* targetPath, const char* overlayPath, + void** outData, size_t* outSize) const { // see README for details on the format of map if (mPackageGroups.size() == 0) { + ALOGW("idmap: target package has no package groups, cannot create idmap\n"); return UNKNOWN_ERROR; } if (mPackageGroups[0]->packages.size() == 0) { + ALOGW("idmap: target package has no packages in its first package group, " + "cannot create idmap\n"); return UNKNOWN_ERROR; } Vector<Vector<uint32_t> > map; + // overlaid packages are assumed to contain only one package group const PackageGroup* pg = mPackageGroups[0]; const Package* pkg = pg->packages[0]; size_t typeCount = pkg->types.size(); // starting size is header + first item (number of types in map) *outSize = (IDMAP_HEADER_SIZE + 1) * sizeof(uint32_t); + // overlay packages are assumed to contain only one package group const String16 overlayPackage(overlay.mPackageGroups[0]->packages[0]->package->name); const uint32_t pkg_id = pkg->package->id << 24; @@ -5426,8 +5459,22 @@ status_t ResTable::createIdmap(const ResTable& overlay, uint32_t originalCrc, ui } uint32_t* data = (uint32_t*)*outData; *data++ = htodl(IDMAP_MAGIC); - *data++ = htodl(originalCrc); + *data++ = htodl(targetCrc); *data++ = htodl(overlayCrc); + const char* paths[] = { targetPath, overlayPath }; + for (int j = 0; j < 2; ++j) { + char* p = (char*)data; + const char* path = paths[j]; + const size_t I = strlen(path); + if (I > 255) { + ALOGV("path exceeds expected 255 characters: %s\n", path); + return UNKNOWN_ERROR; + } + for (size_t i = 0; i < 256; ++i) { + *p++ = i < I ? path[i] : '\0'; + } + data += 256 / sizeof(uint32_t); + } const size_t mapSize = map.size(); *data++ = htodl(mapSize); size_t offset = mapSize; @@ -5442,6 +5489,10 @@ status_t ResTable::createIdmap(const ResTable& overlay, uint32_t originalCrc, ui offset += N; } } + if (offset == mapSize) { + ALOGW("idmap: no resources in overlay package present in base package\n"); + return UNKNOWN_ERROR; + } for (size_t i = 0; i < mapSize; ++i) { const Vector<uint32_t>& vector = map.itemAt(i); const size_t N = vector.size(); @@ -5463,14 +5514,25 @@ status_t ResTable::createIdmap(const ResTable& overlay, uint32_t originalCrc, ui } bool ResTable::getIdmapInfo(const void* idmap, size_t sizeBytes, - uint32_t* pOriginalCrc, uint32_t* pOverlayCrc) + uint32_t* pTargetCrc, uint32_t* pOverlayCrc, + String8* pTargetPath, String8* pOverlayPath) { const uint32_t* map = (const uint32_t*)idmap; if (!assertIdmapHeader(map, sizeBytes)) { return false; } - *pOriginalCrc = map[1]; - *pOverlayCrc = map[2]; + if (pTargetCrc) { + *pTargetCrc = map[1]; + } + if (pOverlayCrc) { + *pOverlayCrc = map[2]; + } + if (pTargetPath) { + pTargetPath->setTo(reinterpret_cast<const char*>(map + 3)); + } + if (pOverlayPath) { + pOverlayPath->setTo(reinterpret_cast<const char*>(map + 3 + 256 / sizeof(uint32_t))); + } return true; } |