summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/tm/src/com/android/commands/tm/Tm.java17
-rw-r--r--core/java/android/content/pm/ThemeUtils.java15
-rw-r--r--core/java/android/content/res/IThemeService.aidl3
-rw-r--r--core/java/android/content/res/ThemeChangeRequest.aidl19
-rw-r--r--core/java/android/content/res/ThemeChangeRequest.java225
-rw-r--r--core/java/android/content/res/ThemeConfig.java16
-rw-r--r--core/java/android/content/res/ThemeManager.java22
-rw-r--r--services/core/java/com/android/server/ThemeService.java178
8 files changed, 403 insertions, 92 deletions
diff --git a/cmds/tm/src/com/android/commands/tm/Tm.java b/cmds/tm/src/com/android/commands/tm/Tm.java
index 14101f7..af1ac75 100644
--- a/cmds/tm/src/com/android/commands/tm/Tm.java
+++ b/cmds/tm/src/com/android/commands/tm/Tm.java
@@ -23,6 +23,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.ParceledListSlice;
import android.content.pm.ThemeUtils;
import android.content.res.IThemeService;
+import android.content.res.ThemeChangeRequest;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -54,13 +55,14 @@ public class Tm extends BaseCommand {
StringBuilder sb = new StringBuilder();
sb.append("usage: tm [subcommand] [options]\n");
sb.append(" tm list\n");
- sb.append(" tm apply <PACKAGE_NAME> [-c <COMPONENT> [-c <COMPONENT>] ...]\n");
+ sb.append(" tm apply <PACKAGE_NAME> [-r] [-c <COMPONENT> [-c <COMPONENT>] ...]\n");
sb.append(" tm rebuild\n");
sb.append(" tm process <PACKAGE_NAME>\n");
sb.append("\n");
sb.append("tm list: return a list of theme packages.\n");
sb.append("\n");
sb.append("tm apply: applies the components for the theme specified by PACKAGE_NAME.\n");
+ sb.append(" -r: remove per app themes\n");
sb.append(" [-c <COMPONENT> [-c <COMPONENT>] ...]\n");
sb.append(" if no components are specified all components will be applied.\n");
sb.append(" Valid components are:\n");
@@ -143,22 +145,27 @@ public class Tm extends BaseCommand {
}
}
- Map<String, String> componentMap = new HashMap<String, String>();
+ boolean removePerAppThemes = false;
+
+ ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder();
String opt;
while ((opt=nextOption()) != null) {
if (opt.equals("-c")) {
- componentMap.put(nextArgRequired(), pkgName);
+ builder.setComponent(nextArgRequired(), pkgName);
+ } else if (opt.equals("-r")) {
+ removePerAppThemes = true;
}
}
// No components specified so let's just try and apply EVERYTHING!
+ Map<String, String> componentMap = builder.build().getThemeComponentsMap();
if (componentMap.size() == 0) {
List<String> components = ThemeUtils.getAllComponents();
for (String component : components) {
- componentMap.put(component, pkgName);
+ builder.setComponent(component, pkgName);
}
}
- mTs.requestThemeChange(componentMap);
+ mTs.requestThemeChange(builder.build(), removePerAppThemes);
}
private void runRebuildResourceCache() throws Exception {
diff --git a/core/java/android/content/pm/ThemeUtils.java b/core/java/android/content/pm/ThemeUtils.java
index 38391d4..a5a523c 100644
--- a/core/java/android/content/pm/ThemeUtils.java
+++ b/core/java/android/content/pm/ThemeUtils.java
@@ -107,6 +107,9 @@ public class ThemeUtils {
public static final int SYSTEM_TARGET_API = 0;
+ // Package name for any app which does not have a specific theme applied
+ private static final String DEFAULT_PKG = "default";
+
private static final String SETTINGS_DB =
"/data/data/com.android.providers.settings/databases/settings.db";
private static final String SETTINGS_SECURE_TABLE = "secure";
@@ -715,4 +718,16 @@ public class ThemeUtils {
return config;
}
+
+ /**
+ * Convenience method to determine if a theme component is a per app theme and not a standard
+ * component.
+ * @param component
+ * @return
+ */
+ public static boolean isPerAppThemeComponent(String component) {
+ return !(DEFAULT_PKG.equals(component)
+ || ThemeConfig.SYSTEMUI_STATUS_BAR_PKG.equals(component)
+ || ThemeConfig.SYSTEMUI_NAVBAR_PKG.equals(component));
+ }
}
diff --git a/core/java/android/content/res/IThemeService.aidl b/core/java/android/content/res/IThemeService.aidl
index 101ace9..90cb9fb 100644
--- a/core/java/android/content/res/IThemeService.aidl
+++ b/core/java/android/content/res/IThemeService.aidl
@@ -17,6 +17,7 @@ package android.content.res;
import android.content.res.IThemeChangeListener;
import android.content.res.IThemeProcessingListener;
+import android.content.res.ThemeChangeRequest;
import android.graphics.Bitmap;
import java.util.Map;
@@ -26,7 +27,7 @@ interface IThemeService {
void requestThemeChangeUpdates(in IThemeChangeListener listener);
void removeUpdates(in IThemeChangeListener listener);
- void requestThemeChange(in Map componentMap);
+ void requestThemeChange(in ThemeChangeRequest request, boolean removePerAppThemes);
void applyDefaultTheme();
boolean isThemeApplying();
int getProgress();
diff --git a/core/java/android/content/res/ThemeChangeRequest.aidl b/core/java/android/content/res/ThemeChangeRequest.aidl
new file mode 100644
index 0000000..e6cf115
--- /dev/null
+++ b/core/java/android/content/res/ThemeChangeRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.res;
+
+/** @hide */
+parcelable ThemeChangeRequest;
diff --git a/core/java/android/content/res/ThemeChangeRequest.java b/core/java/android/content/res/ThemeChangeRequest.java
new file mode 100644
index 0000000..2c1f6ff
--- /dev/null
+++ b/core/java/android/content/res/ThemeChangeRequest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.res;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+
+import static android.provider.ThemesContract.ThemesColumns.*;
+
+/** @hide */
+public final class ThemeChangeRequest implements Parcelable {
+ private final Map<String, String> mThemeComponents = new HashMap<String, String>();
+ private final Map<String, String> mPerAppOverlays = new HashMap<String, String>();
+
+ public String getOverlayThemePackageName() {
+ return getThemePackageNameForComponent(MODIFIES_OVERLAYS);
+ }
+
+ public String getStatusBarThemePackageName() {
+ return getThemePackageNameForComponent(MODIFIES_STATUS_BAR);
+ }
+
+ public String getNavBarThemePackageName() {
+ return getThemePackageNameForComponent(MODIFIES_NAVIGATION_BAR);
+ }
+
+ public String getFontThemePackageName() {
+ return getThemePackageNameForComponent(MODIFIES_FONTS);
+ }
+
+ public String getIconsThemePackageName() {
+ return getThemePackageNameForComponent(MODIFIES_ICONS);
+ }
+
+ public String getBootanimationThemePackageName() {
+ return getThemePackageNameForComponent(MODIFIES_BOOT_ANIM);
+ }
+
+ public String getWallpaperThemePackageName() {
+ return getThemePackageNameForComponent(MODIFIES_LAUNCHER);
+ }
+
+ public String getLockWallpaperThemePackageName() {
+ return getThemePackageNameForComponent(MODIFIES_LOCKSCREEN);
+ }
+
+ public String getAlarmThemePackageName() {
+ return getThemePackageNameForComponent(MODIFIES_ALARMS);
+ }
+
+ public String getNotificationThemePackageName() {
+ return getThemePackageNameForComponent(MODIFIES_NOTIFICATIONS);
+ }
+
+ public String getRingtoneThemePackageName() {
+ return getThemePackageNameForComponent(MODIFIES_RINGTONES);
+ }
+
+ public final Map<String, String> getThemeComponentsMap() {
+ return Collections.unmodifiableMap(mThemeComponents);
+ }
+
+ /**
+ * Get the mapping for per app themes
+ * @return A mapping of apps and the theme to apply for each one. or null if none set.
+ */
+ public final Map<String, String> getPerAppOverlays() {
+ return Collections.unmodifiableMap(mPerAppOverlays);
+ }
+
+ public int getNumChangesRequested() {
+ return mThemeComponents.size() + mPerAppOverlays.size();
+ }
+
+ private String getThemePackageNameForComponent(String componentName) {
+ return mThemeComponents.get(componentName);
+ }
+
+ private ThemeChangeRequest(Map<String, String> components, Map<String, String> perAppThemes) {
+ if (components != null) {
+ mThemeComponents.putAll(components);
+ }
+ if (perAppThemes != null) {
+ mPerAppOverlays.putAll(perAppThemes);
+ }
+ }
+
+ private ThemeChangeRequest(Parcel source) {
+ int numComponents = source.readInt();
+ for (int i = 0; i < numComponents; i++) {
+ mThemeComponents.put(source.readString(), source.readString());
+ }
+
+ numComponents = source.readInt();
+ for (int i = 0 ; i < numComponents; i++) {
+ mPerAppOverlays.put(source.readString(), source.readString());
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mThemeComponents.size());
+ for (String component : mThemeComponents.keySet()) {
+ dest.writeString(component);
+ dest.writeString(mThemeComponents.get(component));
+ }
+ dest.writeInt((mPerAppOverlays.size()));
+ for (String appPkgName : mPerAppOverlays.keySet()) {
+ dest.writeString(appPkgName);
+ dest.writeString(mPerAppOverlays.get(appPkgName));
+ }
+ }
+
+ public static final Parcelable.Creator<ThemeChangeRequest> CREATOR =
+ new Parcelable.Creator<ThemeChangeRequest>() {
+ @Override
+ public ThemeChangeRequest createFromParcel(Parcel source) {
+ return new ThemeChangeRequest(source);
+ }
+
+ @Override
+ public ThemeChangeRequest[] newArray(int size) {
+ return new ThemeChangeRequest[size];
+ }
+ };
+
+ public static class Builder {
+ Map<String, String> mThemeComponents = new HashMap<String, String>();
+ Map<String, String> mPerAppOverlays = new HashMap<String, String>();
+
+ public Builder() {}
+
+ public Builder setOverlay(String pkgName) {
+ return setComponent(MODIFIES_OVERLAYS, pkgName);
+ }
+
+ public Builder setStatusBar(String pkgName) {
+ return setComponent(MODIFIES_STATUS_BAR, pkgName);
+ }
+
+ public Builder setNavBar(String pkgName) {
+ return setComponent(MODIFIES_NAVIGATION_BAR, pkgName);
+ }
+
+ public Builder setFont(String pkgName) {
+ return setComponent(MODIFIES_FONTS, pkgName);
+ }
+
+ public Builder setIcons(String pkgName) {
+ return setComponent(MODIFIES_ICONS, pkgName);
+ }
+
+ public Builder setBootanimation(String pkgName) {
+ return setComponent(MODIFIES_BOOT_ANIM, pkgName);
+ }
+
+ public Builder setWallpaper(String pkgName) {
+ return setComponent(MODIFIES_LAUNCHER, pkgName);
+ }
+
+ public Builder setLockWallpaper(String pkgName) {
+ return setComponent(MODIFIES_LOCKSCREEN, pkgName);
+ }
+
+ public Builder setAlarm(String pkgName) {
+ return setComponent(MODIFIES_ALARMS, pkgName);
+ }
+
+ public Builder setNotification(String pkgName) {
+ return setComponent(MODIFIES_NOTIFICATIONS, pkgName);
+ }
+
+ public Builder setRingtone(String pkgName) {
+ return setComponent(MODIFIES_RINGTONES, pkgName);
+ }
+
+ public Builder setComponent(String component, String pkgName) {
+ if (pkgName != null) {
+ mThemeComponents.put(component, pkgName);
+ } else {
+ mThemeComponents.remove(component);
+ }
+ return this;
+ }
+
+ public Builder setAppOverlay(String appPkgName, String themePkgName) {
+ if (appPkgName != null) {
+ if (themePkgName != null) {
+ mPerAppOverlays.put(appPkgName, themePkgName);
+ } else {
+ mPerAppOverlays.remove(appPkgName);
+ }
+ }
+
+ return this;
+ }
+
+ public ThemeChangeRequest build() {
+ return new ThemeChangeRequest(mThemeComponents, mPerAppOverlays);
+ }
+ }
+}
diff --git a/core/java/android/content/res/ThemeConfig.java b/core/java/android/content/res/ThemeConfig.java
index 61c37c3..1882211 100644
--- a/core/java/android/content/res/ThemeConfig.java
+++ b/core/java/android/content/res/ThemeConfig.java
@@ -31,6 +31,7 @@ import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -105,6 +106,10 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi
return theme.mFontPkgName;
}
+ public Map<String, AppTheme> getAppThemes() {
+ return Collections.unmodifiableMap(mThemes);
+ }
+
private AppTheme getThemeFor(String pkgName) {
AppTheme theme = mThemes.get(pkgName);
if (theme == null) theme = getDefaultTheme();
@@ -429,8 +434,15 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi
String overlay = mOverlays.get(appPkgName);
String font = mFonts.get(appPkgName);
- AppTheme appTheme = new AppTheme(overlay, icon, font);
- appThemes.put(appPkgName, appTheme);
+ // Remove app theme if all items are null
+ if (overlay == null && icon == null && font == null) {
+ if (appThemes.containsKey(appPkgName)) {
+ appThemes.remove(appPkgName);
+ }
+ } else {
+ AppTheme appTheme = new AppTheme(overlay, icon, font);
+ appThemes.put(appPkgName, appTheme);
+ }
}
ThemeConfig themeConfig = new ThemeConfig(appThemes);
themeConfig.mThemeChangeTimestamp = mThemeChangeTimestamp;
diff --git a/core/java/android/content/res/ThemeManager.java b/core/java/android/content/res/ThemeManager.java
index a9d2fcc..fd05f1e 100644
--- a/core/java/android/content/res/ThemeManager.java
+++ b/core/java/android/content/res/ThemeManager.java
@@ -222,16 +222,34 @@ public class ThemeManager {
}
public void requestThemeChange(String pkgName, List<String> components) {
+ requestThemeChange(pkgName, components, true);
+ }
+
+ public void requestThemeChange(String pkgName, List<String> components,
+ boolean removePerAppThemes) {
Map<String, String> componentMap = new HashMap<String, String>(components.size());
for (String component : components) {
componentMap.put(component, pkgName);
}
- requestThemeChange(componentMap);
+ requestThemeChange(componentMap, removePerAppThemes);
}
public void requestThemeChange(Map<String, String> componentMap) {
+ requestThemeChange(componentMap, true);
+ }
+
+ public void requestThemeChange(Map<String, String> componentMap, boolean removePerAppThemes) {
+ ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder();
+ for (String component : componentMap.keySet()) {
+ builder.setComponent(component, componentMap.get(component));
+ }
+
+ requestThemeChange(builder.build(), removePerAppThemes);
+ }
+
+ public void requestThemeChange(ThemeChangeRequest request, boolean removePerAppThemes) {
try {
- mService.requestThemeChange(componentMap);
+ mService.requestThemeChange(request, removePerAppThemes);
} catch (RemoteException e) {
logThemeServiceException(e);
}
diff --git a/services/core/java/com/android/server/ThemeService.java b/services/core/java/com/android/server/ThemeService.java
index 6547a41..d2fa28e 100644
--- a/services/core/java/com/android/server/ThemeService.java
+++ b/services/core/java/com/android/server/ThemeService.java
@@ -37,12 +37,12 @@ import android.content.pm.ThemeUtils;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.IThemeProcessingListener;
+import android.content.res.ThemeChangeRequest;
import android.content.res.ThemeConfig;
import android.content.res.IThemeChangeListener;
import android.content.res.IThemeService;
import android.database.Cursor;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.media.RingtoneManager;
import android.os.Binder;
import android.os.Environment;
@@ -136,8 +136,8 @@ public class ThemeService extends IThemeService.Stub {
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_CHANGE_THEME:
- final Map<String, String> componentMap = (Map<String, String>) msg.obj;
- doApplyTheme(componentMap);
+ final ThemeChangeRequest request = (ThemeChangeRequest) msg.obj;
+ doApplyTheme(request, msg.arg1 == 1);
break;
case MESSAGE_APPLY_DEFAULT_THEME:
doApplyDefaultTheme();
@@ -280,7 +280,7 @@ public class ThemeService extends IThemeService.Stub {
// of the pkg with the system. If it is not compatible then we will add it to a theme
// change request.
Map<String, String> defaults = ThemeUtils.getDefaultComponents(mContext);
- HashMap<String, String> changeThemeRequestMap = new HashMap<String, String>();
+ ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder();
for(Map.Entry<String, String> entry : currentThemeMap.entrySet()) {
String component = entry.getKey();
String pkgName = entry.getValue();
@@ -303,14 +303,15 @@ public class ThemeService extends IThemeService.Stub {
if (!isThemeCompatibleWithUpgradedApi(pkgName)) {
Log.d(TAG, pkgName + "is incompatible with latest theme api for component " +
component + ", Applying " + defaultPkg);
- changeThemeRequestMap.put(component, pkgName);
+ builder.setComponent(component, pkgName);
}
}
// Now actually unapply the incompatible themes
- if (!changeThemeRequestMap.isEmpty()) {
+ ThemeChangeRequest request = builder.build();
+ if (!request.getThemeComponentsMap().isEmpty()) {
try {
- requestThemeChange(changeThemeRequestMap);
+ requestThemeChange(request, true);
} catch(RemoteException e) {
// This cannot happen
}
@@ -361,13 +362,13 @@ public class ThemeService extends IThemeService.Stub {
}
}
- private void doApplyTheme(Map<String, String> componentMap) {
+ private void doApplyTheme(ThemeChangeRequest request, boolean removePerAppTheme) {
synchronized(this) {
mProgress = 0;
}
- if (componentMap == null || componentMap.size() == 0) {
- postFinish(true, componentMap);
+ if (request == null || request.getNumChangesRequested() == 0) {
+ postFinish(true, request);
return;
}
mIsThemeApplying = true;
@@ -375,75 +376,59 @@ public class ThemeService extends IThemeService.Stub {
incrementProgress(5);
// TODO: provide progress updates that reflect the time needed for each component
- final int progressIncrement = 75 / componentMap.size();
+ final int progressIncrement = 75 / request.getNumChangesRequested();
- if (componentMap.containsKey(ThemesColumns.MODIFIES_ICONS)) {
- if (!updateIcons(componentMap.get(ThemesColumns.MODIFIES_ICONS))) {
- componentMap.remove(ThemesColumns.MODIFIES_ICONS);
- }
+ if (request.getIconsThemePackageName() != null) {
+ updateIcons(request.getIconsThemePackageName());
incrementProgress(progressIncrement);
}
- if (componentMap.containsKey(ThemesColumns.MODIFIES_LAUNCHER)) {
- if (updateWallpaper(componentMap.get(ThemesColumns.MODIFIES_LAUNCHER))) {
+ if (request.getWallpaperThemePackageName() != null) {
+ if (updateWallpaper(request.getWallpaperThemePackageName())) {
mWallpaperChangedByUs = true;
- } else {
- componentMap.remove(ThemesColumns.MODIFIES_LAUNCHER);
}
incrementProgress(progressIncrement);
}
- if (componentMap.containsKey(ThemesColumns.MODIFIES_LOCKSCREEN)) {
- if (!updateLockscreen(componentMap.get(ThemesColumns.MODIFIES_LOCKSCREEN))) {
- componentMap.remove(ThemesColumns.MODIFIES_LOCKSCREEN);
- }
+ if (request.getLockWallpaperThemePackageName() != null) {
+ updateLockscreen(request.getLockWallpaperThemePackageName());
incrementProgress(progressIncrement);
}
- if (componentMap.containsKey(ThemesColumns.MODIFIES_NOTIFICATIONS)) {
- if (!updateNotifications(componentMap.get(ThemesColumns.MODIFIES_NOTIFICATIONS))) {
- componentMap.remove(ThemesColumns.MODIFIES_NOTIFICATIONS);
- }
+ Environment.setUserRequired(false);
+ if (request.getNotificationThemePackageName() != null) {
+ updateNotifications(request.getNotificationThemePackageName());
incrementProgress(progressIncrement);
}
- Environment.setUserRequired(false);
- if (componentMap.containsKey(ThemesColumns.MODIFIES_ALARMS)) {
- if (!updateAlarms(componentMap.get(ThemesColumns.MODIFIES_ALARMS))) {
- componentMap.remove(ThemesColumns.MODIFIES_ALARMS);
- }
+ if (request.getAlarmThemePackageName() != null) {
+ updateNotifications(request.getAlarmThemePackageName());
incrementProgress(progressIncrement);
}
- if (componentMap.containsKey(ThemesColumns.MODIFIES_RINGTONES)) {
- if (!updateRingtones(componentMap.get(ThemesColumns.MODIFIES_RINGTONES))) {
- componentMap.remove(ThemesColumns.MODIFIES_RINGTONES);
- }
+ if (request.getRingtoneThemePackageName() != null) {
+ updateNotifications(request.getRingtoneThemePackageName());
incrementProgress(progressIncrement);
}
+ Environment.setUserRequired(true);
- if (componentMap.containsKey(ThemesColumns.MODIFIES_BOOT_ANIM)) {
- if (!updateBootAnim(componentMap.get(ThemesColumns.MODIFIES_BOOT_ANIM))) {
- componentMap.remove(ThemesColumns.MODIFIES_BOOT_ANIM);
- }
+ if (request.getBootanimationThemePackageName() != null) {
+ updateBootAnim(request.getBootanimationThemePackageName());
incrementProgress(progressIncrement);
}
- Environment.setUserRequired(true);
- if (componentMap.containsKey(ThemesColumns.MODIFIES_FONTS)) {
- if (!updateFonts(componentMap.get(ThemesColumns.MODIFIES_FONTS))) {
- componentMap.remove(ThemesColumns.MODIFIES_FONTS);
- }
+ if (request.getFontThemePackageName() != null) {
+ updateFonts(request.getFontThemePackageName());
incrementProgress(progressIncrement);
}
- updateProvider(componentMap);
+ updateProvider(request);
- updateConfiguration(componentMap);
+ updateConfiguration(request, removePerAppTheme);
- killLaunchers(componentMap);
+ killLaunchers(request);
- postFinish(true, componentMap);
+ postFinish(true, request);
mIsThemeApplying = false;
}
@@ -461,12 +446,12 @@ public class ThemeService extends IThemeService.Stub {
components = new ArrayList<String>(
Arrays.asList(defaultThemeComponents.split("\\|")));
}
- Map<String, String> componentMap = new HashMap<String, String>(components.size());
+ ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder();
for (String component : components) {
- componentMap.put(component, defaultThemePkg);
+ builder.setComponent(component, defaultThemePkg);
}
try {
- requestThemeChange(componentMap);
+ requestThemeChange(builder.build(), true);
} catch (RemoteException e) {
Log.w(TAG, "Unable to set default theme", e);
}
@@ -478,9 +463,10 @@ public class ThemeService extends IThemeService.Stub {
processInstalledThemes();
}
- private void updateProvider(Map<String, String> componentMap) {
+ private void updateProvider(ThemeChangeRequest request) {
ContentValues values = new ContentValues();
+ Map<String, String> componentMap = request.getThemeComponentsMap();
for (String component : componentMap.keySet()) {
values.put(ThemesContract.MixnMatchColumns.COL_VALUE, componentMap.get(component));
String where = ThemesContract.MixnMatchColumns.COL_KEY + "=?";
@@ -721,13 +707,15 @@ public class ThemeService extends IThemeService.Stub {
return true;
}
- private boolean updateConfiguration(Map<String, String> components) {
+ private boolean updateConfiguration(ThemeChangeRequest request,
+ boolean removePerAppThemes) {
final IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
final long token = Binder.clearCallingIdentity();
try {
Configuration config = am.getConfiguration();
- ThemeConfig.Builder themeBuilder = createBuilderFrom(config, components, null);
+ ThemeConfig.Builder themeBuilder = createBuilderFrom(config, request, null,
+ removePerAppThemes);
ThemeConfig newConfig = themeBuilder.build();
config.themeConfig = newConfig;
@@ -742,32 +730,40 @@ public class ThemeService extends IThemeService.Stub {
}
private static ThemeConfig.Builder createBuilderFrom(Configuration config,
- Map<String, String> componentMap, String pkgName) {
+ ThemeChangeRequest request, String pkgName, boolean removePerAppThemes) {
ThemeConfig.Builder builder = new ThemeConfig.Builder(config.themeConfig);
- if (componentMap.containsKey(ThemesColumns.MODIFIES_ICONS)) {
- builder.defaultIcon(pkgName == null ?
- componentMap.get(ThemesColumns.MODIFIES_ICONS) : pkgName);
+ if (removePerAppThemes) removePerAppThemesFromConfig(builder, config.themeConfig);
+
+ if (request.getIconsThemePackageName() != null) {
+ builder.defaultIcon(pkgName == null ? request.getIconsThemePackageName() : pkgName);
}
- if (componentMap.containsKey(ThemesColumns.MODIFIES_OVERLAYS)) {
+ if (request.getOverlayThemePackageName() != null) {
builder.defaultOverlay(pkgName == null ?
- componentMap.get(ThemesColumns.MODIFIES_OVERLAYS) : pkgName);
+ request.getOverlayThemePackageName() : pkgName);
}
- if (componentMap.containsKey(ThemesColumns.MODIFIES_FONTS)) {
- builder.defaultFont(pkgName == null ?
- componentMap.get(ThemesColumns.MODIFIES_FONTS) : pkgName);
+ if (request.getFontThemePackageName() != null) {
+ builder.defaultFont(pkgName == null ? request.getFontThemePackageName() : pkgName);
}
- if (componentMap.containsKey(ThemesColumns.MODIFIES_STATUS_BAR)) {
+ if (request.getStatusBarThemePackageName() != null) {
builder.overlay(ThemeConfig.SYSTEMUI_STATUS_BAR_PKG, pkgName == null ?
- componentMap.get(ThemesColumns.MODIFIES_STATUS_BAR) : pkgName);
+ request.getStatusBarThemePackageName() : pkgName);
}
- if (componentMap.containsKey(ThemesColumns.MODIFIES_NAVIGATION_BAR)) {
+ if (request.getNavBarThemePackageName() != null) {
builder.overlay(ThemeConfig.SYSTEMUI_NAVBAR_PKG, pkgName == null ?
- componentMap.get(ThemesColumns.MODIFIES_NAVIGATION_BAR) : pkgName);
+ request.getNavBarThemePackageName() : pkgName);
+ }
+
+ // check for any per app overlays being applied
+ Map<String, String> appOverlays = request.getPerAppOverlays();
+ for (String appPkgName : appOverlays.keySet()) {
+ if (appPkgName != null) {
+ builder.overlay(appPkgName, appOverlays.get(appPkgName));
+ }
}
builder.setThemeChangeTimestamp(System.currentTimeMillis());
@@ -775,11 +771,23 @@ public class ThemeService extends IThemeService.Stub {
return builder;
}
+ private static void removePerAppThemesFromConfig(ThemeConfig.Builder builder,
+ ThemeConfig themeConfig) {
+ if (themeConfig != null) {
+ Map<String, ThemeConfig.AppTheme> themes = themeConfig.getAppThemes();
+ for (String appPkgName : themes.keySet()) {
+ if (ThemeUtils.isPerAppThemeComponent(appPkgName)) {
+ builder.overlay(appPkgName, null);
+ }
+ }
+ }
+ }
+
// Kill the current Home process, they tend to be evil and cache
// drawable references in all apps
- private void killLaunchers(Map<String, String> componentMap) {
- if (!(componentMap.containsKey(ThemesColumns.MODIFIES_ICONS)
- || componentMap.containsKey(ThemesColumns.MODIFIES_OVERLAYS))) {
+ private void killLaunchers(ThemeChangeRequest request) {
+ if (request.getOverlayThemePackageName() == null
+ && request.getIconsThemePackageName() == null) {
return;
}
@@ -838,7 +846,7 @@ public class ThemeService extends IThemeService.Stub {
mClients.finishBroadcast();
}
- private void postFinish(boolean isSuccess, Map<String, String> componentMap) {
+ private void postFinish(boolean isSuccess, ThemeChangeRequest request) {
synchronized(this) {
mProgress = 0;
}
@@ -856,7 +864,7 @@ public class ThemeService extends IThemeService.Stub {
// if successful, broadcast that the theme changed
if (isSuccess) {
- broadcastThemeChange(componentMap);
+ broadcastThemeChange(request);
}
}
@@ -873,9 +881,12 @@ public class ThemeService extends IThemeService.Stub {
mProcessingListeners.finishBroadcast();
}
- private void broadcastThemeChange(Map<String, String> components) {
+ private void broadcastThemeChange(ThemeChangeRequest request) {
+ Map<String, String> componentMap = request.getThemeComponentsMap();
+ if (componentMap == null || componentMap.size() == 0) return;
+
final Intent intent = new Intent(ThemeUtils.ACTION_THEME_CHANGED);
- ArrayList componentsArrayList = new ArrayList(components.keySet());
+ ArrayList componentsArrayList = new ArrayList(componentMap.keySet());
intent.putStringArrayListExtra("components", componentsArrayList);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
@@ -903,7 +914,8 @@ public class ThemeService extends IThemeService.Stub {
}
@Override
- public void requestThemeChange(Map componentMap) throws RemoteException {
+ public void requestThemeChange(ThemeChangeRequest request, boolean removePerAppThemes)
+ throws RemoteException {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_THEME_MANAGER, null);
Message msg;
@@ -917,6 +929,7 @@ public class ThemeService extends IThemeService.Stub {
* the theme will be applied once the processing is done.
*/
synchronized (mThemesToProcessQueue) {
+ Map<String, String> componentMap = request.getThemeComponentsMap();
for (Object key : componentMap.keySet()) {
if (ThemesColumns.MODIFIES_OVERLAYS.equals(key) ||
ThemesColumns.MODIFIES_NAVIGATION_BAR.equals(key) ||
@@ -928,16 +941,17 @@ public class ThemeService extends IThemeService.Stub {
mThemesToProcessQueue.add(0, pkgName);
// We want to make sure these resources are taken care of first so
// send the dequeue message and place it in the front of the queue
- msg = mHandler.obtainMessage(
+ msg = mResourceProcessingHandler.obtainMessage(
ResourceProcessingHandler.MESSAGE_DEQUEUE_AND_PROCESS_THEME);
- mHandler.sendMessageAtFrontOfQueue(msg);
+ mResourceProcessingHandler.sendMessageAtFrontOfQueue(msg);
}
}
}
}
msg = Message.obtain();
msg.what = ThemeWorkerHandler.MESSAGE_CHANGE_THEME;
- msg.obj = componentMap;
+ msg.obj = request;
+ msg.arg1 = removePerAppThemes ? 1 : 0;
mHandler.sendMessage(msg);
}
@@ -1091,9 +1105,9 @@ public class ThemeService extends IThemeService.Stub {
public void onReceive(Context context, Intent intent) {
if (!mWallpaperChangedByUs) {
// In case the mixnmatch table has a mods_launcher entry, we'll clear it
- Map<String, String> components = new HashMap<String, String>(1);
- components.put(ThemesColumns.MODIFIES_LAUNCHER, "");
- updateProvider(components);
+ ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder();
+ builder.setWallpaper("");
+ updateProvider(builder.build());
} else {
mWallpaperChangedByUs = false;
}