Multiple custom themes 1/n
Refactor DefaultThemeProvider for better reuse, and add
support for storing and retrieving more than one custom
theme (custom theme names not supported yet).
Bug: 132257073
Change-Id: I9ed8b0e13fb5ab063373adedf40fc98896d0a20e
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 319aa0a..a97e26d 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -117,9 +117,10 @@
[CHAR LIMIT=20] -->
<string name="custom_theme_previous">Previous</string>
- <!-- Label for a system Style/Theme (combination of fonts/colors/icons) that is defined and
- customized by the user [CHAR LIMIT=15] -->
- <string name="custom_theme_title">Custom</string>
+ <!-- Generic label for one system Style/Theme (combination of fonts/colors/icons) that is
+ defined and customized by the user (note there could be more than one so the label includes
+ a number, eg "Custom 1, Custom 2, etc") [CHAR LIMIT=15] -->
+ <string name="custom_theme_title">Custom <xliff:g name="custom_num" example="1">%1$d</xliff:g></string>
<!-- Title for a screen that lets the user define their custom system Style/Theme
[CHAR LIMIT=30] -->
diff --git a/src/com/android/customization/model/theme/DefaultThemeProvider.java b/src/com/android/customization/model/theme/DefaultThemeProvider.java
index ac32312..a4f9a31 100644
--- a/src/com/android/customization/model/theme/DefaultThemeProvider.java
+++ b/src/com/android/customization/model/theme/DefaultThemeProvider.java
@@ -15,11 +15,7 @@
*/
package com.android.customization.model.theme;
-import static com.android.customization.model.ResourceConstants.ACCENT_COLOR_DARK_NAME;
-import static com.android.customization.model.ResourceConstants.ACCENT_COLOR_LIGHT_NAME;
import static com.android.customization.model.ResourceConstants.ANDROID_PACKAGE;
-import static com.android.customization.model.ResourceConstants.CONFIG_CORNERRADIUS;
-import static com.android.customization.model.ResourceConstants.CONFIG_ICON_MASK;
import static com.android.customization.model.ResourceConstants.ICONS_FOR_PREVIEW;
import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_FONT;
@@ -29,31 +25,22 @@
import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SYSUI;
import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_THEMEPICKER;
import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SHAPE;
-import static com.android.customization.model.ResourceConstants.SETTINGS_PACKAGE;
import static com.android.customization.model.ResourceConstants.SYSUI_PACKAGE;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.om.OverlayInfo;
-import android.content.om.OverlayManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
import android.service.wallpaper.WallpaperService;
import android.text.TextUtils;
import android.util.Log;
-import androidx.annotation.Dimension;
import androidx.annotation.Nullable;
import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
-import com.android.customization.model.ResourceConstants;
import com.android.customization.model.ResourcesApkProvider;
import com.android.customization.model.theme.ThemeBundle.Builder;
import com.android.customization.model.theme.custom.CustomTheme;
@@ -64,6 +51,7 @@
import com.bumptech.glide.request.RequestOptions;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParserException;
@@ -74,7 +62,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.function.Consumer;
/**
* Default implementation of {@link ThemeBundleProvider} that reads Themes' overlays from a stub APK.
@@ -100,29 +87,14 @@
private static final String DEFAULT_THEME_NAME= "default";
- // List of packages
- private final String[] mShapePreviewIconPackages;
+ private final OverlayThemeExtractor mOverlayProvider;
private List<ThemeBundle> mThemes;
- private Map<String, OverlayInfo> mOverlayInfos;
private final CustomizationPreferences mCustomizationPreferences;
public DefaultThemeProvider(Context context, CustomizationPreferences customizationPrefs) {
super(context, context.getString(R.string.themes_stub_package));
- OverlayManager om = context.getSystemService(OverlayManager.class);
+ mOverlayProvider = new OverlayThemeExtractor(context);
mCustomizationPreferences = customizationPrefs;
- mOverlayInfos = new HashMap<>();
-
- Consumer<OverlayInfo> addToMap = overlayInfo -> mOverlayInfos.put(
- overlayInfo.getPackageName(), overlayInfo);
-
- UserHandle user = UserHandle.of(UserHandle.myUserId());
- om.getOverlayInfosForTarget(ANDROID_PACKAGE, user).forEach(addToMap);
- om.getOverlayInfosForTarget(SYSUI_PACKAGE, user).forEach(addToMap);
- om.getOverlayInfosForTarget(SETTINGS_PACKAGE, user).forEach(addToMap);
- om.getOverlayInfosForTarget(ResourceConstants.getLauncherPackage(context), user).forEach(addToMap);
- om.getOverlayInfosForTarget(context.getPackageName(), user).forEach(addToMap);
- mShapePreviewIconPackages = context.getResources().getStringArray(
- R.array.icon_shape_preview_packages);
}
@Override
@@ -154,35 +126,36 @@
"string", mStubPackageName)));
String shapeOverlayPackage = getOverlayPackage(SHAPE_PREFIX, themeName);
- addShapeOverlay(builder, shapeOverlayPackage);
+ mOverlayProvider.addShapeOverlay(builder, shapeOverlayPackage);
String fontOverlayPackage = getOverlayPackage(FONT_PREFIX, themeName);
- addFontOverlay(builder, fontOverlayPackage);
+ mOverlayProvider.addFontOverlay(builder, fontOverlayPackage);
String colorOverlayPackage = getOverlayPackage(COLOR_PREFIX, themeName);
- addColorOverlay(builder, colorOverlayPackage);
+ mOverlayProvider.addColorOverlay(builder, colorOverlayPackage);
String iconAndroidOverlayPackage = getOverlayPackage(ICON_ANDROID_PREFIX,
themeName);
- addAndroidIconOverlay(builder, iconAndroidOverlayPackage);
+ mOverlayProvider.addAndroidIconOverlay(builder, iconAndroidOverlayPackage);
String iconSysUiOverlayPackage = getOverlayPackage(ICON_SYSUI_PREFIX, themeName);
- addSysUiIconOverlay(builder, iconSysUiOverlayPackage);
+ mOverlayProvider.addSysUiIconOverlay(builder, iconSysUiOverlayPackage);
String iconLauncherOverlayPackage = getOverlayPackage(ICON_LAUNCHER_PREFIX,
themeName);
- addNoPreviewIconOverlay(builder, iconLauncherOverlayPackage);
+ mOverlayProvider.addNoPreviewIconOverlay(builder, iconLauncherOverlayPackage);
String iconThemePickerOverlayPackage = getOverlayPackage(ICON_THEMEPICKER_PREFIX,
themeName);
- addNoPreviewIconOverlay(builder, iconThemePickerOverlayPackage);
+ mOverlayProvider.addNoPreviewIconOverlay(builder,
+ iconThemePickerOverlayPackage);
String iconSettingsOverlayPackage = getOverlayPackage(ICON_SETTINGS_PREFIX,
themeName);
- addNoPreviewIconOverlay(builder, iconSettingsOverlayPackage);
+ mOverlayProvider.addNoPreviewIconOverlay(builder, iconSettingsOverlayPackage);
addWallpaper(themeName, builder);
@@ -193,7 +166,7 @@
}
}
- addCustomTheme();
+ addCustomThemes();
}
private void addWallpaper(String themeName, Builder builder) {
@@ -235,9 +208,7 @@
LiveWallpaperInfo liveInfo = new LiveWallpaperInfo(wallpaperInfo);
builder.setLiveWallpaperInfo(liveInfo)
.setWallpaperAsset(liveInfo.getThumbAsset(mContext));
- } catch (XmlPullParserException e) {
- Log.w(TAG, "Skipping wallpaper " + resolveInfo.serviceInfo, e);
- } catch (IOException e) {
+ } catch (XmlPullParserException | IOException e) {
Log.w(TAG, "Skipping wallpaper " + resolveInfo.serviceInfo, e);
}
}
@@ -248,97 +219,6 @@
}
}
- private void addColorOverlay(Builder builder, String colorOverlayPackage)
- throws NameNotFoundException {
- if (!TextUtils.isEmpty(colorOverlayPackage)) {
- builder.addOverlayPackage(getOverlayCategory(colorOverlayPackage),
- colorOverlayPackage)
- .setColorAccentLight(loadColor(ACCENT_COLOR_LIGHT_NAME,
- colorOverlayPackage))
- .setColorAccentDark(loadColor(ACCENT_COLOR_DARK_NAME,
- colorOverlayPackage));
- } else {
- addSystemDefaultColor(builder);
- }
- }
-
- private void addShapeOverlay(Builder builder, String shapeOverlayPackage)
- throws NameNotFoundException {
- if (!TextUtils.isEmpty(shapeOverlayPackage)) {
- builder.addOverlayPackage(getOverlayCategory(shapeOverlayPackage),
- shapeOverlayPackage)
- .setShapePath(loadString(CONFIG_ICON_MASK, shapeOverlayPackage))
- .setBottomSheetCornerRadius(loadDimen(CONFIG_CORNERRADIUS, shapeOverlayPackage))
- /*.setUseRoundIcon(loadBoolean(CONFIG_USE_ROUNDICON, shapeOverlayPackage))*/;
- } else {
- builder.setShapePath(mContext.getResources().getString(
- Resources.getSystem().getIdentifier(CONFIG_ICON_MASK, "string",
- ANDROID_PACKAGE)))
- .setBottomSheetCornerRadius(
- mContext.getResources().getDimensionPixelOffset(
- Resources.getSystem().getIdentifier(CONFIG_CORNERRADIUS,
- "dimen", ANDROID_PACKAGE)))
- /*.setUseRoundIcon(mContext.getResources().getBoolean(
- Resources.getSystem().getIdentifier(CONFIG_USE_ROUNDICON,
- "boolean", ANDROID_PACKAGE)))*/;
- }
- for (String packageName : mShapePreviewIconPackages) {
- try {
- builder.addShapePreviewIcon(
- mContext.getPackageManager().getApplicationIcon(packageName));
- } catch (NameNotFoundException e) {
- Log.d(TAG, "Couldn't find app " + packageName
- + ", won't use it for icon shape preview");
- }
- }
- }
-
- private void addNoPreviewIconOverlay(Builder builder, String overlayPackage) {
- if (!TextUtils.isEmpty(overlayPackage)) {
- builder.addOverlayPackage(getOverlayCategory(overlayPackage),
- overlayPackage);
- }
- }
-
- private void addSysUiIconOverlay(Builder builder, String iconSysUiOverlayPackage)
- throws NameNotFoundException {
- if (!TextUtils.isEmpty(iconSysUiOverlayPackage)) {
- addIconOverlay(builder, iconSysUiOverlayPackage);
- }
- }
-
- private void addAndroidIconOverlay(Builder builder, String iconAndroidOverlayPackage)
- throws NameNotFoundException {
- if (!TextUtils.isEmpty(iconAndroidOverlayPackage)) {
- addIconOverlay(builder, iconAndroidOverlayPackage, ICONS_FOR_PREVIEW);
- } else {
- addSystemDefaultIcons(builder, ANDROID_PACKAGE, ICONS_FOR_PREVIEW);
- }
- }
- private void addIconOverlay(Builder builder, String packageName, String... previewIcons)
- throws NameNotFoundException {
- builder.addOverlayPackage(getOverlayCategory(packageName), packageName);
- for (String iconName : previewIcons) {
- builder.addIcon(loadIconPreviewDrawable(iconName, packageName, false));
- }
- }
-
- private void addFontOverlay(Builder builder, String fontOverlayPackage)
- throws NameNotFoundException {
- if (!TextUtils.isEmpty(fontOverlayPackage)) {
- builder.addOverlayPackage(getOverlayCategory(fontOverlayPackage),
- fontOverlayPackage)
- .setBodyFontFamily(loadTypeface(
- ResourceConstants.CONFIG_BODY_FONT_FAMILY,
- fontOverlayPackage))
- .setHeadlineFontFamily(loadTypeface(
- ResourceConstants.CONFIG_HEADLINE_FONT_FAMILY,
- fontOverlayPackage));
- } else {
- addSystemDefaultFont(builder);
- }
- }
-
/**
* Default theme requires different treatment: if there are overlay packages specified in the
* stub apk, we'll use those, otherwise we'll get the System default values. But we cannot skip
@@ -358,37 +238,29 @@
String colorOverlayPackage = getOverlayPackage(COLOR_PREFIX, DEFAULT_THEME_NAME);
try {
- builder.addOverlayPackage(getOverlayCategory(colorOverlayPackage), colorOverlayPackage)
- .setColorAccentLight(loadColor(ACCENT_COLOR_LIGHT_NAME, colorOverlayPackage))
- .setColorAccentDark(loadColor(ACCENT_COLOR_DARK_NAME, colorOverlayPackage));
+ mOverlayProvider.addColorOverlay(builder, colorOverlayPackage);
} catch (NameNotFoundException | NotFoundException e) {
- Log.d(TAG, "Didn't find color overlay for default theme, will use system default", e);
- addSystemDefaultColor(builder);
+ Log.d(TAG, "Didn't find color overlay for default theme, will use system default");
+ mOverlayProvider.addSystemDefaultColor(builder);
}
String fontOverlayPackage = getOverlayPackage(FONT_PREFIX, DEFAULT_THEME_NAME);
try {
- builder.addOverlayPackage(getOverlayCategory(fontOverlayPackage), fontOverlayPackage)
- .setBodyFontFamily(loadTypeface(ResourceConstants.CONFIG_BODY_FONT_FAMILY,
- fontOverlayPackage))
- .setHeadlineFontFamily(loadTypeface(
- ResourceConstants.CONFIG_HEADLINE_FONT_FAMILY,
- fontOverlayPackage));
+ mOverlayProvider.addFontOverlay(builder, fontOverlayPackage);
} catch (NameNotFoundException | NotFoundException e) {
- Log.d(TAG, "Didn't find font overlay for default theme, will use system default", e);
- addSystemDefaultFont(builder);
+ Log.d(TAG, "Didn't find font overlay for default theme, will use system default");
+ mOverlayProvider.addSystemDefaultFont(builder);
}
try {
String shapeOverlayPackage = getOverlayPackage(SHAPE_PREFIX, DEFAULT_THEME_NAME);
- builder.addOverlayPackage(getOverlayCategory(shapeOverlayPackage), shapeOverlayPackage)
- .setShapePath(loadString(CONFIG_ICON_MASK, shapeOverlayPackage));
+ mOverlayProvider.addShapeOverlay(builder ,shapeOverlayPackage, false);
} catch (NameNotFoundException | NotFoundException e) {
- Log.d(TAG, "Didn't find shape overlay for default theme, will use system default", e);
- addSystemDefaultShape(builder);
+ Log.d(TAG, "Didn't find shape overlay for default theme, will use system default");
+ mOverlayProvider.addSystemDefaultShape(builder);
}
- for (String packageName : mShapePreviewIconPackages) {
+ for (String packageName : mOverlayProvider.getShapePreviewIconPackages()) {
try {
builder.addShapePreviewIcon(
mContext.getPackageManager().getApplicationIcon(packageName));
@@ -401,24 +273,20 @@
try {
String iconAndroidOverlayPackage = getOverlayPackage(ICON_ANDROID_PREFIX,
DEFAULT_THEME_NAME);
- builder.addOverlayPackage(getOverlayCategory(iconAndroidOverlayPackage),
- iconAndroidOverlayPackage)
- .addIcon(loadIconPreviewDrawable(ICON_ANDROID_PREFIX,
- iconAndroidOverlayPackage, false));
+ mOverlayProvider.addAndroidIconOverlay(builder, iconAndroidOverlayPackage);
} catch (NameNotFoundException | NotFoundException e) {
- Log.d(TAG, "Didn't find Android icons overlay for default theme, using system default",
- e);
- addSystemDefaultIcons(builder, ANDROID_PACKAGE, ICONS_FOR_PREVIEW);
+ Log.d(TAG, "Didn't find Android icons overlay for default theme, using system default");
+ mOverlayProvider.addSystemDefaultIcons(builder, ANDROID_PACKAGE, ICONS_FOR_PREVIEW);
}
try {
String iconSysUiOverlayPackage = getOverlayPackage(ICON_SYSUI_PREFIX,
DEFAULT_THEME_NAME);
- addSysUiIconOverlay(builder, iconSysUiOverlayPackage);
+ mOverlayProvider.addSysUiIconOverlay(builder, iconSysUiOverlayPackage);
} catch (NameNotFoundException | NotFoundException e) {
- Log.d(TAG, "Didn't find SystemUi icons overlay for default theme, using system default",
- e);
- addSystemDefaultIcons(builder, SYSUI_PACKAGE, ICONS_FOR_PREVIEW);
+ Log.d(TAG,
+ "Didn't find SystemUi icons overlay for default theme, using system default");
+ mOverlayProvider.addSystemDefaultIcons(builder, SYSUI_PACKAGE, ICONS_FOR_PREVIEW);
}
addWallpaper(DEFAULT_THEME_NAME, builder);
@@ -426,84 +294,83 @@
mThemes.add(builder.build(mContext));
}
- private void addSystemDefaultIcons(Builder builder, String packageName, String... previewIcons) {
- try {
- for (String iconName : previewIcons) {
- builder.addIcon(loadIconPreviewDrawable(iconName, packageName, true));
- }
- } catch (NameNotFoundException | NotFoundException e) {
- Log.w(TAG, "Didn't find android package icons, will skip preview", e);
+ @Override
+ public void storeCustomTheme(CustomTheme theme) {
+ if (mThemes == null) {
+ fetch(options -> {
+ addCustomThemeAndStore(theme);
+ }, false);
+ } else {
+ addCustomThemeAndStore(theme);
}
}
- private void addSystemDefaultShape(Builder builder) {
- Resources system = Resources.getSystem();
- String iconMaskPath = system.getString(system.getIdentifier(CONFIG_ICON_MASK,
- "string", ANDROID_PACKAGE));
- builder.setShapePath(iconMaskPath)
- .setBottomSheetCornerRadius(
- system.getDimensionPixelOffset(
- system.getIdentifier(CONFIG_CORNERRADIUS,
- "dimen", ANDROID_PACKAGE)));
- }
-
- private void addSystemDefaultColor(Builder builder) {
- Resources system = Resources.getSystem();
- int colorAccentLight = system.getColor(
- system.getIdentifier(ACCENT_COLOR_LIGHT_NAME, "color", ANDROID_PACKAGE), null);
- builder.setColorAccentLight(colorAccentLight);
-
- int colorAccentDark = system.getColor(
- system.getIdentifier(ACCENT_COLOR_DARK_NAME, "color", ANDROID_PACKAGE), null);
- builder.setColorAccentDark(colorAccentDark);
- }
-
- private void addSystemDefaultFont(Builder builder) {
- Resources system = Resources.getSystem();
- String headlineFontFamily = system.getString(system.getIdentifier(
- ResourceConstants.CONFIG_HEADLINE_FONT_FAMILY,"string", ANDROID_PACKAGE));
- String bodyFontFamily = system.getString(system.getIdentifier(
- ResourceConstants.CONFIG_BODY_FONT_FAMILY,
- "string", ANDROID_PACKAGE));
- builder.setHeadlineFontFamily(Typeface.create(headlineFontFamily, Typeface.NORMAL))
- .setBodyFontFamily(Typeface.create(bodyFontFamily, Typeface.NORMAL));
- }
-
- @Override
- public void storeCustomTheme(CustomTheme theme) {
- mCustomizationPreferences.storeCustomTheme(theme.getSerializedPackages());
+ private void addCustomThemeAndStore(CustomTheme theme) {
+ mThemes.add(theme);
+ JSONArray themesArray = new JSONArray();
+ mThemes.stream()
+ .filter(themeBundle -> themeBundle instanceof CustomTheme
+ && !themeBundle.getPackagesByCategory().isEmpty())
+ .forEachOrdered(themeBundle -> themesArray.put(themeBundle.getJsonPackages()));
+ mCustomizationPreferences.storeCustomThemes(themesArray.toString());
}
@Override
public void removeCustomTheme(CustomTheme theme) {
- //TODO: add support for multiple custom themes.
- mCustomizationPreferences.storeCustomTheme("");
+ JSONArray themesArray = new JSONArray();
+ mThemes.stream()
+ .filter(themeBundle -> themeBundle instanceof CustomTheme)
+ .forEachOrdered(themeBundle -> {
+ if (!themeBundle.equals(theme)) {
+ themesArray.put(themeBundle.getJsonPackages());
+ }
+ });
+ mCustomizationPreferences.storeCustomThemes(themesArray.toString());
}
- private void addCustomTheme() {
- String serializedTheme = mCustomizationPreferences.getSerializedCustomTheme();
- if (TextUtils.isEmpty(serializedTheme)) {
- mThemes.add(new CustomTheme(mContext.getString(R.string.custom_theme_title),
- new HashMap<>(), null));
- return;
+ private void addCustomThemes() {
+ String serializedThemes = mCustomizationPreferences.getSerializedCustomThemes();
+ int customThemesCount = 0;
+ if (!TextUtils.isEmpty(serializedThemes)) {
+ try {
+ JSONArray customThemes = new JSONArray(serializedThemes);
+ for (int i = 0; i < customThemes.length(); i++) {
+ ThemeBundle.Builder builder = convertJsonToBuilder(
+ customThemes.getJSONObject(i));
+ if (builder != null) {
+ builder.setTitle(mContext.getString(R.string.custom_theme_title,
+ customThemesCount + 1));
+ mThemes.add(builder.build(mContext));
+ } else {
+ Log.w(TAG, "Couldn't read stored custom theme, resetting");
+ mThemes.add(new CustomTheme(mContext.getString(R.string.custom_theme_title,
+ customThemesCount + 1), new HashMap<>(), null));
+ }
+ customThemesCount++;
+ }
+ } catch (JSONException e) {
+ Log.w(TAG, "Couldn't read stored custom theme, resetting", e);
+ mThemes.add(new CustomTheme(mContext.getString(R.string.custom_theme_title,
+ customThemesCount + 1), new HashMap<>(), null));
+ }
}
- ThemeBundle.Builder builder = parseCustomTheme(serializedTheme);
- if (builder != null) {
- builder.setTitle(mContext.getString(R.string.custom_theme_title));
- mThemes.add(builder.build(mContext));
- } else {
- Log.w(TAG, "Couldn't read stored custom theme, resetting");
- mThemes.add(new CustomTheme(mContext.getString(R.string.custom_theme_title),
- new HashMap<>(), null));
- }
+
+ // Add an empty one at the end.
+ mThemes.add(new CustomTheme(mContext.getString(R.string.custom_theme_title,
+ customThemesCount + 1), new HashMap<>(), null));
+
}
@Override
- public Builder parseCustomTheme(String serializedTheme) {
+ public Builder parseCustomTheme(String serializedTheme) throws JSONException {
+ JSONObject theme = new JSONObject(serializedTheme);
+ return convertJsonToBuilder(theme);
+ }
+
+ @Nullable
+ private Builder convertJsonToBuilder(JSONObject theme) throws JSONException {
try {
Map<String, String> customPackages = new HashMap<>();
-
- JSONObject theme = new JSONObject(serializedTheme);
Iterator<String> keysIterator = theme.keys();
while (keysIterator.hasNext()) {
@@ -511,94 +378,30 @@
customPackages.put(category, theme.getString(category));
}
CustomTheme.Builder builder = new CustomTheme.Builder();
- builder.setTitle(mContext.getString(R.string.custom_theme_title));
- addShapeOverlay(builder, customPackages.get(OVERLAY_CATEGORY_SHAPE));
- addFontOverlay(builder, customPackages.get(OVERLAY_CATEGORY_FONT));
- addColorOverlay(builder, customPackages.get(OVERLAY_CATEGORY_COLOR));
- addAndroidIconOverlay(builder, customPackages.get(OVERLAY_CATEGORY_ICON_ANDROID));
- addSysUiIconOverlay(builder, customPackages.get(OVERLAY_CATEGORY_ICON_SYSUI));
- addNoPreviewIconOverlay(builder, customPackages.get(OVERLAY_CATEGORY_ICON_SETTINGS));
- addNoPreviewIconOverlay(builder, customPackages.get(OVERLAY_CATEGORY_ICON_LAUNCHER));
- addNoPreviewIconOverlay(builder, customPackages.get(OVERLAY_CATEGORY_ICON_THEMEPICKER));
+ mOverlayProvider.addShapeOverlay(builder,
+ customPackages.get(OVERLAY_CATEGORY_SHAPE));
+ mOverlayProvider.addFontOverlay(builder,
+ customPackages.get(OVERLAY_CATEGORY_FONT));
+ mOverlayProvider.addColorOverlay(builder,
+ customPackages.get(OVERLAY_CATEGORY_COLOR));
+ mOverlayProvider.addAndroidIconOverlay(builder,
+ customPackages.get(OVERLAY_CATEGORY_ICON_ANDROID));
+ mOverlayProvider.addSysUiIconOverlay(builder,
+ customPackages.get(OVERLAY_CATEGORY_ICON_SYSUI));
+ mOverlayProvider.addNoPreviewIconOverlay(builder,
+ customPackages.get(OVERLAY_CATEGORY_ICON_SETTINGS));
+ mOverlayProvider.addNoPreviewIconOverlay(builder,
+ customPackages.get(OVERLAY_CATEGORY_ICON_LAUNCHER));
+ mOverlayProvider.addNoPreviewIconOverlay(builder,
+ customPackages.get(OVERLAY_CATEGORY_ICON_THEMEPICKER));
return builder;
- } catch (JSONException | NameNotFoundException | NotFoundException e) {
+ } catch (NameNotFoundException | NotFoundException e) {
Log.i(TAG, "Couldn't parse serialized custom theme", e);
return null;
}
}
- private String getOverlayPackage(String prefix, String themeName) {
- return getItemStringFromStub(prefix, themeName);
- }
-
- private ResourceAsset getDrawableResourceAsset(String prefix, String themeName) {
- int drawableResId = mStubApkResources.getIdentifier(prefix + themeName,
- "drawable", mStubPackageName);
- return drawableResId == 0 ? null : new ResourceAsset(mStubApkResources, drawableResId,
- RequestOptions.fitCenterTransform());
- }
-
- private Typeface loadTypeface(String configName, String fontOverlayPackage)
- throws NameNotFoundException, NotFoundException {
-
- // TODO(santie): check for font being present in system
-
- Resources overlayRes = mContext.getPackageManager()
- .getResourcesForApplication(fontOverlayPackage);
-
- String fontFamily = overlayRes.getString(overlayRes.getIdentifier(configName,
- "string", fontOverlayPackage));
- return Typeface.create(fontFamily, Typeface.NORMAL);
- }
-
- private int loadColor(String colorName, String colorPackage)
- throws NameNotFoundException, NotFoundException {
-
- Resources overlayRes = mContext.getPackageManager()
- .getResourcesForApplication(colorPackage);
- return overlayRes.getColor(overlayRes.getIdentifier(colorName, "color", colorPackage),
- null);
- }
-
- private String loadString(String stringName, String packageName)
- throws NameNotFoundException, NotFoundException {
-
- Resources overlayRes = mContext.getPackageManager().getResourcesForApplication(packageName);
- return overlayRes.getString(overlayRes.getIdentifier(stringName, "string", packageName));
- }
-
- @Dimension
- private int loadDimen(String dimenName, String packageName)
- throws NameNotFoundException, NotFoundException {
-
- Resources overlayRes = mContext.getPackageManager().getResourcesForApplication(packageName);
- return overlayRes.getDimensionPixelOffset(overlayRes.getIdentifier(
- dimenName, "dimen", packageName));
- }
-
- private boolean loadBoolean(String booleanName, String packageName)
- throws NameNotFoundException, NotFoundException {
-
- Resources overlayRes = mContext.getPackageManager().getResourcesForApplication(packageName);
- return overlayRes.getBoolean(overlayRes.getIdentifier(
- booleanName, "boolean", packageName));
- }
-
- private Drawable loadIconPreviewDrawable(String drawableName, String packageName,
- boolean fromSystem) throws NameNotFoundException, NotFoundException {
-
- Resources packageRes = mContext.getPackageManager().getResourcesForApplication(packageName);
- Resources res = fromSystem ? Resources.getSystem() : packageRes;
- return res.getDrawable(
- packageRes.getIdentifier(drawableName, "drawable", packageName), null);
- }
-
- @Nullable
- private String getOverlayCategory(String packageName) {
- OverlayInfo info = mOverlayInfos.get(packageName);
- return info != null ? info.getCategory() : null;
- }
@Override
public ThemeBundle findEquivalent(ThemeBundle other) {
@@ -612,4 +415,15 @@
}
return null;
}
+
+ private String getOverlayPackage(String prefix, String themeName) {
+ return getItemStringFromStub(prefix, themeName);
+ }
+
+ private ResourceAsset getDrawableResourceAsset(String prefix, String themeName) {
+ int drawableResId = mStubApkResources.getIdentifier(prefix + themeName,
+ "drawable", mStubPackageName);
+ return drawableResId == 0 ? null : new ResourceAsset(mStubApkResources, drawableResId,
+ RequestOptions.fitCenterTransform());
+ }
}
diff --git a/src/com/android/customization/model/theme/OverlayThemeExtractor.java b/src/com/android/customization/model/theme/OverlayThemeExtractor.java
new file mode 100644
index 0000000..3c261e7
--- /dev/null
+++ b/src/com/android/customization/model/theme/OverlayThemeExtractor.java
@@ -0,0 +1,274 @@
+package com.android.customization.model.theme;
+
+import static com.android.customization.model.ResourceConstants.ANDROID_PACKAGE;
+import static com.android.customization.model.ResourceConstants.ICONS_FOR_PREVIEW;
+import static com.android.customization.model.ResourceConstants.SETTINGS_PACKAGE;
+import static com.android.customization.model.ResourceConstants.SYSUI_PACKAGE;
+
+import android.content.Context;
+import android.content.om.OverlayInfo;
+import android.content.om.OverlayManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.Dimension;
+import androidx.annotation.Nullable;
+
+import com.android.customization.model.ResourceConstants;
+import com.android.customization.model.theme.ThemeBundle.Builder;
+import com.android.wallpaper.R;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+
+class OverlayThemeExtractor {
+
+ private static final String TAG = "OverlayThemeExtractor";
+
+ private final Context mContext;
+ private final Map<String, OverlayInfo> mOverlayInfos = new HashMap<>();
+ // List of packages
+ private final String[] mShapePreviewIconPackages;
+
+ OverlayThemeExtractor(Context context) {
+ mContext = context;
+ OverlayManager om = context.getSystemService(OverlayManager.class);
+ Consumer<OverlayInfo> addToMap = overlayInfo -> mOverlayInfos.put(
+ overlayInfo.getPackageName(), overlayInfo);
+
+ UserHandle user = UserHandle.of(UserHandle.myUserId());
+ om.getOverlayInfosForTarget(ANDROID_PACKAGE, user).forEach(addToMap);
+ om.getOverlayInfosForTarget(SYSUI_PACKAGE, user).forEach(addToMap);
+ om.getOverlayInfosForTarget(SETTINGS_PACKAGE, user).forEach(addToMap);
+ om.getOverlayInfosForTarget(ResourceConstants.getLauncherPackage(context), user)
+ .forEach(addToMap);
+ om.getOverlayInfosForTarget(context.getPackageName(), user).forEach(addToMap);
+
+ mShapePreviewIconPackages = context.getResources().getStringArray(
+ R.array.icon_shape_preview_packages);
+ }
+
+ void addColorOverlay(Builder builder, String colorOverlayPackage)
+ throws NameNotFoundException {
+ if (!TextUtils.isEmpty(colorOverlayPackage)) {
+ builder.addOverlayPackage(getOverlayCategory(colorOverlayPackage),
+ colorOverlayPackage)
+ .setColorAccentLight(loadColor(ResourceConstants.ACCENT_COLOR_LIGHT_NAME,
+ colorOverlayPackage))
+ .setColorAccentDark(loadColor(ResourceConstants.ACCENT_COLOR_DARK_NAME,
+ colorOverlayPackage));
+ } else {
+ addSystemDefaultColor(builder);
+ }
+ }
+
+ void addShapeOverlay(Builder builder, String shapeOverlayPackage)
+ throws NameNotFoundException {
+ addShapeOverlay(builder, shapeOverlayPackage, true);
+ }
+
+ void addShapeOverlay(Builder builder, String shapeOverlayPackage, boolean addPreview)
+ throws NameNotFoundException {
+ if (!TextUtils.isEmpty(shapeOverlayPackage)) {
+ builder.addOverlayPackage(getOverlayCategory(shapeOverlayPackage),
+ shapeOverlayPackage)
+ .setShapePath(
+ loadString(ResourceConstants.CONFIG_ICON_MASK, shapeOverlayPackage))
+ .setBottomSheetCornerRadius(
+ loadDimen(ResourceConstants.CONFIG_CORNERRADIUS, shapeOverlayPackage));
+ } else {
+ addSystemDefaultShape(builder);
+ }
+ if (addPreview) {
+ addShapePreviewIcons(builder);
+ }
+ }
+
+ private void addShapePreviewIcons(Builder builder) {
+ for (String packageName : mShapePreviewIconPackages) {
+ try {
+ builder.addShapePreviewIcon(
+ mContext.getPackageManager().getApplicationIcon(
+ packageName));
+ } catch (NameNotFoundException e) {
+ Log.d(TAG, "Couldn't find app " + packageName
+ + ", won't use it for icon shape preview");
+ }
+ }
+ }
+
+ void addNoPreviewIconOverlay(Builder builder, String overlayPackage) {
+ if (!TextUtils.isEmpty(overlayPackage)) {
+ builder.addOverlayPackage(getOverlayCategory(overlayPackage),
+ overlayPackage);
+ }
+ }
+
+ void addSysUiIconOverlay(Builder builder, String iconSysUiOverlayPackage)
+ throws NameNotFoundException {
+ if (!TextUtils.isEmpty(iconSysUiOverlayPackage)) {
+ addIconOverlay(builder, iconSysUiOverlayPackage);
+ }
+ }
+
+ void addAndroidIconOverlay(Builder builder, String iconAndroidOverlayPackage)
+ throws NameNotFoundException {
+ if (!TextUtils.isEmpty(iconAndroidOverlayPackage)) {
+ addIconOverlay(builder, iconAndroidOverlayPackage, ICONS_FOR_PREVIEW);
+ } else {
+ addSystemDefaultIcons(builder, ANDROID_PACKAGE, ICONS_FOR_PREVIEW);
+ }
+ }
+
+ void addIconOverlay(Builder builder, String packageName, String... previewIcons)
+ throws NameNotFoundException {
+ builder.addOverlayPackage(getOverlayCategory(packageName), packageName);
+ for (String iconName : previewIcons) {
+ builder.addIcon(loadIconPreviewDrawable(iconName, packageName, false));
+ }
+ }
+
+ void addFontOverlay(Builder builder, String fontOverlayPackage)
+ throws NameNotFoundException {
+ if (!TextUtils.isEmpty(fontOverlayPackage)) {
+ builder.addOverlayPackage(getOverlayCategory(fontOverlayPackage),
+ fontOverlayPackage)
+ .setBodyFontFamily(loadTypeface(
+ ResourceConstants.CONFIG_BODY_FONT_FAMILY,
+ fontOverlayPackage))
+ .setHeadlineFontFamily(loadTypeface(
+ ResourceConstants.CONFIG_HEADLINE_FONT_FAMILY,
+ fontOverlayPackage));
+ } else {
+ addSystemDefaultFont(builder);
+ }
+ }
+
+ void addSystemDefaultIcons(Builder builder, String packageName,
+ String... previewIcons) {
+ try {
+ for (String iconName : previewIcons) {
+ builder.addIcon(loadIconPreviewDrawable(iconName, packageName, true));
+ }
+ } catch (NameNotFoundException | NotFoundException e) {
+ Log.w(TAG, "Didn't find android package icons, will skip preview", e);
+ }
+ }
+
+ void addSystemDefaultShape(Builder builder) {
+ Resources system = Resources.getSystem();
+ String iconMaskPath = system.getString(
+ system.getIdentifier(ResourceConstants.CONFIG_ICON_MASK,
+ "string", ResourceConstants.ANDROID_PACKAGE));
+ builder.setShapePath(iconMaskPath)
+ .setBottomSheetCornerRadius(
+ system.getDimensionPixelOffset(
+ system.getIdentifier(ResourceConstants.CONFIG_CORNERRADIUS,
+ "dimen", ResourceConstants.ANDROID_PACKAGE)));
+ }
+
+ void addSystemDefaultColor(Builder builder) {
+ Resources system = Resources.getSystem();
+ int colorAccentLight = system.getColor(
+ system.getIdentifier(ResourceConstants.ACCENT_COLOR_LIGHT_NAME, "color",
+ ResourceConstants.ANDROID_PACKAGE), null);
+ builder.setColorAccentLight(colorAccentLight);
+
+ int colorAccentDark = system.getColor(
+ system.getIdentifier(ResourceConstants.ACCENT_COLOR_DARK_NAME, "color",
+ ResourceConstants.ANDROID_PACKAGE), null);
+ builder.setColorAccentDark(colorAccentDark);
+ }
+
+ void addSystemDefaultFont(Builder builder) {
+ Resources system = Resources.getSystem();
+ String headlineFontFamily = system.getString(system.getIdentifier(
+ ResourceConstants.CONFIG_HEADLINE_FONT_FAMILY, "string",
+ ResourceConstants.ANDROID_PACKAGE));
+ String bodyFontFamily = system.getString(system.getIdentifier(
+ ResourceConstants.CONFIG_BODY_FONT_FAMILY,
+ "string", ResourceConstants.ANDROID_PACKAGE));
+ builder.setHeadlineFontFamily(Typeface.create(headlineFontFamily, Typeface.NORMAL))
+ .setBodyFontFamily(Typeface.create(bodyFontFamily, Typeface.NORMAL));
+ }
+
+ Typeface loadTypeface(String configName, String fontOverlayPackage)
+ throws NameNotFoundException, NotFoundException {
+
+ // TODO(santie): check for font being present in system
+
+ Resources overlayRes = mContext.getPackageManager()
+ .getResourcesForApplication(fontOverlayPackage);
+
+ String fontFamily = overlayRes.getString(overlayRes.getIdentifier(configName,
+ "string", fontOverlayPackage));
+ return Typeface.create(fontFamily, Typeface.NORMAL);
+ }
+
+ int loadColor(String colorName, String colorPackage)
+ throws NameNotFoundException, NotFoundException {
+
+ Resources overlayRes = mContext.getPackageManager()
+ .getResourcesForApplication(colorPackage);
+ return overlayRes.getColor(overlayRes.getIdentifier(colorName, "color", colorPackage),
+ null);
+ }
+
+ String loadString(String stringName, String packageName)
+ throws NameNotFoundException, NotFoundException {
+
+ Resources overlayRes =
+ mContext.getPackageManager().getResourcesForApplication(
+ packageName);
+ return overlayRes.getString(overlayRes.getIdentifier(stringName, "string", packageName));
+ }
+
+ @Dimension
+ int loadDimen(String dimenName, String packageName)
+ throws NameNotFoundException, NotFoundException {
+
+ Resources overlayRes =
+ mContext.getPackageManager().getResourcesForApplication(
+ packageName);
+ return overlayRes.getDimensionPixelOffset(overlayRes.getIdentifier(
+ dimenName, "dimen", packageName));
+ }
+
+ boolean loadBoolean(String booleanName, String packageName)
+ throws NameNotFoundException, NotFoundException {
+
+ Resources overlayRes =
+ mContext.getPackageManager().getResourcesForApplication(
+ packageName);
+ return overlayRes.getBoolean(overlayRes.getIdentifier(
+ booleanName, "boolean", packageName));
+ }
+
+ Drawable loadIconPreviewDrawable(String drawableName, String packageName,
+ boolean fromSystem) throws NameNotFoundException, NotFoundException {
+
+ Resources packageRes =
+ mContext.getPackageManager().getResourcesForApplication(
+ packageName);
+ Resources res = fromSystem ? Resources.getSystem() : packageRes;
+ return res.getDrawable(
+ packageRes.getIdentifier(drawableName, "drawable", packageName), null);
+ }
+
+ @Nullable
+ String getOverlayCategory(String packageName) {
+ OverlayInfo info = mOverlayInfos.get(packageName);
+ return info != null ? info.getCategory() : null;
+ }
+
+ String[] getShapePreviewIconPackages() {
+ return mShapePreviewIconPackages;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/customization/model/theme/ThemeBundle.java b/src/com/android/customization/model/theme/ThemeBundle.java
index 414719e..ad21405 100644
--- a/src/com/android/customization/model/theme/ThemeBundle.java
+++ b/src/com/android/customization/model/theme/ThemeBundle.java
@@ -192,10 +192,17 @@
if (isDefault()) {
return "";
}
+ return getJsonPackages().toString();
+ }
+
+ JSONObject getJsonPackages() {
+ if (isDefault()) {
+ return new JSONObject();
+ }
JSONObject json = new JSONObject(mPackagesByCategory);
// Remove items with null values to avoid deserialization issues.
removeNullValues(json);
- return json.toString();
+ return json;
}
private void removeNullValues(JSONObject json) {
diff --git a/src/com/android/customization/model/theme/ThemeBundleProvider.java b/src/com/android/customization/model/theme/ThemeBundleProvider.java
index cd33a81..578b96c 100644
--- a/src/com/android/customization/model/theme/ThemeBundleProvider.java
+++ b/src/com/android/customization/model/theme/ThemeBundleProvider.java
@@ -21,6 +21,7 @@
import com.android.customization.model.theme.ThemeBundle.Builder;
import com.android.customization.model.theme.custom.CustomTheme;
+import org.json.JSONException;
/**
* Interface for a class that can retrieve Themes from the system.
@@ -43,7 +44,7 @@
void removeCustomTheme(CustomTheme theme);
- @Nullable Builder parseCustomTheme(String serializedTheme);
+ @Nullable Builder parseCustomTheme(String serializedTheme) throws JSONException;
ThemeBundle findEquivalent(ThemeBundle other);
}
diff --git a/src/com/android/customization/model/theme/ThemeManager.java b/src/com/android/customization/model/theme/ThemeManager.java
index d873972..de6a98b 100644
--- a/src/com/android/customization/model/theme/ThemeManager.java
+++ b/src/com/android/customization/model/theme/ThemeManager.java
@@ -164,7 +164,7 @@
private void applyOverlays(ThemeBundle theme, Callback callback) {
boolean allApplied = Settings.Secure.putString(mActivity.getContentResolver(),
ResourceConstants.THEME_SETTING, theme.getSerializedPackages());
- if (theme instanceof CustomTheme) {
+ if (theme instanceof CustomTheme && !((CustomTheme) theme).isDefined()) {
storeCustomTheme((CustomTheme) theme);
}
mCurrentOverlays = null;
diff --git a/src/com/android/customization/model/theme/custom/CustomThemeManager.java b/src/com/android/customization/model/theme/custom/CustomThemeManager.java
index f8e5fbb..5463eb0 100644
--- a/src/com/android/customization/model/theme/custom/CustomThemeManager.java
+++ b/src/com/android/customization/model/theme/custom/CustomThemeManager.java
@@ -31,7 +31,8 @@
private final Map<String, String> mOverlayPackages = new HashMap<>();
private final CustomTheme mOriginalTheme;
- private CustomThemeManager(Map<String, String> overlayPackages, @Nullable CustomTheme originalTheme) {
+ private CustomThemeManager(Map<String, String> overlayPackages,
+ @Nullable CustomTheme originalTheme) {
mOverlayPackages.putAll(overlayPackages);
mOriginalTheme = originalTheme;
}
@@ -53,10 +54,8 @@
return mOverlayPackages;
}
- public CustomTheme buildPartialCustomTheme(Context context) {
- return new CustomTheme(mOriginalTheme != null
- ? mOriginalTheme.getTitle() : context.getString(R.string.custom_theme_title),
- mOverlayPackages, null);
+ public CustomTheme buildPartialCustomTheme(String title) {
+ return new CustomTheme(title, mOverlayPackages, null);
}
@Override
diff --git a/src/com/android/customization/module/CustomizationPreferences.java b/src/com/android/customization/module/CustomizationPreferences.java
index dc7662c..d32143a 100644
--- a/src/com/android/customization/module/CustomizationPreferences.java
+++ b/src/com/android/customization/module/CustomizationPreferences.java
@@ -22,9 +22,9 @@
String KEY_CUSTOM_THEME= "themepicker_custom_theme";
String KEY_VISITED_PREFIX = "themepicker_visited_";
- String getSerializedCustomTheme();
+ String getSerializedCustomThemes();
- void storeCustomTheme(String serializedCustomTheme);
+ void storeCustomThemes(String serializedCustomThemes);
boolean getTabVisited(String id);
diff --git a/src/com/android/customization/module/DefaultCustomizationPreferences.java b/src/com/android/customization/module/DefaultCustomizationPreferences.java
index 202ff49..e6b4d05 100644
--- a/src/com/android/customization/module/DefaultCustomizationPreferences.java
+++ b/src/com/android/customization/module/DefaultCustomizationPreferences.java
@@ -28,13 +28,13 @@
@Override
- public String getSerializedCustomTheme() {
+ public String getSerializedCustomThemes() {
return mSharedPrefs.getString(KEY_CUSTOM_THEME, null);
}
@Override
- public void storeCustomTheme(String serializedCustomTheme) {
- mSharedPrefs.edit().putString(KEY_CUSTOM_THEME, serializedCustomTheme).apply();
+ public void storeCustomThemes(String serializedCustomThemes) {
+ mSharedPrefs.edit().putString(KEY_CUSTOM_THEME, serializedCustomThemes).apply();
}
@Override
diff --git a/src/com/android/customization/picker/theme/CustomThemeActivity.java b/src/com/android/customization/picker/theme/CustomThemeActivity.java
index 40d1fe8..1e8af0a 100644
--- a/src/com/android/customization/picker/theme/CustomThemeActivity.java
+++ b/src/com/android/customization/picker/theme/CustomThemeActivity.java
@@ -55,6 +55,8 @@
import com.android.wallpaper.module.InjectorProvider;
import com.android.wallpaper.module.WallpaperSetter;
+import org.json.JSONException;
+
import java.util.ArrayList;
import java.util.List;
@@ -87,12 +89,17 @@
&& intent.hasExtra(EXTRA_THEME_TITLE)) {
ThemeBundleProvider themeProvider =
new DefaultThemeProvider(this, injector.getCustomizationPreferences(this));
- Builder themeBuilder = themeProvider.parseCustomTheme(
- intent.getStringExtra(EXTRA_THEME_PACKAGES));
- if (themeBuilder != null) {
- themeBuilder.setTitle(intent.getStringExtra(EXTRA_THEME_TITLE));
+ Builder themeBuilder = null;
+ try {
+ themeBuilder = themeProvider.parseCustomTheme(
+ intent.getStringExtra(EXTRA_THEME_PACKAGES));
+ if (themeBuilder != null) {
+ themeBuilder.setTitle(intent.getStringExtra(EXTRA_THEME_TITLE));
+ customTheme = (CustomTheme) themeBuilder.build(this);
+ }
+ } catch (JSONException e) {
+ Log.w(TAG, "Couldn't parse provided custom theme, will override it");
}
- customTheme = (CustomTheme) themeBuilder.build(this);
}
mThemeManager = new ThemeManager(
@@ -166,15 +173,20 @@
if (mCurrentStep < mSteps.size() - 1) {
navigateToStep(mCurrentStep + 1);
} else {
+ CustomTheme originalTheme = mCustomThemeManager.getOriginalTheme();
+
// We're on the last step, apply theme and leave
CustomTheme themeToApply = mCustomThemeManager.buildPartialCustomTheme(
- CustomThemeActivity.this);
+ originalTheme != null
+ ? originalTheme.getTitle()
+ : getString(R.string.custom_theme_title,
+ 0));
// If the current theme is equal to the original theme being edited, then
// don't search for an equivalent, let the user apply the same one by keeping
// it null.
- ThemeBundle equivalent = (mCustomThemeManager.getOriginalTheme() != null
- && mCustomThemeManager.getOriginalTheme().isEquivalent(themeToApply))
+ ThemeBundle equivalent = (originalTheme != null
+ && originalTheme.isEquivalent(themeToApply))
? null : mThemeManager.findThemeByPackages(themeToApply);
if (equivalent != null) {