summaryrefslogtreecommitdiffstats
path: root/libs/androidfw/AssetManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/androidfw/AssetManager.cpp')
-rw-r--r--libs/androidfw/AssetManager.cpp231
1 files changed, 132 insertions, 99 deletions
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 56c95bd..de6a33c 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -74,6 +74,7 @@ static const char* kAssetsRoot = "assets";
static const char* kAppZipName = NULL; //"classes.jar";
static const char* kSystemAssets = "framework/framework-res.apk";
static const char* kResourceCache = "resource-cache";
+static const char* kAndroidManifest = "AndroidManifest.xml";
static const char* kExcludeExtension = ".EXCLUDE";
@@ -205,6 +206,16 @@ bool AssetManager::addAssetPath(const String8& path, int32_t* cookie)
ALOGV("In %p Asset %s path: %s", this,
ap.type == kFileTypeDirectory ? "dir" : "zip", ap.path.string());
+ // Check that the path has an AndroidManifest.xml
+ Asset* manifestAsset = const_cast<AssetManager*>(this)->openNonAssetInPathLocked(
+ kAndroidManifest, Asset::ACCESS_BUFFER, ap);
+ if (manifestAsset == NULL) {
+ // This asset path does not contain any resources.
+ delete manifestAsset;
+ return false;
+ }
+ delete manifestAsset;
+
mAssetPaths.add(ap);
// new paths are always added at the end
@@ -220,6 +231,10 @@ bool AssetManager::addAssetPath(const String8& path, int32_t* cookie)
}
#endif
+ if (mResources != NULL) {
+ appendPathToResTable(ap);
+ }
+
return true;
}
@@ -245,7 +260,7 @@ bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie)
String8 targetPath;
String8 overlayPath;
if (!ResTable::getIdmapInfo(idmap->getBuffer(false), idmap->getLength(),
- NULL, NULL, &targetPath, &overlayPath)) {
+ NULL, NULL, NULL, &targetPath, &overlayPath)) {
ALOGW("failed to read idmap file %s\n", idmapPath.string());
delete idmap;
return false;
@@ -300,7 +315,7 @@ bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApk
ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
return false;
}
- tables[i].add(ass, 1, false /* copyData */, NULL /* idMap */);
+ tables[i].add(ass);
}
return tables[0].createIdmap(tables[1], targetCrc, overlayCrc,
@@ -508,7 +523,7 @@ Asset* AssetManager::open(const char* fileName, AccessMode mode)
* The "fileName" is the partial path starting from the application
* name.
*/
-Asset* AssetManager::openNonAsset(const char* fileName, AccessMode mode)
+Asset* AssetManager::openNonAsset(const char* fileName, AccessMode mode, int32_t* outCookie)
{
AutoMutex _l(mLock);
@@ -529,6 +544,7 @@ Asset* AssetManager::openNonAsset(const char* fileName, AccessMode mode)
Asset* pAsset = openNonAssetInPathLocked(
fileName, mode, mAssetPaths.itemAt(i));
if (pAsset != NULL) {
+ if (outCookie != NULL) *outCookie = static_cast<int32_t>(i + 1);
return pAsset != kExcludedAsset ? pAsset : NULL;
}
}
@@ -584,6 +600,96 @@ FileType AssetManager::getFileType(const char* fileName)
return kFileTypeRegular;
}
+bool AssetManager::appendPathToResTable(const asset_path& ap) const {
+ Asset* ass = NULL;
+ ResTable* sharedRes = NULL;
+ bool shared = true;
+ bool onlyEmptyResources = true;
+ MY_TRACE_BEGIN(ap.path.string());
+ Asset* idmap = openIdmapLocked(ap);
+ size_t nextEntryIdx = mResources->getTableCount();
+ ALOGV("Looking for resource asset in '%s'\n", ap.path.string());
+ if (ap.type != kFileTypeDirectory) {
+ if (nextEntryIdx == 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) {
+ // skip ahead the number of system overlay packages preloaded
+ nextEntryIdx = sharedRes->getTableCount();
+ }
+ }
+ 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 (nextEntryIdx == 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, idmap, nextEntryIdx + 1, false);
+#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, nextEntryIdx);
+#endif
+ sharedRes = const_cast<AssetManager*>(this)->
+ mZipSet.setZipResourceTable(ap.path, sharedRes);
+ }
+ }
+ } else {
+ ALOGV("loading resource table %s\n", ap.path.string());
+ ass = const_cast<AssetManager*>(this)->
+ openNonAssetInPathLocked("resources.arsc",
+ Asset::ACCESS_BUFFER,
+ ap);
+ shared = false;
+ }
+
+ if ((ass != NULL || sharedRes != NULL) && ass != kExcludedAsset) {
+ ALOGV("Installing resource asset %p in to table %p\n", ass, mResources);
+ if (sharedRes != NULL) {
+ ALOGV("Copying existing resources for %s", ap.path.string());
+ mResources->add(sharedRes);
+ } else {
+ ALOGV("Parsing resources for %s", ap.path.string());
+ mResources->add(ass, idmap, nextEntryIdx + 1, !shared);
+ }
+ onlyEmptyResources = false;
+
+ if (!shared) {
+ delete ass;
+ }
+ } else {
+ ALOGV("Installing empty resources in to table %p\n", mResources);
+ mResources->addEmpty(nextEntryIdx + 1);
+ }
+
+ if (idmap != NULL) {
+ delete idmap;
+ }
+ MY_TRACE_END();
+
+ return onlyEmptyResources;
+}
+
const ResTable* AssetManager::getResTable(bool required) const
{
ResTable* rt = mResources;
@@ -603,100 +709,27 @@ const ResTable* AssetManager::getResTable(bool required) const
LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
}
- if (mCacheMode != CACHE_OFF && !mCacheValid)
+ if (mCacheMode != CACHE_OFF && !mCacheValid) {
const_cast<AssetManager*>(this)->loadFileNameCacheLocked();
+ }
+ mResources = new ResTable();
+ updateResourceParamsLocked();
+
+ bool onlyEmptyResources = true;
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);
- MY_TRACE_BEGIN(ap.path.string());
- 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) {
- // skip ahead the number of system overlay packages preloaded
- i += sharedRes->getTableCount() - 1;
- }
- }
- 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, 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);
- }
- }
- } else {
- ALOGV("loading resource table %s\n", ap.path.string());
- 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, i + 1, !shared, idmap);
- }
-
- if (!shared) {
- delete ass;
- }
- }
- if (idmap != NULL) {
- delete idmap;
- }
- MY_TRACE_END();
+ bool empty = appendPathToResTable(mAssetPaths.itemAt(i));
+ onlyEmptyResources = onlyEmptyResources && empty;
}
- if (required && !rt) ALOGW("Unable to find resources file resources.arsc");
- if (!rt) {
- mResources = rt = new ResTable();
+ if (required && onlyEmptyResources) {
+ ALOGW("Unable to find resources file resources.arsc");
+ delete mResources;
+ mResources = NULL;
}
- return rt;
+
+ return mResources;
}
void AssetManager::updateResourceParamsLocked() const
@@ -762,7 +795,7 @@ void AssetManager::addSystemOverlays(const char* pathOverlaysList,
if (oass != NULL) {
Asset* oidmap = openIdmapLocked(oap);
offset++;
- sharedRes->add(oass, offset + 1, false, oidmap);
+ sharedRes->add(oass, oidmap, offset + 1, false);
const_cast<AssetManager*>(this)->mAssetPaths.add(oap);
const_cast<AssetManager*>(this)->mZipSet.addOverlay(targetPackagePath, oap);
}
@@ -903,7 +936,7 @@ Asset* AssetManager::openInLocaleVendorLocked(const char* fileName, AccessMode m
/* look at the filesystem on disk */
String8 path(createPathNameLocked(ap, locale, vendor));
path.appendPath(fileName);
-
+
String8 excludeName(path);
excludeName.append(kExcludeExtension);
if (::getFileType(excludeName.string()) != kFileTypeNonexistent) {
@@ -911,28 +944,28 @@ Asset* AssetManager::openInLocaleVendorLocked(const char* fileName, AccessMode m
//printf("+++ excluding '%s'\n", (const char*) excludeName);
return kExcludedAsset;
}
-
+
pAsset = openAssetFromFileLocked(path, mode);
-
+
if (pAsset == NULL) {
/* try again, this time with ".gz" */
path.append(".gz");
pAsset = openAssetFromFileLocked(path, mode);
}
-
+
if (pAsset != NULL)
pAsset->setAssetSource(path);
} else {
/* find in cache */
String8 path(createPathNameLocked(ap, locale, vendor));
path.appendPath(fileName);
-
+
AssetDir::FileInfo tmpInfo;
bool found = false;
-
+
String8 excludeName(path);
excludeName.append(kExcludeExtension);
-
+
if (mCache.indexOf(excludeName) != NAME_NOT_FOUND) {
/* go no farther */
//printf("+++ Excluding '%s'\n", (const char*) excludeName);
@@ -1756,7 +1789,7 @@ bool AssetManager::fncScanAndMergeDirLocked(
// XXX This is broken -- the filename cache needs to hold the base
// asset path separately from its filename.
-
+
partialPath = createPathNameLocked(ap, locale, vendor);
if (dirName[0] != '\0') {
partialPath.appendPath(dirName);