summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/idmap/create.cpp25
-rw-r--r--cmds/idmap/idmap.cpp22
-rw-r--r--cmds/idmap/idmap.h4
-rw-r--r--cmds/idmap/scan.cpp3
-rw-r--r--core/java/android/app/ResourcesManager.java15
-rw-r--r--core/java/android/content/pm/ThemeUtils.java83
-rw-r--r--core/java/android/content/res/AssetManager.java15
-rw-r--r--core/jni/android_util_AssetManager.cpp16
-rw-r--r--include/androidfw/AssetManager.h6
-rw-r--r--libs/androidfw/AssetManager.cpp99
-rw-r--r--services/core/java/com/android/server/ThemeService.java2
-rw-r--r--services/core/java/com/android/server/pm/Installer.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java74
-rw-r--r--tests/ThemesTest/src/com/example/themetests/MainActivity.java4
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";