Skip to content

Commit

Permalink
base: Fix the problems for runtime overlay.
Browse files Browse the repository at this point in the history
 - There is no need to make the string blocking when adding the asset path,
   as it will be made by the resources.
 - After adding the overlay path, it also needs to update the string blocks.
 - Scan all the sub folders for framework overlay res.

Change-Id: Iaad019111ae364c319e58dce57dbf4647b38d4c3
  • Loading branch information
yingying authored and rmcc committed Nov 9, 2014
1 parent 15348fc commit b97528c
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 57 deletions.
99 changes: 60 additions & 39 deletions cmds/idmap/scan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,62 @@ namespace {
dataMap->release();
return priority;
}

int idmap_scan(const char *overlay_dir, const char *target_package_name,
const char *target_apk_path, const char *idmap_dir,
SortedVector<Overlay>& overlayVector)
{
DIR *dir = opendir(overlay_dir);
if (dir == NULL) {
return EXIT_FAILURE;
}

struct dirent *dirent;
while ((dirent = readdir(dir)) != NULL) {
struct stat st;
char overlay_apk_path[PATH_MAX + 1];
snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
if (stat(overlay_apk_path, &st) < 0) {
continue;
}
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
continue;
}

if (S_ISDIR(st.st_mode)) {
String8 dir_name = String8(overlay_apk_path).getPathLeaf();
if (dir_name == "." || dir_name == "..") {
// Skip the "." and ".." dir.
continue;
}
idmap_scan(overlay_apk_path, target_package_name, target_apk_path, idmap_dir,
overlayVector);
} else {
int priority = parse_apk(overlay_apk_path, target_package_name);
if (priority < 0) {
continue;
}

String8 idmap_path(idmap_dir);
idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
idmap_path.append("@idmap");

if (idmap_create_path(target_apk_path, overlay_apk_path,
idmap_path.string()) != 0) {
ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
target_apk_path, overlay_apk_path, idmap_path.string());
continue;
}

Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
overlayVector.add(overlay);
}
}

closedir(dir);

return EXIT_SUCCESS;
}
}

int idmap_scan(const char *overlay_dir, const char *target_package_name,
Expand All @@ -198,48 +254,13 @@ int idmap_scan(const char *overlay_dir, const char *target_package_name,
return EXIT_FAILURE;
}

DIR *dir = opendir(overlay_dir);
if (dir == NULL) {
return EXIT_FAILURE;
}

SortedVector<Overlay> overlayVector;
struct dirent *dirent;
while ((dirent = readdir(dir)) != NULL) {
struct stat st;
char overlay_apk_path[PATH_MAX + 1];
snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
if (stat(overlay_apk_path, &st) < 0) {
continue;
}
if (!S_ISREG(st.st_mode)) {
continue;
}

int priority = parse_apk(overlay_apk_path, target_package_name);
if (priority < 0) {
continue;
}

String8 idmap_path(idmap_dir);
idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
idmap_path.append("@idmap");

if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) {
ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
target_apk_path, overlay_apk_path, idmap_path.string());
continue;
}

Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
overlayVector.add(overlay);
}

closedir(dir);
int res = idmap_scan(overlay_dir, target_package_name, target_apk_path, idmap_dir,
overlayVector);

if (!writePackagesList(filename.string(), overlayVector)) {
if (res == EXIT_FAILURE || !writePackagesList(filename.string(), overlayVector)) {
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
return res;
}
16 changes: 14 additions & 2 deletions core/java/android/content/res/AssetManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,9 @@ protected void finalize() throws Throwable
public final int addAssetPath(String path) {
synchronized (this) {
int res = addAssetPathNative(path);
makeStringBlocks(mStringBlocks);
if (mStringBlocks != null) {
makeStringBlocks(mStringBlocks);
}
return res;
}
}
Expand All @@ -627,7 +629,17 @@ public final int addAssetPath(String path) {
*
* {@hide}
*/
public native final int addOverlayPath(String idmapPath);
public final int addOverlayPath(String idmapPath) {
synchronized (this) {
int res = addOverlayPathNative(idmapPath);
if (mStringBlocks != null) {
makeStringBlocks(mStringBlocks);
}
return res;
}
}

private native final int addOverlayPathNative(String idmapPath);

/**
* Add multiple sets of assets to the asset manager at once. See
Expand Down
2 changes: 1 addition & 1 deletion core/jni/android_util_AssetManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2001,7 +2001,7 @@ static JNINativeMethod gAssetManagerMethods[] = {
(void*) android_content_AssetManager_getAssetRemainingLength },
{ "addAssetPathNative", "(Ljava/lang/String;)I",
(void*) android_content_AssetManager_addAssetPath },
{ "addOverlayPath", "(Ljava/lang/String;)I",
{ "addOverlayPathNative", "(Ljava/lang/String;)I",
(void*) android_content_AssetManager_addOverlayPath },
{ "isUpToDate", "()Z",
(void*) android_content_AssetManager_isUpToDate },
Expand Down
2 changes: 1 addition & 1 deletion include/androidfw/AssetManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ class AssetManager : public AAssetManager {
const ResTable* getResTable(bool required = true) const;
void setLocaleLocked(const char* locale);
void updateResourceParamsLocked() const;
bool appendPathToResTable(const asset_path& ap) const;
bool appendPathToResTable(const asset_path& ap, size_t* entryIdx) const;

Asset* openIdmapLocked(const struct asset_path& ap) const;

Expand Down
33 changes: 19 additions & 14 deletions libs/androidfw/AssetManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ bool AssetManager::addAssetPath(const String8& path, int32_t* cookie)

mAssetPaths.add(ap);

if (mResources != NULL) {
size_t index = mAssetPaths.size() - 1;
appendPathToResTable(ap, &index);
}

// new paths are always added at the end
if (cookie) {
*cookie = static_cast<int32_t>(mAssetPaths.size());
Expand All @@ -231,10 +236,6 @@ bool AssetManager::addAssetPath(const String8& path, int32_t* cookie)
}
#endif

if (mResources != NULL) {
appendPathToResTable(ap);
}

return true;
}

Expand Down Expand Up @@ -296,6 +297,11 @@ bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie)
mAssetPaths.add(oap);
*cookie = static_cast<int32_t>(mAssetPaths.size());

if (mResources != NULL) {
size_t index = mAssetPaths.size() - 1;
appendPathToResTable(oap, &index);
}

return true;
}

Expand Down Expand Up @@ -600,24 +606,23 @@ FileType AssetManager::getFileType(const char* fileName)
return kFileTypeRegular;
}

bool AssetManager::appendPathToResTable(const asset_path& ap) const {
bool AssetManager::appendPathToResTable(const asset_path& ap, size_t* entryIdx) 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) {
if (*entryIdx == 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();
*entryIdx += sharedRes->getTableCount() - 1;
}
}
if (sharedRes == NULL) {
Expand All @@ -635,20 +640,20 @@ bool AssetManager::appendPathToResTable(const asset_path& ap) const {
}
}

if (nextEntryIdx == 0 && ass != NULL) {
if (*entryIdx == 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);
sharedRes->add(ass, idmap, *entryIdx + 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);
addSystemOverlays(overlaysListPath.string(), ap.path, sharedRes, *entryIdx);
#endif
sharedRes = const_cast<AssetManager*>(this)->
mZipSet.setZipResourceTable(ap.path, sharedRes);
Expand All @@ -670,7 +675,7 @@ bool AssetManager::appendPathToResTable(const asset_path& ap) const {
mResources->add(sharedRes);
} else {
ALOGV("Parsing resources for %s", ap.path.string());
mResources->add(ass, idmap, nextEntryIdx + 1, !shared);
mResources->add(ass, idmap, *entryIdx + 1, !shared);
}
onlyEmptyResources = false;

Expand All @@ -679,7 +684,7 @@ bool AssetManager::appendPathToResTable(const asset_path& ap) const {
}
} else {
ALOGV("Installing empty resources in to table %p\n", mResources);
mResources->addEmpty(nextEntryIdx + 1);
mResources->addEmpty(*entryIdx + 1);
}

if (idmap != NULL) {
Expand Down Expand Up @@ -719,7 +724,7 @@ const ResTable* AssetManager::getResTable(bool required) const
bool onlyEmptyResources = true;
const size_t N = mAssetPaths.size();
for (size_t i=0; i<N; i++) {
bool empty = appendPathToResTable(mAssetPaths.itemAt(i));
bool empty = appendPathToResTable(mAssetPaths.itemAt(i), &i);
onlyEmptyResources = onlyEmptyResources && empty;
}

Expand Down

0 comments on commit b97528c

Please sign in to comment.