diff options
-rw-r--r-- | cmds/idmap/create.cpp | 25 | ||||
-rw-r--r-- | cmds/idmap/idmap.cpp | 22 | ||||
-rw-r--r-- | cmds/idmap/idmap.h | 4 | ||||
-rw-r--r-- | cmds/idmap/scan.cpp | 3 | ||||
-rw-r--r-- | core/java/android/app/ResourcesManager.java | 15 | ||||
-rw-r--r-- | core/java/android/content/pm/ThemeUtils.java | 83 | ||||
-rw-r--r-- | core/java/android/content/res/AssetManager.java | 15 | ||||
-rw-r--r-- | core/jni/android_util_AssetManager.cpp | 16 | ||||
-rw-r--r-- | include/androidfw/AssetManager.h | 6 | ||||
-rw-r--r-- | libs/androidfw/AssetManager.cpp | 99 | ||||
-rw-r--r-- | services/core/java/com/android/server/ThemeService.java | 2 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/Installer.java | 6 | ||||
-rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 74 | ||||
-rw-r--r-- | tests/ThemesTest/src/com/example/themetests/MainActivity.java | 4 |
14 files changed, 156 insertions, 218 deletions
diff --git a/cmds/idmap/create.cpp b/cmds/idmap/create.cpp index 8c07eb0..f706533 100644 --- a/cmds/idmap/create.cpp +++ b/cmds/idmap/create.cpp @@ -153,7 +153,8 @@ fail: } int create_idmap(const char *target_apk_path, const char *overlay_apk_path, - uint32_t target_hash, uint32_t overlay_hash, uint32_t **data, size_t *size) + const char *cache_path, uint32_t target_hash, uint32_t overlay_hash, uint32_t **data, + size_t *size) { uint32_t target_crc, overlay_crc; @@ -164,13 +165,14 @@ fail: overlay_crc = 0; AssetManager am; - bool b = am.createIdmap(target_apk_path, overlay_apk_path, target_crc, overlay_crc, - target_hash, overlay_hash, data, size); + bool b = am.createIdmap(target_apk_path, overlay_apk_path, cache_path, target_crc, + overlay_crc, target_hash, overlay_hash, data, size); return b ? 0 : -1; } int create_and_write_idmap(const char *target_apk_path, const char *overlay_apk_path, - uint32_t target_hash, uint32_t overlay_hash, int fd, bool check_if_stale) + const char *cache_path, uint32_t target_hash, uint32_t overlay_hash, int fd, + bool check_if_stale) { if (check_if_stale) { if (!is_idmap_stale_fd(target_apk_path, overlay_apk_path, fd)) { @@ -182,7 +184,7 @@ fail: uint32_t *data = NULL; size_t size; - if (create_idmap(target_apk_path, overlay_apk_path, target_hash, overlay_hash, + if (create_idmap(target_apk_path, overlay_apk_path, cache_path, target_hash, overlay_hash, &data, &size) == -1) { return -1; } @@ -198,7 +200,7 @@ fail: } int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path, - uint32_t target_hash, uint32_t overlay_hash, + const char *cache_path, uint32_t target_hash, uint32_t overlay_hash, const char *idmap_path) { if (!is_idmap_stale_path(target_apk_path, overlay_apk_path, idmap_path)) { @@ -211,8 +213,8 @@ int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path, return EXIT_FAILURE; } - int r = create_and_write_idmap(target_apk_path, overlay_apk_path, target_hash, overlay_hash, - fd, false); + int r = create_and_write_idmap(target_apk_path, overlay_apk_path, cache_path, + target_hash, overlay_hash, fd, false); close(fd); if (r != 0) { unlink(idmap_path); @@ -221,10 +223,9 @@ int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path, } int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, - uint32_t target_hash, uint32_t overlay_hash, - int fd) + const char *cache_path, uint32_t target_hash, uint32_t overlay_hash, int fd) { - return create_and_write_idmap(target_apk_path, overlay_apk_path, target_hash, overlay_hash, - fd, true) == 0 ? + return create_and_write_idmap(target_apk_path, overlay_apk_path, cache_path, target_hash, + overlay_hash, fd, true) == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/cmds/idmap/idmap.cpp b/cmds/idmap/idmap.cpp index 607cfd3..cc3f231 100644 --- a/cmds/idmap/idmap.cpp +++ b/cmds/idmap/idmap.cpp @@ -122,7 +122,8 @@ NOTES \n\ } int maybe_create_fd(const char *target_apk_path, const char *overlay_apk_path, - const char *idmap_str, const char *target_hash_str, const char *overlay_hash_str) + const char *cache_path, const char *idmap_str, const char *target_hash_str, + const char *overlay_hash_str) { // anyone (not just root or system) may do --fd -- the file has // already been opened by someone else on our behalf @@ -146,12 +147,13 @@ NOTES \n\ int target_hash = strtol(target_hash_str, 0, 10); int overlay_hash = strtol(overlay_hash_str, 0, 10); - return idmap_create_fd(target_apk_path, overlay_apk_path, target_hash, overlay_hash, - idmap_fd); + return idmap_create_fd(target_apk_path, overlay_apk_path, cache_path, target_hash, + overlay_hash, idmap_fd); } int maybe_create_path(const char *target_apk_path, const char *overlay_apk_path, - const char *idmap_path, const char *target_hash_str, const char *overlay_hash_str) + const char *cache_path, const char *idmap_path, const char *target_hash_str, + const char *overlay_hash_str) { if (!verify_root_or_system()) { fprintf(stderr, "error: permission denied: not user root or user system\n"); @@ -170,8 +172,8 @@ NOTES \n\ int target_hash = strtol(target_hash_str, 0, 10); int overlay_hash = strtol(overlay_hash_str, 0, 10); - return idmap_create_path(target_apk_path, overlay_apk_path, target_hash, overlay_hash, - idmap_path); + return idmap_create_path(target_apk_path, overlay_apk_path, cache_path, target_hash, + overlay_hash, idmap_path); } int maybe_scan(const char *overlay_dir, const char *target_package_name, @@ -230,12 +232,12 @@ int main(int argc, char **argv) return 0; } - if (argc == 7 && !strcmp(argv[1], "--fd")) { - return maybe_create_fd(argv[2], argv[3], argv[4], argv[5], argv[6]); + if (argc == 8 && !strcmp(argv[1], "--fd")) { + return maybe_create_fd(argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); } - if (argc == 7 && !strcmp(argv[1], "--path")) { - return maybe_create_path(argv[2], argv[3], argv[4], argv[5], argv[6]); + if (argc == 8 && !strcmp(argv[1], "--path")) { + return maybe_create_path(argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); } if (argc == 6 && !strcmp(argv[1], "--scan")) { diff --git a/cmds/idmap/idmap.h b/cmds/idmap/idmap.h index 1794db7..6a9c5ef 100644 --- a/cmds/idmap/idmap.h +++ b/cmds/idmap/idmap.h @@ -19,11 +19,11 @@ #endif int idmap_create_path(const char *target_apk_path, const char *overlay_apk_path, - uint32_t target_hash, uint32_t overlay_hash, + const char *cache_path, uint32_t target_hash, uint32_t overlay_hash, const char *idmap_path); int idmap_create_fd(const char *target_apk_path, const char *overlay_apk_path, - uint32_t target_hash, uint32_t overlay_hash, + const char *cache_path, uint32_t target_hash, uint32_t overlay_hash, int fd); // Regarding target_package_name: the idmap_scan implementation should diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp index 62ad6a9..34118e6 100644 --- a/cmds/idmap/scan.cpp +++ b/cmds/idmap/scan.cpp @@ -203,7 +203,8 @@ int idmap_scan(const char *overlay_dir, const char *target_package_name, idmap_path.appendPath(flatten_path(overlay_apk_path + 1)); idmap_path.append("@idmap"); - if (idmap_create_path(target_apk_path, overlay_apk_path, 0, 0, idmap_path.string()) != 0) { + if (idmap_create_path(target_apk_path, overlay_apk_path, NULL, 0, 0, + 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; diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index e78ccba..31a8e39 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -228,7 +228,7 @@ public class ResourcesManager { if (overlayDirs != null) { for (String idmapPath : overlayDirs) { - assets.addOverlayPath(idmapPath, null, null, null); + assets.addOverlayPath(idmapPath, null, null, null, null); } } @@ -579,9 +579,10 @@ public class ResourcesManager { String targetPackagePath = piTarget.applicationInfo.sourceDir; String prefixPath = ThemeUtils.getOverlayPathToTarget(basePackageName); - String resCachePath = ThemeUtils.getResDir(basePackageName, piTheme); + String resCachePath = ThemeUtils.getTargetCacheDir(piTarget.packageName, piTheme); String resApkPath = resCachePath + "/resources.apk"; - int cookie = assets.addOverlayPath(themePath, resApkPath, + String idmapPath = ThemeUtils.getIdmapPath(piTarget.packageName, piTheme.packageName); + int cookie = assets.addOverlayPath(idmapPath, themePath, resApkPath, targetPackagePath, prefixPath); if (cookie != 0) { @@ -591,11 +592,12 @@ public class ResourcesManager { } if (!piTarget.isThemeApk && piTheme.mOverlayTargets.contains("android")) { - String resCachePath= ThemeUtils.getResDir(piAndroid.packageName, piTheme); + String resCachePath= ThemeUtils.getTargetCacheDir(piAndroid.packageName, piTheme); String prefixPath = ThemeUtils.getOverlayPathToTarget(piAndroid.packageName); String targetPackagePath = piAndroid.applicationInfo.publicSourceDir; String resApkPath = resCachePath + "/resources.apk"; - int cookie = assets.addOverlayPath(themePath, + String idmapPath = ThemeUtils.getIdmapPath("android", piTheme.packageName); + int cookie = assets.addOverlayPath(idmapPath, themePath, resApkPath, targetPackagePath, prefixPath); if (cookie != 0) { assets.setThemePackageName(themePackageName); @@ -692,7 +694,8 @@ public class ResourcesManager { if (themePackageName != null && !themePackageName.isEmpty()) { String themePath = piTheme.applicationInfo.publicSourceDir; String prefixPath = ThemeUtils.COMMON_RES_PATH; - String resCachePath = ThemeUtils.getResDir(ThemeUtils.COMMON_RES_TARGET, piTheme); + String resCachePath = + ThemeUtils.getTargetCacheDir(ThemeUtils.COMMON_RES_TARGET, piTheme); String resApkPath = resCachePath + "/resources.apk"; int cookie = assets.addCommonOverlayPath(themePath, resApkPath, prefixPath); diff --git a/core/java/android/content/pm/ThemeUtils.java b/core/java/android/content/pm/ThemeUtils.java index 7cb2216..38391d4 100644 --- a/core/java/android/content/pm/ThemeUtils.java +++ b/core/java/android/content/pm/ThemeUtils.java @@ -15,7 +15,6 @@ */ package android.content.pm; -import android.Manifest; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.ContentValues; @@ -27,7 +26,6 @@ import android.content.res.Configuration; import android.content.res.ThemeConfig; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; import android.media.RingtoneManager; import android.net.Uri; import android.os.FileUtils; @@ -73,8 +71,7 @@ public class ThemeUtils { public static final String ICONS_PATH = "assets/icons/"; public static final String COMMON_RES_PATH = "assets/overlays/common/"; public static final String FONT_XML = "fonts.xml"; - public static final String RESTABLE_EXTENSION = ".arsc"; - public static final String IDMAP_PREFIX = "/data/resource-cache/"; + public static final String RESOURCE_CACHE_DIR = "/data/resource-cache/"; public static final String IDMAP_SUFFIX = "@idmap"; public static final String COMMON_RES_SUFFIX = ".common"; public static final String COMMON_RES_TARGET = "common"; @@ -128,47 +125,40 @@ public class ThemeUtils { }; - /* - * Retrieve the path to a resource table (ie resource.arsc) - * Themes have a resources.arsc for every overlay package targeted. These are compiled - * at install time and stored in the data partition. - * + /** + * Get the root path of the resource cache for the given theme + * @param themePkgName + * @return Root resource cache path for the given theme */ - public static String getResTablePath(String targetPkgName, PackageInfo overlayPkg) { - return getResTablePath(targetPkgName, overlayPkg.applicationInfo.publicSourceDir); + public static String getOverlayResourceCacheDir(String themePkgName) { + return RESOURCE_CACHE_DIR + themePkgName; } - public static String getResTablePath(String targetPkgName, PackageParser.Package overlayPkg) { - return getResTablePath(targetPkgName, overlayPkg.applicationInfo.publicSourceDir); - } - - public static String getResTablePath(String targetPkgName, String overlayApkPath) { - String restablePath = getResDir(targetPkgName, overlayApkPath) + "/resources.arsc"; - return restablePath; - } - - /* - * Retrieve the path to the directory where resource table (ie resource.arsc) resides - * Themes have a resources.arsc for every overlay package targeted. These are compiled - * at install time and stored in the data partition. - * + /** + * Get the path of the resource cache for the given target and theme + * @param targetPkgName + * @param themePkg + * @return Path to the resource cache for this target and theme */ - public static String getResDir(String targetPkgName, PackageInfo overlayPkg) { - return getResDir(targetPkgName, overlayPkg.applicationInfo.publicSourceDir); + public static String getTargetCacheDir(String targetPkgName, PackageInfo themePkg) { + return getTargetCacheDir(targetPkgName, themePkg.packageName); } - public static String getResDir(String targetPkgName, PackageParser.Package overlayPkg) { - return getResDir(targetPkgName, overlayPkg.applicationInfo.publicSourceDir); + public static String getTargetCacheDir(String targetPkgName, PackageParser.Package themePkg) { + return getTargetCacheDir(targetPkgName, themePkg.packageName); } - public static String getResDir(String targetPkgName, String overlayApkPath) { - String restableName = overlayApkPath.replaceAll("/", "@") + "@" + targetPkgName; - if (restableName.startsWith("@")) restableName = restableName.substring(1); - return IDMAP_PREFIX + restableName; + public static String getTargetCacheDir(String targetPkgName, String themePkgName) { + return getOverlayResourceCacheDir(themePkgName) + File.separator + targetPkgName; } + /** + * Get the path to the icons for the given theme + * @param pkgName + * @return + */ public static String getIconPackDir(String pkgName) { - return IDMAP_PREFIX + pkgName; + return getOverlayResourceCacheDir(pkgName) + File.separator + "icons"; } public static String getIconHashFile(String pkgName) { @@ -183,6 +173,10 @@ public class ThemeUtils { return getIconPackDir(pkgName) + "/resources.arsc"; } + public static String getIdmapPath(String targetPkgName, String overlayPkgName) { + return getTargetCacheDir(targetPkgName, overlayPkgName) + File.separator + "idmap"; + } + public static String getOverlayPathToTarget(String targetPkgName) { StringBuilder sb = new StringBuilder(); sb.append(OVERLAY_PATH); @@ -198,7 +192,7 @@ public class ThemeUtils { } public static void createCacheDirIfNotExists() throws IOException { - File file = new File(IDMAP_PREFIX); + File file = new File(RESOURCE_CACHE_DIR); if (!file.exists() && !file.mkdir()) { throw new IOException("Could not create dir: " + file.toString()); } @@ -206,9 +200,10 @@ public class ThemeUtils { | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH, -1, -1); } - public static void createResourcesDirIfNotExists(String targetPkgName, String overlayApkPath) + public static void createResourcesDirIfNotExists(String targetPkgName, String overlayPkgName) throws IOException { - File file = new File(getResDir(targetPkgName, overlayApkPath)); + createDirIfNotExists(getOverlayResourceCacheDir(overlayPkgName)); + File file = new File(getTargetCacheDir(targetPkgName, overlayPkgName)); if (!file.exists() && !file.mkdir()) { throw new IOException("Could not create dir: " + file.toString()); } @@ -217,6 +212,7 @@ public class ThemeUtils { } public static void createIconDirIfNotExists(String pkgName) throws IOException { + createDirIfNotExists(getOverlayResourceCacheDir(pkgName)); File file = new File(getIconPackDir(pkgName)); if (!file.exists() && !file.mkdir()) { throw new IOException("Could not create dir: " + file.toString()); @@ -283,18 +279,7 @@ public class ThemeUtils { } public static void clearIconCache() { - deleteFilesInDir(SYSTEM_THEME_ICON_CACHE_DIR); - } - - //Note: will not delete populated subdirs - public static void deleteFilesInDir(String dirPath) { - File fontDir = new File(dirPath); - File[] files = fontDir.listFiles(); - if (files != null) { - for(File file : fontDir.listFiles()) { - file.delete(); - } - } + FileUtils.deleteContents(new File(SYSTEM_THEME_ICON_CACHE_DIR)); } public static InputStream getInputStreamFromAsset(Context ctx, String path) throws IOException { diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index f663c50..421701a 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -644,11 +644,10 @@ public final class AssetManager implements AutoCloseable { * * {@hide} */ - - public final int addOverlayPath(String idmapPath, String resApkPath, String targetPkgPath, - String prefixPath) { + public final int addOverlayPath(String idmapPath, String themeApkPath, + String resApkPath, String targetPkgPath, String prefixPath) { synchronized (this) { - int res = addOverlayPathNative(idmapPath, resApkPath, targetPkgPath, + int res = addOverlayPathNative(idmapPath, themeApkPath, resApkPath, targetPkgPath, prefixPath); makeStringBlocks(mStringBlocks); return res; @@ -660,7 +659,7 @@ public final class AssetManager implements AutoCloseable { * * {@hide} */ - private native final int addOverlayPathNative(String idmapPath, + private native final int addOverlayPathNative(String idmapPath, String themeApkPath, String resApkPath, String targetPkgPath, String prefixPath); /** @@ -668,14 +667,14 @@ public final class AssetManager implements AutoCloseable { * * {@hide} */ - public final int addCommonOverlayPath(String idmapPath, + public final int addCommonOverlayPath(String themeApkPath, String resApkPath, String prefixPath) { synchronized (this) { - return addCommonOverlayPathNative(idmapPath, resApkPath, prefixPath); + return addCommonOverlayPathNative(themeApkPath, resApkPath, prefixPath); } } - private native final int addCommonOverlayPathNative(String idmapPath, + private native final int addCommonOverlayPathNative(String themeApkPath, String resApkPath, String prefixPath); /** diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index 326e57d..af9d006 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -520,10 +520,16 @@ static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz } static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz, + jstring idmapPath, jstring packagePath, jstring resApkPath, jstring targetPkgPath, jstring prefixPath) { + ScopedUtfChars idmapPath8(env, idmapPath); + if (idmapPath8.c_str() == NULL) { + return 0; + } + ScopedUtfChars packagePath8(env, packagePath); if (packagePath8.c_str() == NULL) { return 0; @@ -550,9 +556,13 @@ static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject cla } int32_t cookie; - bool res = am->addOverlayPath(String8(packagePath8.c_str()), &cookie, + bool res = am->addOverlayPath( + String8(idmapPath8.c_str()), + String8(packagePath8.c_str()), + &cookie, String8(resApkPath8.c_str()), - String8(targetPkgPath8.c_str()), String8(prefixPath8.c_str())); + String8(targetPkgPath8.c_str()), + String8(prefixPath8.c_str())); return (res) ? (jint)cookie : 0; } @@ -2229,7 +2239,7 @@ static JNINativeMethod gAssetManagerMethods[] = { (void*) android_content_AssetManager_getAssetRemainingLength }, { "addAssetPathNative", "(Ljava/lang/String;)I", (void*) android_content_AssetManager_addAssetPath }, - { "addOverlayPathNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", + { "addOverlayPathNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", (void*) android_content_AssetManager_addOverlayPath }, { "addCommonOverlayPathNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", (void*) android_content_AssetManager_addCommonOverlayPath }, diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h index 81b15bc..0fbf766 100644 --- a/include/androidfw/AssetManager.h +++ b/include/androidfw/AssetManager.h @@ -101,7 +101,7 @@ public: * newly-added asset source. */ bool addAssetPath(const String8& path, int32_t* cookie); - bool addOverlayPath(const String8& path, int32_t* cookie, + bool addOverlayPath(const String8& idmapPath, const String8& overlayApkpath, int32_t* cookie, const String8& resApkPath, const String8& targetPkgPath, const String8& prefixPath); bool addCommonOverlayPath(const String8& path, int32_t* cookie, @@ -238,7 +238,7 @@ public: * Generate idmap data to translate resources IDs between a package and a * corresponding overlay package. */ - bool createIdmap(const char* targetApkPath, const char* overlayApkPath, + bool createIdmap(const char* targetApkPath, const char* overlayApkPath, const char* cache_path, uint32_t targetCrc, uint32_t overlayCrc, time_t targetMtime, time_t overlayMtime, uint32_t** outData, size_t* outSize); @@ -309,7 +309,7 @@ private: String8 getPkgName(const char *apkPath); - String8 getOverlayResPath(const char* targetApkPath, const char* overlayApkPath); + String8 getOverlayResPath(const char* cachePath); class SharedZip : public RefBase { public: diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp index 413ae53..370aaa2 100644 --- a/libs/androidfw/AssetManager.cpp +++ b/libs/androidfw/AssetManager.cpp @@ -77,10 +77,13 @@ static const char* kAssetsRoot = "assets"; static const char* kAppZipName = NULL; //"classes.jar"; static const char* kSystemAssets = "framework/framework-res.apk"; static const char* kCMSDKAssets = "framework/org.cyanogenmod.platform-res.apk"; -static const char* kResourceCache = "resource-cache"; static const char* kAndroidManifest = "AndroidManifest.xml"; static const int kComposedIconAsset = 128; +#ifdef HAVE_ANDROID_OS +static const char* kResourceCache = "resource-cache"; +#endif + static const char* kExcludeExtension = ".EXCLUDE"; static Asset* const kExcludedAsset = (Asset*) 0xd000000d; @@ -96,49 +99,6 @@ const char* AssetManager::IDMAP_DIR = "/data/resource-cache"; const char* AssetManager::APK_EXTENSION = ".apk"; namespace { - String8 idmapPathForPackagePath(const String8& pkgPath, const String8& targetPkgPath) - { - const char* root = getenv("ANDROID_DATA"); - LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set"); - String8 path(root); - path.appendPath(kResourceCache); - - char buf[256]; // 256 chars should be enough for anyone... - strncpy(buf, targetPkgPath.string(), 255); - buf[255] = '\0'; - char* filename = buf; - while (*filename && *filename == '/') { - ++filename; - } - char* p = filename; - while (*p) { - if (*p == '/') { - *p = '@'; - } - ++p; - } - path.appendPath(filename); - path.append("@"); - - strncpy(buf, pkgPath.string(), 255); - buf[255] = '\0'; - filename = buf; - while (*filename && *filename == '/') { - ++filename; - } - p = filename; - while (*p) { - if (*p == '/') { - *p = '@'; - } - ++p; - } - path.append(filename); - path.append("@idmap"); - - return path; - } - /* * Like strdup(), but uses C++ "new" operator instead of malloc. */ @@ -156,13 +116,6 @@ namespace { return newStr; } - - static String8 flatten_path(const char *path) - { - String16 tmp(path); - tmp.replaceAll('/', '@'); - return String8(tmp); - } } /* @@ -289,16 +242,14 @@ bool AssetManager::addAssetPath(const String8& path, int32_t* cookie) * Our resources.arsc will reference foo.png's path as "res/drawable/foo.png" * so we need "assets/com.android.launcher/" as a prefix */ -bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie, - const String8& resApkPath, const String8& targetPkgPath, +bool AssetManager::addOverlayPath(const String8& idmapPath, const String8& overlayPackagePath, + int32_t* cookie, const String8& resApkPath, const String8& targetPkgPath, const String8& prefixPath) { - const String8 idmapPath = idmapPathForPackagePath(packagePath, targetPkgPath); - AutoMutex _l(mLock); - ALOGV("package path: %s, idmap Path: %s, resApkPath %s, targetPkgPath: %s", - packagePath.string(), idmapPath.string(), + ALOGV("overlayApkPath: %s, idmap Path: %s, resApkPath %s, targetPkgPath: %s", + overlayPackagePath.string(), idmapPath.string(), resApkPath.string(), targetPkgPath.string()); @@ -325,9 +276,9 @@ bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie, } delete idmap; - if (overlayPath != packagePath) { + if (overlayPath != overlayPackagePath) { ALOGW("idmap file %s inconcistent: expected path %s does not match actual path %s\n", - idmapPath.string(), packagePath.string(), overlayPath.string()); + idmapPath.string(), overlayPackagePath.string(), overlayPath.string()); return false; } if (access(targetPath.string(), R_OK) != 0) { @@ -363,25 +314,25 @@ bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie, return true; } -bool AssetManager::addCommonOverlayPath(const String8& packagePath, int32_t* cookie, +bool AssetManager::addCommonOverlayPath(const String8& themePackagePath, int32_t* cookie, const String8& resApkPath, const String8& prefixPath) { AutoMutex _l(mLock); - ALOGV("targetApkPath: %s, resApkPath %s, prefixPath %s", - packagePath.string(), resApkPath.string(), prefixPath.string()); + ALOGV("themePackagePath: %s, resApkPath %s, prefixPath %s", + themePackagePath.string(), resApkPath.string(), prefixPath.string()); // Skip if we have it already. for (size_t i = 0; i < mAssetPaths.size(); ++i) { - if (mAssetPaths[i].path == packagePath && mAssetPaths[i].resApkPath == resApkPath) { + if (mAssetPaths[i].path == themePackagePath && mAssetPaths[i].resApkPath == resApkPath) { *cookie = static_cast<int32_t>(i + 1); return true; } } asset_path oap; - oap.path = packagePath; - oap.type = ::getFileType(packagePath.string()); + oap.path = themePackagePath; + oap.type = ::getFileType(themePackagePath.string()); oap.resApkPath = resApkPath; oap.prefixPath = prefixPath; mAssetPaths.add(oap); @@ -492,19 +443,9 @@ String8 AssetManager::getBasePackageName(uint32_t index) return mBasePackageName; } -String8 AssetManager::getOverlayResPath(const char* targetApkPath, const char* overlayApkPath) +String8 AssetManager::getOverlayResPath(const char* cachePath) { - //Remove leading '/' - if (strlen(overlayApkPath) >= 2 && *overlayApkPath == '/') { - overlayApkPath++; - } - String8 overlayApkPathFlat = flatten_path(overlayApkPath); - String8 targetPkgName = getPkgName(targetApkPath); - - String8 resPath(AssetManager::IDMAP_DIR); - resPath.appendPath(overlayApkPathFlat); - resPath.append("@"); - resPath.append(targetPkgName); + String8 resPath(cachePath); resPath.append("/"); resPath.append("resources"); resPath.append(AssetManager::APK_EXTENSION); @@ -512,7 +453,7 @@ String8 AssetManager::getOverlayResPath(const char* targetApkPath, const char* o } bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApkPath, - uint32_t targetCrc, uint32_t overlayCrc, + const char *cache_path, uint32_t targetCrc, uint32_t overlayCrc, time_t targetMtime, time_t overlayMtime, uint32_t** outData, size_t* outSize) { @@ -521,7 +462,7 @@ bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApk ResTable tables[2]; //Our overlay APK might use an external restable - String8 resPath = getOverlayResPath(targetApkPath, overlayApkPath); + String8 resPath = getOverlayResPath(cache_path); for (int i = 0; i < 2; ++i) { asset_path ap; diff --git a/services/core/java/com/android/server/ThemeService.java b/services/core/java/com/android/server/ThemeService.java index 81d62d7..a53c063 100644 --- a/services/core/java/com/android/server/ThemeService.java +++ b/services/core/java/com/android/server/ThemeService.java @@ -500,7 +500,7 @@ public class ThemeService extends IThemeService.Stub { private boolean updateFonts(String pkgName) { //Clear the font dir - ThemeUtils.deleteFilesInDir(ThemeUtils.SYSTEM_THEME_FONT_PATH); + FileUtils.deleteContents(new File(ThemeUtils.SYSTEM_THEME_FONT_PATH)); if (!pkgName.equals(SYSTEM_DEFAULT)) { //Get Font Assets diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 8f12cf2..dba38a3 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -97,14 +97,16 @@ public final class Installer extends SystemService { debuggable, outputPath); } - public int idmap(String targetApkPath, String overlayApkPath, int uid, - int targetHash, int overlayHash) { + public int idmap(String targetApkPath, String overlayApkPath, String cachePath, + int uid, int targetHash, int overlayHash) { StringBuilder builder = new StringBuilder("idmap"); builder.append(' '); builder.append(targetApkPath); builder.append(' '); builder.append(overlayApkPath); builder.append(' '); + builder.append(cachePath); + builder.append(' '); builder.append(uid); builder.append(' '); builder.append(targetHash); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 3c3effb..8830b01 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -441,8 +441,6 @@ public class PackageManagerService extends IPackageManager.Stub { } final ServiceThread mHandlerThread; - private static final String IDMAP_PREFIX = "/data/resource-cache/"; - private static final String IDMAP_SUFFIX = "@idmap"; //Where overlays are be found in a theme APK private static final String APK_PATH_TO_OVERLAY = "assets/overlays/"; @@ -451,7 +449,6 @@ public class PackageManagerService extends IPackageManager.Stub { private static final String APK_PATH_TO_ICONS = "assets/icons/"; private static final String COMMON_OVERLAY = ThemeUtils.COMMON_RES_TARGET; - private static final String APK_PATH_TO_COMMON_OVERLAY = APK_PATH_TO_OVERLAY + COMMON_OVERLAY; private static final long PACKAGE_HASH_EXPIRATION = 3*60*1000; // 3 minutes private static final long COMMON_RESOURCE_EXPIRATION = 3*60*1000; // 3 minutes @@ -1928,6 +1925,8 @@ public class PackageManagerService extends IPackageManager.Stub { getDefaultDisplayMetrics(context, mMetrics); + removeLegacyResourceCache(); + SystemConfig systemConfig = SystemConfig.getInstance(); mGlobalGids = systemConfig.getGlobalGids(); mSystemPermissions = systemConfig.getSystemPermissions(); @@ -5703,7 +5702,9 @@ public class PackageManagerService extends IPackageManager.Stub { return false; } final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); - if (mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, sharedGid, + final String cachePath = + ThemeUtils.getTargetCacheDir(pkg.packageName, opkg.packageName); + if (mInstaller.idmap(pkg.baseCodePath, opkg.baseCodePath, cachePath, sharedGid, getPackageHashCode(pkg), getPackageHashCode(opkg)) != 0) { Slog.e(TAG, "Failed to generate idmap for " + pkg.baseCodePath + " and " + opkg.baseCodePath); @@ -8044,14 +8045,12 @@ public class PackageManagerService extends IPackageManager.Stub { if (hasCommonResources(pkg) && shouldCompileCommonResources(pkg)) { - ThemeUtils.createResourcesDirIfNotExists(COMMON_OVERLAY, - pkg.applicationInfo.publicSourceDir); + ThemeUtils.createResourcesDirIfNotExists(COMMON_OVERLAY, pkg.packageName); compileResources(COMMON_OVERLAY, pkg); mAvailableCommonResources.put(pkg.packageName, System.currentTimeMillis()); } - ThemeUtils.createResourcesDirIfNotExists(target, - pkg.applicationInfo.publicSourceDir); + ThemeUtils.createResourcesDirIfNotExists(target, pkg.packageName); compileResources(target, pkg); } @@ -8131,7 +8130,7 @@ public class PackageManagerService extends IPackageManager.Stub { private void compileResourcesWithAapt(String target, PackageParser.Package pkg) throws Exception { String internalPath = APK_PATH_TO_OVERLAY + target; - String resPath = ThemeUtils.getResDir(target, pkg); + String resPath = ThemeUtils.getTargetCacheDir(target, pkg); final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); int pkgId; if ("android".equals(target)) { @@ -8145,7 +8144,7 @@ public class PackageManagerService extends IPackageManager.Stub { boolean hasCommonResources = (hasCommonResources(pkg) && !COMMON_OVERLAY.equals(target)); if (mInstaller.aapt(pkg.baseCodePath, internalPath, resPath, sharedGid, pkgId, pkg.applicationInfo.targetSdkVersion, - hasCommonResources ? ThemeUtils.getResDir(COMMON_OVERLAY, pkg) + hasCommonResources ? ThemeUtils.getTargetCacheDir(COMMON_OVERLAY, pkg) + File.separator + "resources.apk" : "") != 0) { throw new AaptException("Failed to run aapt"); } @@ -8173,21 +8172,10 @@ public class PackageManagerService extends IPackageManager.Stub { mOverlays.remove(target); } } - - PackageParser.Package targetPkg = mPackages.get(target); - if (targetPkg != null) { - String idmapPath = getIdmapPath(targetPkg, opkg); - new File(idmapPath).delete(); - } - - // recursively delete the cached resource directory - String resPath = ThemeUtils.getResDir(target, opkg); - recursiveDelete(new File(resPath)); } - // Cleanup icons - String iconResources = ThemeUtils.getIconPackDir(opkg.packageName); - recursiveDelete(new File(iconResources)); + // Now simply delete the root overlay cache directory and all its contents + recursiveDelete(new File(ThemeUtils.getOverlayResourceCacheDir(opkg.packageName))); } private void uninstallThemeForApp(PackageParser.Package appPkg) { @@ -8195,8 +8183,8 @@ public class PackageManagerService extends IPackageManager.Stub { if (map == null) return; for(PackageParser.Package opkg : map.values()) { - String idmapPath = getIdmapPath(appPkg, opkg); - new File(idmapPath).delete(); + String cachePath = ThemeUtils.getTargetCacheDir(appPkg.packageName, opkg.packageName); + recursiveDelete(new File(cachePath)); } } @@ -8234,20 +8222,6 @@ public class PackageManagerService extends IPackageManager.Stub { resFile.delete(); } - private String getIdmapPath(PackageParser.Package targetPkg, PackageParser.Package overlayPkg) { - String targetPathFlat = targetPkg.baseCodePath.replaceAll("/", "@"); - if (targetPathFlat.startsWith("@")) targetPathFlat = targetPathFlat.substring(1); - - String overlayPkgFlat = overlayPkg.baseCodePath.replaceAll("/", "@"); - - StringBuilder sb = new StringBuilder(); - sb.append(ThemeUtils.IDMAP_PREFIX); - sb.append(targetPathFlat); - sb.append(overlayPkgFlat); - sb.append(ThemeUtils.IDMAP_SUFFIX); - return sb.toString(); - } - /** * Checks for existance of resources.arsc in target apk, then * Compares the 32 bit hash of the target and overlay to those stored @@ -8278,7 +8252,8 @@ public class PackageManagerService extends IPackageManager.Stub { int targetHash = getPackageHashCode(targetPkg); int overlayHash = getPackageHashCode(overlayPkg); - File idmap = new File(getIdmapPath(targetPkg, overlayPkg)); + File idmap = + new File(ThemeUtils.getIdmapPath(targetPkg.packageName, overlayPkg.packageName)); if (!idmap.exists()) return true; @@ -17478,4 +17453,23 @@ public class PackageManagerService extends IPackageManager.Stub { return 0; } + + /** + * The new resource cache structure does not flatten the paths for idmaps, so this method + * checks for files that end with @idmap and assumes this indicates the older format and + * removes all files and directories from the resource cache so that it can be rebuilt + * using the new format. + */ + private static void removeLegacyResourceCache() { + File cacheDir = new File(ThemeUtils.RESOURCE_CACHE_DIR); + if (cacheDir.exists()) { + for (File f : cacheDir.listFiles()) { + if (f.getName().endsWith(ThemeUtils.IDMAP_SUFFIX)) { + Log.i(TAG, "Removing old resource cache"); + FileUtils.deleteContents(new File(ThemeUtils.RESOURCE_CACHE_DIR)); + return; + } + } + } + } } diff --git a/tests/ThemesTest/src/com/example/themetests/MainActivity.java b/tests/ThemesTest/src/com/example/themetests/MainActivity.java index 2793272..430c997 100644 --- a/tests/ThemesTest/src/com/example/themetests/MainActivity.java +++ b/tests/ThemesTest/src/com/example/themetests/MainActivity.java @@ -147,7 +147,7 @@ public class MainActivity extends Activity { String targetPackagePath = piTarget.applicationInfo.sourceDir; String prefixPath = ThemeUtils.getOverlayPathToTarget(basePackageName); - String resCachePath = ThemeUtils.getResDir(basePackageName, piTheme); + String resCachePath = ThemeUtils.getTargetCacheDir(basePackageName, piTheme); String resTablePath = resCachePath + "/resources.arsc"; String resApkPath = resCachePath + "/resources.apk"; int cookie = assets.addOverlayPath(themePath, resTablePath, resApkPath, @@ -160,7 +160,7 @@ public class MainActivity extends Activity { } if (!piTarget.isThemeApk && piTheme.mOverlayTargets.contains("android")) { - String resCachePath= ThemeUtils.getResDir(piAndroid.packageName, piTheme); + String resCachePath= ThemeUtils.getTargetCacheDir(piAndroid.packageName, piTheme); String prefixPath = ThemeUtils.getOverlayPathToTarget(piAndroid.packageName); String targetPackagePath = piAndroid.applicationInfo.publicSourceDir; String resTablePath = resCachePath + "/resources.arsc"; |