summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityThread.java101
-rw-r--r--core/java/android/content/res/AssetManager.java4
-rw-r--r--core/jni/android_util_AssetManager.cpp12
-rw-r--r--include/utils/AssetManager.h6
-rw-r--r--libs/utils/AssetManager.cpp48
5 files changed, 101 insertions, 70 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 06250fc..e0b2ba2 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -44,6 +44,7 @@ import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.ThemeInfo;
import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -235,9 +236,7 @@ public final class ActivityThread {
}
if (!TextUtils.isEmpty(config.customTheme.getThemePackageName())) {
- if (!attachThemeAssets(assets, resDir, config.customTheme)) {
- Log.e(TAG, "Failed to attach theme " + config.customTheme + " to resource '" + resDir + "'");
- }
+ attachThemeAssets(assets, config.customTheme, false);
}
}
@@ -266,23 +265,82 @@ public final class ActivityThread {
}
}
- private boolean attachThemeAssets(AssetManager assets, String resDir, CustomTheme theme) {
- PackageInfo pi = getPackageInfo(theme.getThemePackageName(), 0);
- if (pi != null) {
- String themeResDir = pi.getResDir();
- int cookie = assets.addAssetPath(themeResDir);
+ /**
+ * Attach the necessary theme asset paths and meta information to convert an
+ * AssetManager to being globally "theme-aware".
+ *
+ * @param assets
+ * @param theme
+ * @param updating If true, this AssetManager has already been accessed and
+ * special steps must be taken to update the underlying resource
+ * table.
+ * @return true if the AssetManager is now theme-aware; false otherwise.
+ * This can fail, for example, if the theme package has been been
+ * removed and the theme manager has yet to revert formally back to
+ * the framework default.
+ */
+ private boolean attachThemeAssets(AssetManager assets, CustomTheme theme, boolean updating) {
+ android.content.pm.PackageInfo pi = null;
+ try {
+ pi = getPackageManager().getPackageInfo(theme.getThemePackageName(), 0);
+ } catch (RemoteException e) {
+ }
+ if (pi != null && pi.applicationInfo != null && pi.themeInfos != null) {
+ /*
+ * It's important that this is called before
+ * updateResourcesWithAssetPath as it depends on the result of
+ * getThemePackageName to figure out what to do with the resource
+ * redirection table.
+ */
+ assets.setThemePackageInfo(theme.getThemePackageName(),
+ findThemeResourceId(pi.themeInfos, theme));
+
+ String themeResDir = pi.applicationInfo.publicSourceDir;
+ int cookie;
+ if (updating) {
+ cookie = assets.updateResourcesWithAssetPath(themeResDir);
+ } else {
+ cookie = assets.addAssetPath(themeResDir);
+ }
if (cookie != 0) {
- assets.setThemePackageName(theme.getThemePackageName());
assets.setThemeCookie(cookie);
return true;
} else {
- Log.e(TAG, "Unable to add theme resdir=" + themeResDir);
+ Log.e(TAG, "Unable to " + (updating ? "update" : "add") + " theme assets at " +
+ themeResDir);
+
+ /* Roll back the theme package info. */
+ assets.setThemePackageInfo(null, 0);
}
}
return false;
}
/**
+ * Searches for the high-level theme resource id for the specific
+ * <theme> tag being applied.
+ * <p>
+ * An individual theme package can contain multiple &lt;theme&gt; tags, each
+ * representing a separate theme choice from the user's perspective, even
+ * though the most common case is for there to be only 1.
+ *
+ * @return The style resource id or 0 if no match was found.
+ */
+ private int findThemeResourceId(ThemeInfo[] themeInfos, CustomTheme theme) {
+ String needle = theme.getThemeId();
+ if (themeInfos != null && !TextUtils.isEmpty(needle)) {
+ int n = themeInfos.length;
+ for (int i = 0; i < n; i++) {
+ ThemeInfo info = themeInfos[i];
+ if (needle.equals(info.themeId)) {
+ return info.styleResourceId;
+ }
+ }
+ }
+ return 0;
+ }
+
+ /**
* Creates the top level resources for the given package.
*
* @deprecated {@link #getTopLevelResources(String, PackageInfo, boolean)}
@@ -4051,16 +4109,12 @@ public final class ActivityThread {
String oldThemePackage = am.getThemePackageName();
int themeCookie = am.getThemeCookie();
if (!TextUtils.isEmpty(oldThemePackage) && themeCookie != 0) {
- am.setThemePackageName(null);
+ am.setThemePackageInfo(null, 0);
am.removeAssetPath(oldThemePackage, themeCookie);
am.setThemeCookie(0);
}
- String newThemePackage = config.customTheme.getThemePackageName();
- String resDir = getPackageResDir(newThemePackage);
- if (resDir != null) {
- am.setThemePackageName(newThemePackage);
- int newCookie = am.updateResourcesWithAssetPath(resDir);
- am.setThemeCookie(newCookie);
+ if (!TextUtils.isEmpty(config.customTheme.getThemePackageName())) {
+ attachThemeAssets(am, config.customTheme, true);
}
}
}
@@ -4079,19 +4133,6 @@ public final class ActivityThread {
return changes;
}
- private String getPackageResDir(String packageName) {
- android.content.pm.PackageInfo pi;
- try {
- pi = getPackageManager().getPackageInfo(packageName, 0);
- if (pi == null || pi.applicationInfo == null)
- return null;
- return pi.applicationInfo.publicSourceDir;
- } catch (RemoteException e) {
- Log.e("ActivityThread", "Exception in getPackageResDir", e);
- }
- return null;
- }
-
final void handleConfigurationChanged(Configuration config) {
ArrayList<ComponentCallbacks> callbacks = null;
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 6aca089..532572d 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -697,10 +697,10 @@ public final class AssetManager {
public native final String getThemePackageName();
/**
- * Sets package name for current theme (null is allowed).
+ * Sets package name and highest level style id for current theme (null, 0 is allowed).
* {@hide}
*/
- public native final void setThemePackageName(String packageName);
+ public native final void setThemePackageInfo(String packageName, int styleId);
/**
* Get asset cookie for current theme (may return 0).
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index da91bd7..0cabc9a 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1767,8 +1767,8 @@ static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env,
return AssetManager::getGlobalCount();
}
-static void android_content_AssetManager_setThemePackageName(JNIEnv* env, jobject clazz,
- jstring packageName)
+static void android_content_AssetManager_setThemePackageInfo(JNIEnv* env, jobject clazz,
+ jstring packageName, jint styleId)
{
AssetManager* am = assetManagerForJavaObject(env, clazz);
if (am == NULL) {
@@ -1777,10 +1777,10 @@ static void android_content_AssetManager_setThemePackageName(JNIEnv* env, jobjec
if (packageName != NULL) {
const char* packageName8 = env->GetStringUTFChars(packageName, NULL);
- am->setThemePackageName(packageName8);
+ am->setThemePackageInfo(packageName8, styleId);
env->ReleaseStringUTFChars(packageName, packageName8);
} else {
- am->setThemePackageName(NULL);
+ am->setThemePackageInfo(NULL, styleId);
}
}
@@ -1966,8 +1966,8 @@ static JNINativeMethod gAssetManagerMethods[] = {
(void*) android_content_AssetManager_splitThemePackage },
// Dynamic theme package support.
- { "setThemePackageName", "(Ljava/lang/String;)V",
- (void*) android_content_AssetManager_setThemePackageName },
+ { "setThemePackageInfo", "(Ljava/lang/String;I)V",
+ (void*) android_content_AssetManager_setThemePackageInfo },
{ "getThemePackageName", "()Ljava/lang/String;",
(void*) android_content_AssetManager_getThemePackageName },
{ "removeAssetPath", "(Ljava/lang/String;I)Z",
diff --git a/include/utils/AssetManager.h b/include/utils/AssetManager.h
index fe92e87..89020de 100644
--- a/include/utils/AssetManager.h
+++ b/include/utils/AssetManager.h
@@ -198,7 +198,7 @@ public:
*/
void getLocales(Vector<String8>* locales) const;
- void setThemePackageName(const char* packageName);
+ void setThemePackageInfo(const char* packageName, uint32_t styleId);
const char* getThemePackageName();
/*
@@ -222,7 +222,8 @@ private:
SharedBuffer* generateRedirections(SharedBuffer* entriesByTypeBuf, ResTable* rt,
const char* themePackageName, const char16_t* resPackageName);
bool generateAndWriteRedirections(ResTable* rt, const char* themePackageName,
- const char16_t* resPackageName, const char* redirPath, bool isFramework) const;
+ uint32_t themeStyleId, const char16_t* resPackageName, const char* redirPath,
+ bool isFramework) const;
void loadRedirectionMappings(ResTable* rt) const;
void updateResTableFromAssetPath(ResTable* rt, const asset_path& ap, void* cookie) const;
Asset* openInPathLocked(const char* fileName, AccessMode mode,
@@ -344,6 +345,7 @@ private:
// If non-null, represents the theme package from which to construct the
// resource redirection map used by ResTable.
char* mThemePackageName;
+ uint32_t mThemeStyleId;
mutable ResTable* mResources;
ResTable_config* mConfig;
diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp
index 94f0fcd..eb8e62e 100644
--- a/libs/utils/AssetManager.cpp
+++ b/libs/utils/AssetManager.cpp
@@ -515,33 +515,15 @@ static bool writeRedirections(const char* redirPath, SharedBuffer* entriesByType
// for testing. This code should be generalized and follow a much better OO
// structure.
static SharedBuffer* generateFrameworkRedirections(SharedBuffer* entriesByTypeBuf, ResTable* rt,
- const char* themePackageName, const char* redirPath)
+ const char* themePackageName, uint32_t styleId, const char* redirPath)
{
- REDIRECT_NOISY(LOGW("generateFrameworkRedirections: themePackageName=%s\n", themePackageName));
-
- // HACK HACK HACK
- if (strcmp(themePackageName, "com.tmobile.theme.Androidian") != 0) {
- LOGW("EEP, UNEXPECTED PACKAGE!");
- return entriesByTypeBuf;
- }
+ REDIRECT_NOISY(LOGW("generateFrameworkRedirections: themePackageName=%s, styleId=0x%08x\n", themePackageName, styleId));
rt->lock();
// Load up a bag for the user-supplied theme.
- String16 type("style");
- String16 name("Androidian");
- String16 package(themePackageName);
- uint32_t ident = rt->identifierForName(name.string(), name.size(), type.string(), type.size(),
- package.string(), package.size());
- if (ident == 0) {
- LOGW("unable to locate theme identifier %s:%s/%s\n", String8(package).string(),
- String8(type).string(), String8(name).string());
- rt->unlock();
- return entriesByTypeBuf;
- }
-
const ResTable::bag_entry* themeEnt = NULL;
- ssize_t N = rt->getBagLocked(ident, &themeEnt);
+ ssize_t N = rt->getBagLocked(styleId, &themeEnt);
const ResTable::bag_entry* endThemeEnt = themeEnt + N;
// ...and a bag for the framework default.
@@ -550,7 +532,7 @@ static SharedBuffer* generateFrameworkRedirections(SharedBuffer* entriesByTypeBu
const ResTable::bag_entry* endFrameworkEnt = frameworkEnt + N;
// The first entry should be for the theme itself.
- entriesByTypeBuf = addToEntriesByTypeBuffer(entriesByTypeBuf, 0x01030005, ident);
+ entriesByTypeBuf = addToEntriesByTypeBuffer(entriesByTypeBuf, 0x01030005, styleId);
// Now compare them and infer resource redirections for attributes that
// remap to different styles. This works by essentially lining up all the
@@ -560,7 +542,7 @@ static SharedBuffer* generateFrameworkRedirections(SharedBuffer* entriesByTypeBu
// the one in the theme. This lets us do things like automatically find
// redirections for @android:style/Widget.Button by looking at how the
// theme overrides the android:attr/buttonStyle attribute.
- REDIRECT_NOISY(LOGW("delta between 0x01030005 and 0x%08x:\n", ident));
+ REDIRECT_NOISY(LOGW("delta between 0x01030005 and 0x%08x:\n", styleId));
for (; frameworkEnt < endFrameworkEnt; frameworkEnt++) {
if (frameworkEnt->map.value.dataType != Res_value::TYPE_REFERENCE) {
continue;
@@ -723,8 +705,9 @@ SharedBuffer* AssetManager::generateRedirections(SharedBuffer* entriesByTypeBuf,
}
bool AssetManager::generateAndWriteRedirections(ResTable* rt,
- const char* themePackageName, const char16_t* resPackageName,
- const char* redirPath, bool isFramework) const
+ const char* themePackageName, uint32_t themeStyleId,
+ const char16_t* resPackageName, const char* redirPath,
+ bool isFramework) const
{
// FIXME: the const is a lie!!!
AssetManager* am = (AssetManager*)this;
@@ -732,7 +715,8 @@ bool AssetManager::generateAndWriteRedirections(ResTable* rt,
SharedBuffer* buf = NULL;
if (isFramework) {
// Special framework theme heuristic...
- buf = generateFrameworkRedirections(buf, rt, themePackageName, redirPath);
+ buf = generateFrameworkRedirections(buf, rt, themePackageName,
+ themeStyleId, redirPath);
}
// Generate redirections from the package XML.
buf = am->generateRedirections(buf, rt, themePackageName, resPackageName);
@@ -778,7 +762,8 @@ void AssetManager::loadRedirectionMappings(ResTable* rt) const
if (lstat(redirPath.string(), &statbuf) != 0) {
generateAndWriteRedirections(rt, mThemePackageName,
- resPackageName, redirPath.string(), false);
+ mThemeStyleId, resPackageName, redirPath.string(),
+ false);
}
rt->addRedirections(packageId, redirPath.string());
@@ -795,7 +780,7 @@ void AssetManager::loadRedirectionMappings(ResTable* rt) const
if (lstat(frameworkRedirPath.string(), &statbuf) != 0) {
generateAndWriteRedirections(rt, mThemePackageName,
- String16("android").string(),
+ mThemeStyleId, String16("android").string(),
frameworkRedirPath.string(), true);
}
@@ -2205,17 +2190,20 @@ int AssetManager::ZipSet::getIndex(const String8& zip) const
}
/*
- * Set the currently applied theme package name.
+ * Set the currently applied theme package name and the high-level theme style
+ * identifier (the one to replace @android:style/Theme). May be set to NULL, 0
+ * to indicate that this AssetManager does not have an added theme package.
*
* This information is used when constructing the ResTable's resource
* redirection map.
*/
-void AssetManager::setThemePackageName(const char* packageName)
+void AssetManager::setThemePackageInfo(const char* packageName, uint32_t styleId)
{
if (mThemePackageName != NULL) {
delete[] mThemePackageName;
}
mThemePackageName = strdupNew(packageName);
+ mThemeStyleId = styleId;
}
const char* AssetManager::getThemePackageName()