summaryrefslogtreecommitdiff
path: root/src/com/android/customization/model/theme
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/customization/model/theme')
-rw-r--r--src/com/android/customization/model/theme/DefaultThemeProvider.java424
-rw-r--r--src/com/android/customization/model/theme/OverlayThemeExtractor.java293
-rw-r--r--src/com/android/customization/model/theme/ThemeBundle.java432
-rw-r--r--src/com/android/customization/model/theme/ThemeBundleProvider.java51
-rw-r--r--src/com/android/customization/model/theme/ThemeBundledWallpaperInfo.java190
-rw-r--r--src/com/android/customization/model/theme/ThemeManager.java149
-rw-r--r--src/com/android/customization/model/theme/custom/ColorOptionsProvider.java171
-rw-r--r--src/com/android/customization/model/theme/custom/CustomTheme.java106
-rw-r--r--src/com/android/customization/model/theme/custom/CustomThemeManager.java116
-rw-r--r--src/com/android/customization/model/theme/custom/FontOptionsProvider.java86
-rw-r--r--src/com/android/customization/model/theme/custom/IconOptionsProvider.java153
-rw-r--r--src/com/android/customization/model/theme/custom/ShapeOptionsProvider.java154
-rw-r--r--src/com/android/customization/model/theme/custom/ThemeComponentOption.java556
-rw-r--r--src/com/android/customization/model/theme/custom/ThemeComponentOptionProvider.java78
14 files changed, 0 insertions, 2959 deletions
diff --git a/src/com/android/customization/model/theme/DefaultThemeProvider.java b/src/com/android/customization/model/theme/DefaultThemeProvider.java
deleted file mode 100644
index 89067c65..00000000
--- a/src/com/android/customization/model/theme/DefaultThemeProvider.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 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.OVERLAY_CATEGORY_COLOR;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_FONT;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_ANDROID;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_LAUNCHER;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SETTINGS;
-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.SYSUI_PACKAGE;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-
-import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
-import com.android.customization.model.ResourcesApkProvider;
-import com.android.customization.model.theme.ThemeBundle.Builder;
-import com.android.customization.model.theme.ThemeBundle.PreviewInfo.ShapeAppIcon;
-import com.android.customization.model.theme.custom.CustomTheme;
-import com.android.customization.module.CustomizationPreferences;
-import com.android.wallpaper.R;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Default implementation of {@link ThemeBundleProvider} that reads Themes' overlays from a stub APK.
- */
-public class DefaultThemeProvider extends ResourcesApkProvider implements ThemeBundleProvider {
-
- private static final String TAG = "DefaultThemeProvider";
-
- private static final String THEMES_ARRAY = "themes";
- private static final String TITLE_PREFIX = "theme_title_";
- private static final String FONT_PREFIX = "theme_overlay_font_";
- private static final String COLOR_PREFIX = "theme_overlay_color_";
- private static final String SHAPE_PREFIX = "theme_overlay_shape_";
- private static final String ICON_ANDROID_PREFIX = "theme_overlay_icon_android_";
- private static final String ICON_LAUNCHER_PREFIX = "theme_overlay_icon_launcher_";
- private static final String ICON_THEMEPICKER_PREFIX = "theme_overlay_icon_themepicker_";
- private static final String ICON_SETTINGS_PREFIX = "theme_overlay_icon_settings_";
- private static final String ICON_SYSUI_PREFIX = "theme_overlay_icon_sysui_";
-
- private static final String DEFAULT_THEME_NAME= "default";
- private static final String THEME_TITLE_FIELD = "_theme_title";
- private static final String THEME_ID_FIELD = "_theme_id";
-
- private final OverlayThemeExtractor mOverlayProvider;
- private List<ThemeBundle> mThemes;
- private final CustomizationPreferences mCustomizationPreferences;
-
- public DefaultThemeProvider(Context context, CustomizationPreferences customizationPrefs) {
- super(context, context.getString(R.string.themes_stub_package));
- mOverlayProvider = new OverlayThemeExtractor(context);
- mCustomizationPreferences = customizationPrefs;
- }
-
- @Override
- public void fetch(OptionsFetchedListener<ThemeBundle> callback, boolean reload) {
- if (mThemes == null || reload) {
- mThemes = new ArrayList<>();
- loadAll();
- }
-
- if(callback != null) {
- callback.onOptionsLoaded(mThemes);
- }
- }
-
- @Override
- public boolean isAvailable() {
- return mOverlayProvider.isAvailable() && super.isAvailable();
- }
-
- private void loadAll() {
- // Add "Custom" option at the beginning.
- mThemes.add(new CustomTheme.Builder()
- .setId(CustomTheme.newId())
- .setTitle(mContext.getString(R.string.custom_theme))
- .build(mContext));
-
- addDefaultTheme();
-
- String[] themeNames = getItemsFromStub(THEMES_ARRAY);
-
- for (String themeName : themeNames) {
- // Default theme needs special treatment (see #addDefaultTheme())
- if (DEFAULT_THEME_NAME.equals(themeName)) {
- continue;
- }
- ThemeBundle.Builder builder = new Builder();
- try {
- builder.setTitle(mStubApkResources.getString(
- mStubApkResources.getIdentifier(TITLE_PREFIX + themeName,
- "string", mStubPackageName)));
-
- String shapeOverlayPackage = getOverlayPackage(SHAPE_PREFIX, themeName);
- mOverlayProvider.addShapeOverlay(builder, shapeOverlayPackage);
-
- String fontOverlayPackage = getOverlayPackage(FONT_PREFIX, themeName);
- mOverlayProvider.addFontOverlay(builder, fontOverlayPackage);
-
- String colorOverlayPackage = getOverlayPackage(COLOR_PREFIX, themeName);
- mOverlayProvider.addColorOverlay(builder, colorOverlayPackage);
-
- String iconAndroidOverlayPackage = getOverlayPackage(ICON_ANDROID_PREFIX,
- themeName);
-
- mOverlayProvider.addAndroidIconOverlay(builder, iconAndroidOverlayPackage);
-
- String iconSysUiOverlayPackage = getOverlayPackage(ICON_SYSUI_PREFIX, themeName);
-
- mOverlayProvider.addSysUiIconOverlay(builder, iconSysUiOverlayPackage);
-
- String iconLauncherOverlayPackage = getOverlayPackage(ICON_LAUNCHER_PREFIX,
- themeName);
- mOverlayProvider.addNoPreviewIconOverlay(builder, iconLauncherOverlayPackage);
-
- String iconThemePickerOverlayPackage = getOverlayPackage(ICON_THEMEPICKER_PREFIX,
- themeName);
- mOverlayProvider.addNoPreviewIconOverlay(builder,
- iconThemePickerOverlayPackage);
-
- String iconSettingsOverlayPackage = getOverlayPackage(ICON_SETTINGS_PREFIX,
- themeName);
-
- mOverlayProvider.addNoPreviewIconOverlay(builder, iconSettingsOverlayPackage);
-
- mThemes.add(builder.build(mContext));
- } catch (NameNotFoundException | NotFoundException e) {
- Log.w(TAG, String.format("Couldn't load part of theme %s, will skip it", themeName),
- e);
- }
- }
-
- addCustomThemes();
- }
-
- /**
- * 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
- * the default theme.
- */
- private void addDefaultTheme() {
- ThemeBundle.Builder builder = new Builder().asDefault();
-
- int titleId = mStubApkResources.getIdentifier(TITLE_PREFIX + DEFAULT_THEME_NAME,
- "string", mStubPackageName);
- if (titleId > 0) {
- builder.setTitle(mStubApkResources.getString(titleId));
- } else {
- builder.setTitle(mContext.getString(R.string.default_theme_title));
- }
-
- try {
- String colorOverlayPackage = getOverlayPackage(COLOR_PREFIX, DEFAULT_THEME_NAME);
- mOverlayProvider.addColorOverlay(builder, colorOverlayPackage);
- } catch (NameNotFoundException | NotFoundException e) {
- Log.d(TAG, "Didn't find color overlay for default theme, will use system default");
- mOverlayProvider.addSystemDefaultColor(builder);
- }
-
- try {
- String fontOverlayPackage = getOverlayPackage(FONT_PREFIX, DEFAULT_THEME_NAME);
- mOverlayProvider.addFontOverlay(builder, fontOverlayPackage);
- } catch (NameNotFoundException | NotFoundException e) {
- 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);
- mOverlayProvider.addShapeOverlay(builder ,shapeOverlayPackage, false);
- } catch (NameNotFoundException | NotFoundException e) {
- Log.d(TAG, "Didn't find shape overlay for default theme, will use system default");
- mOverlayProvider.addSystemDefaultShape(builder);
- }
-
- List<ShapeAppIcon> icons = new ArrayList<>();
- for (String packageName : mOverlayProvider.getShapePreviewIconPackages()) {
- Drawable icon = null;
- CharSequence name = null;
- try {
- icon = mContext.getPackageManager().getApplicationIcon(packageName);
- ApplicationInfo appInfo = mContext.getPackageManager()
- .getApplicationInfo(packageName, /* flag= */ 0);
- name = mContext.getPackageManager().getApplicationLabel(appInfo);
- } catch (NameNotFoundException e) {
- Log.d(TAG, "Couldn't find app " + packageName + ", won't use it for icon shape"
- + "preview");
- } finally {
- if (icon != null && !TextUtils.isEmpty(name)) {
- icons.add(new ShapeAppIcon(icon, name));
- }
- }
- }
- builder.setShapePreviewIcons(icons);
-
- try {
- String iconAndroidOverlayPackage = getOverlayPackage(ICON_ANDROID_PREFIX,
- DEFAULT_THEME_NAME);
- mOverlayProvider.addAndroidIconOverlay(builder, iconAndroidOverlayPackage);
- } catch (NameNotFoundException | NotFoundException e) {
- 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);
- mOverlayProvider.addSysUiIconOverlay(builder, iconSysUiOverlayPackage);
- } catch (NameNotFoundException | NotFoundException e) {
- Log.d(TAG,
- "Didn't find SystemUi icons overlay for default theme, using system default");
- mOverlayProvider.addSystemDefaultIcons(builder, SYSUI_PACKAGE, ICONS_FOR_PREVIEW);
- }
-
- mThemes.add(builder.build(mContext));
- }
-
- @Override
- public void storeCustomTheme(CustomTheme theme) {
- if (mThemes == null) {
- fetch(options -> {
- addCustomThemeAndStore(theme);
- }, false);
- } else {
- addCustomThemeAndStore(theme);
- }
- }
-
- private void addCustomThemeAndStore(CustomTheme theme) {
- if (!mThemes.contains(theme)) {
- mThemes.add(theme);
- } else {
- mThemes.replaceAll(t -> theme.equals(t) ? theme : t);
- }
- JSONArray themesArray = new JSONArray();
- mThemes.stream()
- .filter(themeBundle -> themeBundle instanceof CustomTheme
- && !themeBundle.getPackagesByCategory().isEmpty())
- .forEachOrdered(themeBundle -> addThemeBundleToArray(themesArray, themeBundle));
- mCustomizationPreferences.storeCustomThemes(themesArray.toString());
- }
-
- private void addThemeBundleToArray(JSONArray themesArray, ThemeBundle themeBundle) {
- JSONObject jsonPackages = themeBundle.getJsonPackages(false);
- try {
- jsonPackages.put(THEME_TITLE_FIELD, themeBundle.getTitle());
- if (themeBundle instanceof CustomTheme) {
- jsonPackages.put(THEME_ID_FIELD, ((CustomTheme)themeBundle).getId());
- }
- } catch (JSONException e) {
- Log.w("Exception saving theme's title", e);
- }
- themesArray.put(jsonPackages);
- }
-
- @Override
- public void removeCustomTheme(CustomTheme theme) {
- JSONArray themesArray = new JSONArray();
- mThemes.stream()
- .filter(themeBundle -> themeBundle instanceof CustomTheme
- && ((CustomTheme) themeBundle).isDefined())
- .forEachOrdered(customTheme -> {
- if (!customTheme.equals(theme)) {
- addThemeBundleToArray(themesArray, customTheme);
- }
- });
- mCustomizationPreferences.storeCustomThemes(themesArray.toString());
- }
-
- 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++) {
- JSONObject jsonTheme = customThemes.getJSONObject(i);
- CustomTheme.Builder builder = new CustomTheme.Builder();
- try {
- convertJsonToBuilder(jsonTheme, builder);
- } catch (NameNotFoundException | NotFoundException e) {
- Log.i(TAG, "Couldn't parse serialized custom theme", e);
- builder = null;
- }
- if (builder != null) {
- if (TextUtils.isEmpty(builder.getTitle())) {
- 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.Builder()
- .setId(CustomTheme.newId())
- .setTitle(mContext.getString(
- R.string.custom_theme_title, customThemesCount + 1))
- .build(mContext));
- }
- customThemesCount++;
- }
- } catch (JSONException e) {
- Log.w(TAG, "Couldn't read stored custom theme, resetting", e);
- mThemes.add(new CustomTheme.Builder()
- .setId(CustomTheme.newId())
- .setTitle(mContext.getString(
- R.string.custom_theme_title, customThemesCount + 1))
- .build(mContext));
- }
- }
- }
-
- @Nullable
- @Override
- public ThemeBundle.Builder parseThemeBundle(String serializedTheme) throws JSONException {
- JSONObject theme = new JSONObject(serializedTheme);
- try {
- ThemeBundle.Builder builder = new ThemeBundle.Builder();
- convertJsonToBuilder(theme, builder);
- return builder;
- } catch (NameNotFoundException | NotFoundException e) {
- Log.i(TAG, "Couldn't parse serialized custom theme", e);
- return null;
- }
- }
-
- @Nullable
- @Override
- public CustomTheme.Builder parseCustomTheme(String serializedTheme) throws JSONException {
- JSONObject theme = new JSONObject(serializedTheme);
- try {
- CustomTheme.Builder builder = new CustomTheme.Builder();
- convertJsonToBuilder(theme, builder);
- return builder;
- } catch (NameNotFoundException | NotFoundException e) {
- Log.i(TAG, "Couldn't parse serialized custom theme", e);
- return null;
- }
- }
-
- private void convertJsonToBuilder(JSONObject theme, ThemeBundle.Builder builder)
- throws JSONException, NameNotFoundException, NotFoundException {
- Map<String, String> customPackages = new HashMap<>();
- Iterator<String> keysIterator = theme.keys();
-
- while (keysIterator.hasNext()) {
- String category = keysIterator.next();
- customPackages.put(category, theme.getString(category));
- }
- 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));
- if (theme.has(THEME_TITLE_FIELD)) {
- builder.setTitle(theme.getString(THEME_TITLE_FIELD));
- }
- if (builder instanceof CustomTheme.Builder && theme.has(THEME_ID_FIELD)) {
- ((CustomTheme.Builder) builder).setId(theme.getString(THEME_ID_FIELD));
- }
- }
-
- @Override
- public ThemeBundle findEquivalent(ThemeBundle other) {
- if (mThemes == null) {
- return null;
- }
- for (ThemeBundle theme : mThemes) {
- if (theme.isEquivalent(other)) {
- return theme;
- }
- }
- return null;
- }
-
- private String getOverlayPackage(String prefix, String themeName) {
- return getItemStringFromStub(prefix, themeName);
- }
-}
diff --git a/src/com/android/customization/model/theme/OverlayThemeExtractor.java b/src/com/android/customization/model/theme/OverlayThemeExtractor.java
deleted file mode 100644
index 816176e7..00000000
--- a/src/com/android/customization/model/theme/OverlayThemeExtractor.java
+++ /dev/null
@@ -1,293 +0,0 @@
-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.ApplicationInfo;
-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.customization.model.theme.ThemeBundle.PreviewInfo.ShapeAppIcon;
-import com.android.wallpaper.R;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-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);
- if (om != null) {
- 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);
- }
-
- boolean isAvailable() {
- return !mOverlayInfos.isEmpty();
- }
-
- 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) {
- List<ShapeAppIcon> icons = new ArrayList<>();
- for (String packageName : mShapePreviewIconPackages) {
- Drawable icon = null;
- CharSequence name = null;
- try {
- icon = mContext.getPackageManager().getApplicationIcon(packageName);
- // Add the shape icon app name.
- ApplicationInfo appInfo = mContext.getPackageManager()
- .getApplicationInfo(packageName, /* flag= */ 0);
- name = mContext.getPackageManager().getApplicationLabel(appInfo);
- } catch (NameNotFoundException e) {
- Log.d(TAG, "Couldn't find app " + packageName
- + ", won't use it for icon shape preview");
- } finally {
- if (icon != null && !TextUtils.isEmpty(name)) {
- icons.add(new ShapeAppIcon(icon, name));
- }
- }
- }
- builder.setShapePreviewIcons(icons);
- }
-
- 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
deleted file mode 100644
index 3a32f257..00000000
--- a/src/com/android/customization/model/theme/ThemeBundle.java
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme;
-
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_FONT;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_ANDROID;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SHAPE;
-import static com.android.customization.model.ResourceConstants.PATH_SIZE;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Path;
-import android.graphics.Typeface;
-import android.graphics.drawable.AdaptiveIconDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.PathShape;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.Dimension;
-import androidx.annotation.Nullable;
-import androidx.core.graphics.PathParser;
-
-import com.android.customization.model.CustomizationManager;
-import com.android.customization.model.CustomizationOption;
-import com.android.customization.model.theme.ThemeBundle.PreviewInfo.ShapeAppIcon;
-import com.android.customization.widget.DynamicAdaptiveIconDrawable;
-import com.android.wallpaper.R;
-import com.android.wallpaper.asset.Asset;
-import com.android.wallpaper.asset.BitmapCachingAsset;
-import com.android.wallpaper.model.WallpaperInfo;
-import com.android.wallpaper.util.ResourceUtils;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Represents a Theme component available in the system as a "persona" bundle.
- * Note that in this context a Theme is not related to Android's Styles, but it's rather an
- * abstraction representing a series of overlays to be applied to the system.
- */
-public class ThemeBundle implements CustomizationOption<ThemeBundle> {
-
- private static final String TAG = "ThemeBundle";
- private final static String EMPTY_JSON = "{}";
- private final static String TIMESTAMP_FIELD = "_applied_timestamp";
-
- private final String mTitle;
- private final PreviewInfo mPreviewInfo;
- private final boolean mIsDefault;
- protected final Map<String, String> mPackagesByCategory;
- private WallpaperInfo mOverrideWallpaper;
- private Asset mOverrideWallpaperAsset;
- private CharSequence mContentDescription;
-
- protected ThemeBundle(String title, Map<String, String> overlayPackages,
- boolean isDefault, PreviewInfo previewInfo) {
- mTitle = title;
- mIsDefault = isDefault;
- mPreviewInfo = previewInfo;
- mPackagesByCategory = Collections.unmodifiableMap(removeNullValues(overlayPackages));
- }
-
- @Override
- public String getTitle() {
- return mTitle;
- }
-
- @Override
- public void bindThumbnailTile(View view) {
- Resources res = view.getContext().getResources();
-
- ((TextView) view.findViewById(R.id.theme_option_font)).setTypeface(
- mPreviewInfo.headlineFontFamily);
- if (mPreviewInfo.shapeDrawable != null) {
- ((ShapeDrawable) mPreviewInfo.shapeDrawable).getPaint().setColor(
- mPreviewInfo.resolveAccentColor(res));
- ((ImageView) view.findViewById(R.id.theme_option_shape)).setImageDrawable(
- mPreviewInfo.shapeDrawable);
- }
- if (!mPreviewInfo.icons.isEmpty()) {
- Drawable icon = mPreviewInfo.icons.get(0).getConstantState().newDrawable().mutate();
- icon.setTint(ResourceUtils.getColorAttr(
- view.getContext(), android.R.attr.textColorSecondary));
- ((ImageView) view.findViewById(R.id.theme_option_icon)).setImageDrawable(
- icon);
- }
- view.setContentDescription(getContentDescription(view.getContext()));
- }
-
- @Override
- public boolean isActive(CustomizationManager<ThemeBundle> manager) {
- ThemeManager themeManager = (ThemeManager) manager;
-
- if (mIsDefault) {
- String serializedOverlays = themeManager.getStoredOverlays();
- return TextUtils.isEmpty(serializedOverlays) || EMPTY_JSON.equals(serializedOverlays);
- } else {
- Map<String, String> currentOverlays = themeManager.getCurrentOverlays();
- return mPackagesByCategory.equals(currentOverlays);
- }
- }
-
- @Override
- public int getLayoutResId() {
- return R.layout.theme_option;
- }
-
- /**
- * This is similar to #equals() but it only compares this theme's packages with the other, that
- * is, it will return true if applying this theme has the same effect of applying the given one.
- */
- public boolean isEquivalent(ThemeBundle other) {
- if (other == null) {
- return false;
- }
- if (mIsDefault) {
- return other.isDefault() || TextUtils.isEmpty(other.getSerializedPackages())
- || EMPTY_JSON.equals(other.getSerializedPackages());
- }
- // Map#equals ensures keys and values are compared.
- return mPackagesByCategory.equals(other.mPackagesByCategory);
- }
-
- public PreviewInfo getPreviewInfo() {
- return mPreviewInfo;
- }
-
- public void setOverrideThemeWallpaper(WallpaperInfo homeWallpaper) {
- mOverrideWallpaper = homeWallpaper;
- mOverrideWallpaperAsset = null;
- }
-
- private Asset getOverrideWallpaperAsset(Context context) {
- if (mOverrideWallpaperAsset == null) {
- mOverrideWallpaperAsset = new BitmapCachingAsset(context,
- mOverrideWallpaper.getThumbAsset(context));
- }
- return mOverrideWallpaperAsset;
- }
-
- boolean isDefault() {
- return mIsDefault;
- }
-
- public Map<String, String> getPackagesByCategory() {
- return mPackagesByCategory;
- }
-
- public String getSerializedPackages() {
- return getJsonPackages(false).toString();
- }
-
- public String getSerializedPackagesWithTimestamp() {
- return getJsonPackages(true).toString();
- }
-
- JSONObject getJsonPackages(boolean insertTimestamp) {
- if (isDefault()) {
- return new JSONObject();
- }
- JSONObject json = new JSONObject(mPackagesByCategory);
- // Remove items with null values to avoid deserialization issues.
- removeNullValues(json);
- if (insertTimestamp) {
- try {
- json.put(TIMESTAMP_FIELD, System.currentTimeMillis());
- } catch (JSONException e) {
- Log.e(TAG, "Couldn't add timestamp to serialized themebundle");
- }
- }
- return json;
- }
-
- private void removeNullValues(JSONObject json) {
- Iterator<String> keys = json.keys();
- Set<String> keysToRemove = new HashSet<>();
- while(keys.hasNext()) {
- String key = keys.next();
- if (json.isNull(key)) {
- keysToRemove.add(key);
- }
- }
- for (String key : keysToRemove) {
- json.remove(key);
- }
- }
-
- private Map<String, String> removeNullValues(Map<String, String> map) {
- return map.entrySet()
- .stream()
- .filter(entry -> entry.getValue() != null)
- .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
- }
-
- protected CharSequence getContentDescription(Context context) {
- if (mContentDescription == null) {
- CharSequence defaultName = context.getString(R.string.default_theme_title);
- if (isDefault()) {
- mContentDescription = defaultName;
- } else {
- PackageManager pm = context.getPackageManager();
- CharSequence fontName = getOverlayName(pm, OVERLAY_CATEGORY_FONT);
- CharSequence iconName = getOverlayName(pm, OVERLAY_CATEGORY_ICON_ANDROID);
- CharSequence shapeName = getOverlayName(pm, OVERLAY_CATEGORY_SHAPE);
- CharSequence colorName = getOverlayName(pm, OVERLAY_CATEGORY_COLOR);
- mContentDescription = context.getString(R.string.theme_description,
- TextUtils.isEmpty(fontName) ? defaultName : fontName,
- TextUtils.isEmpty(iconName) ? defaultName : iconName,
- TextUtils.isEmpty(shapeName) ? defaultName : shapeName,
- TextUtils.isEmpty(colorName) ? defaultName : colorName);
- }
- }
- return mContentDescription;
- }
-
- private CharSequence getOverlayName(PackageManager pm, String overlayCategoryFont) {
- try {
- return pm.getApplicationInfo(
- mPackagesByCategory.get(overlayCategoryFont), 0).loadLabel(pm);
- } catch (PackageManager.NameNotFoundException e) {
- return "";
- }
- }
-
- public static class PreviewInfo {
- public final Typeface bodyFontFamily;
- public final Typeface headlineFontFamily;
- @ColorInt public final int colorAccentLight;
- @ColorInt public final int colorAccentDark;
- public final List<Drawable> icons;
- public final Drawable shapeDrawable;
- public final List<ShapeAppIcon> shapeAppIcons;
- @Dimension public final int bottomSheeetCornerRadius;
-
- /** A class to represent an App icon and its name. */
- public static class ShapeAppIcon {
- private Drawable mIconDrawable;
- private CharSequence mAppName;
-
- public ShapeAppIcon(Drawable icon, CharSequence appName) {
- mIconDrawable = icon;
- mAppName = appName;
- }
-
- /** Returns a copy of app icon drawable. */
- public Drawable getDrawableCopy() {
- return mIconDrawable.getConstantState().newDrawable().mutate();
- }
-
- /** Returns the app name. */
- public CharSequence getAppName() {
- return mAppName;
- }
- }
-
- private PreviewInfo(Context context, Typeface bodyFontFamily, Typeface headlineFontFamily,
- int colorAccentLight, int colorAccentDark, List<Drawable> icons,
- Drawable shapeDrawable, @Dimension int cornerRadius,
- List<ShapeAppIcon> shapeAppIcons) {
- this.bodyFontFamily = bodyFontFamily;
- this.headlineFontFamily = headlineFontFamily;
- this.colorAccentLight = colorAccentLight;
- this.colorAccentDark = colorAccentDark;
- this.icons = icons;
- this.shapeDrawable = shapeDrawable;
- this.bottomSheeetCornerRadius = cornerRadius;
- this.shapeAppIcons = shapeAppIcons;
- }
-
- /**
- * Returns the accent color to be applied corresponding with the current configuration's
- * UI mode.
- * @return one of {@link #colorAccentDark} or {@link #colorAccentLight}
- */
- @ColorInt
- public int resolveAccentColor(Resources res) {
- return (res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
- == Configuration.UI_MODE_NIGHT_YES ? colorAccentDark : colorAccentLight;
- }
- }
-
- public static class Builder {
- protected String mTitle;
- private Typeface mBodyFontFamily;
- private Typeface mHeadlineFontFamily;
- @ColorInt private int mColorAccentLight = -1;
- @ColorInt private int mColorAccentDark = -1;
- private List<Drawable> mIcons = new ArrayList<>();
- private String mPathString;
- private Path mShapePath;
- private boolean mIsDefault;
- @Dimension private int mCornerRadius;
- protected Map<String, String> mPackages = new HashMap<>();
- private List<ShapeAppIcon> mAppIcons = new ArrayList<>();
-
- public ThemeBundle build(Context context) {
- return new ThemeBundle(mTitle, mPackages, mIsDefault, createPreviewInfo(context));
- }
-
- public PreviewInfo createPreviewInfo(Context context) {
- ShapeDrawable shapeDrawable = null;
- List<ShapeAppIcon> shapeIcons = new ArrayList<>();
- Path path = mShapePath;
- if (!TextUtils.isEmpty(mPathString)) {
- path = PathParser.createPathFromPathData(mPathString);
- }
- if (path != null) {
- PathShape shape = new PathShape(path, PATH_SIZE, PATH_SIZE);
- shapeDrawable = new ShapeDrawable(shape);
- shapeDrawable.setIntrinsicHeight((int) PATH_SIZE);
- shapeDrawable.setIntrinsicWidth((int) PATH_SIZE);
- for (ShapeAppIcon icon : mAppIcons) {
- Drawable drawable = icon.mIconDrawable;
- if (drawable instanceof AdaptiveIconDrawable) {
- AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) drawable;
- shapeIcons.add(new ShapeAppIcon(
- new DynamicAdaptiveIconDrawable(adaptiveIcon.getBackground(),
- adaptiveIcon.getForeground(), path),
- icon.getAppName()));
- } else if (drawable instanceof DynamicAdaptiveIconDrawable) {
- shapeIcons.add(icon);
- }
- // TODO: add iconloader library's legacy treatment helper methods for
- // non-adaptive icons
- }
- }
- return new PreviewInfo(context, mBodyFontFamily, mHeadlineFontFamily, mColorAccentLight,
- mColorAccentDark, mIcons, shapeDrawable, mCornerRadius, shapeIcons);
- }
-
- public Map<String, String> getPackages() {
- return Collections.unmodifiableMap(mPackages);
- }
-
- public String getTitle() {
- return mTitle;
- }
-
- public Builder setTitle(String title) {
- mTitle = title;
- return this;
- }
-
- public Builder setBodyFontFamily(@Nullable Typeface bodyFontFamily) {
- mBodyFontFamily = bodyFontFamily;
- return this;
- }
-
- public Builder setHeadlineFontFamily(@Nullable Typeface headlineFontFamily) {
- mHeadlineFontFamily = headlineFontFamily;
- return this;
- }
-
- public Builder setColorAccentLight(@ColorInt int colorAccentLight) {
- mColorAccentLight = colorAccentLight;
- return this;
- }
-
- public Builder setColorAccentDark(@ColorInt int colorAccentDark) {
- mColorAccentDark = colorAccentDark;
- return this;
- }
-
- public Builder addIcon(Drawable icon) {
- mIcons.add(icon);
- return this;
- }
-
- public Builder addOverlayPackage(String category, String packageName) {
- mPackages.put(category, packageName);
- return this;
- }
-
- public Builder setShapePath(String path) {
- mPathString = path;
- return this;
- }
-
- public Builder setShapePath(Path path) {
- mShapePath = path;
- return this;
- }
-
- public Builder asDefault() {
- mIsDefault = true;
- return this;
- }
-
- public Builder setShapePreviewIcons(List<ShapeAppIcon> appIcons) {
- mAppIcons.clear();
- mAppIcons.addAll(appIcons);
- return this;
- }
-
- public Builder setBottomSheetCornerRadius(@Dimension int radius) {
- mCornerRadius = radius;
- return this;
- }
- }
-}
diff --git a/src/com/android/customization/model/theme/ThemeBundleProvider.java b/src/com/android/customization/model/theme/ThemeBundleProvider.java
deleted file mode 100644
index 34342b31..00000000
--- a/src/com/android/customization/model/theme/ThemeBundleProvider.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme;
-
-import androidx.annotation.Nullable;
-
-import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
-import com.android.customization.model.theme.custom.CustomTheme;
-
-import org.json.JSONException;
-
-/**
- * Interface for a class that can retrieve Themes from the system.
- */
-public interface ThemeBundleProvider {
-
- /**
- * Returns whether themes are available in the current setup.
- */
- boolean isAvailable();
-
- /**
- * Retrieve the available themes.
- * @param callback called when the themes have been retrieved (or immediately if cached)
- * @param reload whether to reload themes if they're cached.
- */
- void fetch(OptionsFetchedListener<ThemeBundle> callback, boolean reload);
-
- void storeCustomTheme(CustomTheme theme);
-
- void removeCustomTheme(CustomTheme theme);
-
- @Nullable ThemeBundle.Builder parseThemeBundle(String serializedTheme) throws JSONException;
-
- @Nullable CustomTheme.Builder parseCustomTheme(String serializedTheme) throws JSONException;
-
- ThemeBundle findEquivalent(ThemeBundle other);
-}
diff --git a/src/com/android/customization/model/theme/ThemeBundledWallpaperInfo.java b/src/com/android/customization/model/theme/ThemeBundledWallpaperInfo.java
deleted file mode 100644
index 4f0cd6c7..00000000
--- a/src/com/android/customization/model/theme/ThemeBundledWallpaperInfo.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme;
-
-import android.app.Activity;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.os.Parcel;
-import android.util.Log;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.StringRes;
-
-import com.android.wallpaper.asset.Asset;
-import com.android.wallpaper.asset.ResourceAsset;
-import com.android.wallpaper.model.InlinePreviewIntentFactory;
-import com.android.wallpaper.model.WallpaperInfo;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Represents a wallpaper coming from the resources of the theme bundle container APK.
- */
-public class ThemeBundledWallpaperInfo extends WallpaperInfo {
- public static final Creator<ThemeBundledWallpaperInfo> CREATOR =
- new Creator<ThemeBundledWallpaperInfo>() {
- @Override
- public ThemeBundledWallpaperInfo createFromParcel(Parcel in) {
- return new ThemeBundledWallpaperInfo(in);
- }
-
- @Override
- public ThemeBundledWallpaperInfo[] newArray(int size) {
- return new ThemeBundledWallpaperInfo[size];
- }
- };
-
- private static final String TAG = "ThemeBundledWallpaperInfo";
-
- private final String mPackageName;
- private final String mResName;
- private final String mCollectionId;
- @DrawableRes private final int mDrawableResId;
- @StringRes private final int mTitleResId;
- @StringRes private final int mAttributionResId;
- @StringRes private final int mActionUrlResId;
- private List<String> mAttributions;
- private String mActionUrl;
- private Resources mResources;
- private Asset mAsset;
-
- /**
- * Constructs a new theme-bundled static wallpaper model object.
- *
- * @param drawableResId Resource ID of the raw wallpaper image.
- * @param resName The unique name of the wallpaper resource, e.g. "z_wp001".
- * @param themeName Unique name of the collection this wallpaper belongs in; used for logging.
- * @param titleResId Resource ID of the string for the title attribution.
- * @param attributionResId Resource ID of the string for the first subtitle attribution.
- */
- public ThemeBundledWallpaperInfo(String packageName, String resName, String themeName,
- int drawableResId, int titleResId, int attributionResId, int actionUrlResId) {
- mPackageName = packageName;
- mResName = resName;
- mCollectionId = themeName;
- mDrawableResId = drawableResId;
- mTitleResId = titleResId;
- mAttributionResId = attributionResId;
- mActionUrlResId = actionUrlResId;
- }
-
- private ThemeBundledWallpaperInfo(Parcel in) {
- super(in);
- mPackageName = in.readString();
- mResName = in.readString();
- mCollectionId = in.readString();
- mDrawableResId = in.readInt();
- mTitleResId = in.readInt();
- mAttributionResId = in.readInt();
- mActionUrlResId = in.readInt();
- }
-
- @Override
- public List<String> getAttributions(Context context) {
- if (mAttributions == null) {
- Resources res = getPackageResources(context);
- mAttributions = new ArrayList<>();
- if (mTitleResId != 0) {
- mAttributions.add(res.getString(mTitleResId));
- }
- if (mAttributionResId != 0) {
- mAttributions.add(res.getString(mAttributionResId));
- }
- }
-
- return mAttributions;
- }
-
- @Override
- public String getActionUrl(Context context) {
- if (mActionUrl == null && mActionUrlResId != 0) {
- mActionUrl = getPackageResources(context).getString(mActionUrlResId);
- }
- return mActionUrl;
- }
-
- @Override
- public Asset getAsset(Context context) {
- if (mAsset == null) {
- Resources res = getPackageResources(context);
- mAsset = new ResourceAsset(res, mDrawableResId);
- }
-
- return mAsset;
- }
-
- @Override
- public Asset getThumbAsset(Context context) {
- return getAsset(context);
- }
-
- @Override
- public void showPreview(Activity srcActivity, InlinePreviewIntentFactory factory,
- int requestCode, boolean isAssetIdPresent) {
- try {
- srcActivity.startActivityForResult(factory.newIntent(srcActivity, this,
- isAssetIdPresent), requestCode);
- } catch (ActivityNotFoundException |SecurityException e) {
- Log.e(TAG, "App isn't installed or ThemePicker doesn't have permission to launch", e);
- }
- }
-
- @Override
- public String getCollectionId(Context unused) {
- return mCollectionId;
- }
-
- @Override
- public String getWallpaperId() {
- return mResName;
- }
-
- public String getResName() {
- return mResName;
- }
-
- /**
- * Returns the {@link Resources} instance for the theme bundles stub APK.
- */
- private Resources getPackageResources(Context context) {
- if (mResources != null) {
- return mResources;
- }
-
- try {
- mResources = context.getPackageManager().getResourcesForApplication(mPackageName);
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "Could not get app resources for " + mPackageName);
- }
- return mResources;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeString(mPackageName);
- dest.writeString(mResName);
- dest.writeString(mCollectionId);
- dest.writeInt(mDrawableResId);
- dest.writeInt(mTitleResId);
- dest.writeInt(mAttributionResId);
- dest.writeInt(mActionUrlResId);
- }
-}
diff --git a/src/com/android/customization/model/theme/ThemeManager.java b/src/com/android/customization/model/theme/ThemeManager.java
deleted file mode 100644
index 85241c13..00000000
--- a/src/com/android/customization/model/theme/ThemeManager.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme;
-
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_FONT;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_ANDROID;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_LAUNCHER;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SETTINGS;
-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 android.provider.Settings;
-import android.text.TextUtils;
-
-import androidx.annotation.Nullable;
-import androidx.fragment.app.FragmentActivity;
-
-import com.android.customization.model.CustomizationManager;
-import com.android.customization.model.ResourceConstants;
-import com.android.customization.model.theme.custom.CustomTheme;
-import com.android.customization.module.ThemesUserEventLogger;
-
-import org.json.JSONObject;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class ThemeManager implements CustomizationManager<ThemeBundle> {
-
- public static final Set<String> THEME_CATEGORIES = new HashSet<>();
- static {
- THEME_CATEGORIES.add(OVERLAY_CATEGORY_COLOR);
- THEME_CATEGORIES.add(OVERLAY_CATEGORY_FONT);
- THEME_CATEGORIES.add(OVERLAY_CATEGORY_SHAPE);
- THEME_CATEGORIES.add(OVERLAY_CATEGORY_ICON_ANDROID);
- THEME_CATEGORIES.add(OVERLAY_CATEGORY_ICON_SETTINGS);
- THEME_CATEGORIES.add(OVERLAY_CATEGORY_ICON_SYSUI);
- THEME_CATEGORIES.add(OVERLAY_CATEGORY_ICON_LAUNCHER);
- THEME_CATEGORIES.add(OVERLAY_CATEGORY_ICON_THEMEPICKER);
- }
-
- private final ThemeBundleProvider mProvider;
- private final OverlayManagerCompat mOverlayManagerCompat;
-
- protected final FragmentActivity mActivity;
- private final ThemesUserEventLogger mEventLogger;
-
- private Map<String, String> mCurrentOverlays;
-
- public ThemeManager(ThemeBundleProvider provider, FragmentActivity activity,
- OverlayManagerCompat overlayManagerCompat,
- ThemesUserEventLogger logger) {
- mProvider = provider;
- mActivity = activity;
- mOverlayManagerCompat = overlayManagerCompat;
- mEventLogger = logger;
- }
-
- @Override
- public boolean isAvailable() {
- return mOverlayManagerCompat.isAvailable() && mProvider.isAvailable();
- }
-
- @Override
- public void apply(ThemeBundle theme, Callback callback) {
- applyOverlays(theme, callback);
- }
-
- private void applyOverlays(ThemeBundle theme, Callback callback) {
- boolean allApplied = Settings.Secure.putString(mActivity.getContentResolver(),
- ResourceConstants.THEME_SETTING, theme.getSerializedPackagesWithTimestamp());
- if (theme instanceof CustomTheme) {
- storeCustomTheme((CustomTheme) theme);
- }
- mCurrentOverlays = null;
- if (allApplied) {
- mEventLogger.logThemeApplied(theme, theme instanceof CustomTheme);
- callback.onSuccess();
- } else {
- callback.onError(null);
- }
- }
-
- private void storeCustomTheme(CustomTheme theme) {
- mProvider.storeCustomTheme(theme);
- }
-
- @Override
- public void fetchOptions(OptionsFetchedListener<ThemeBundle> callback, boolean reload) {
- mProvider.fetch(callback, reload);
- }
-
- public Map<String, String> getCurrentOverlays() {
- if (mCurrentOverlays == null) {
- mCurrentOverlays = mOverlayManagerCompat.getEnabledOverlaysForTargets(
- ResourceConstants.getPackagesToOverlay(mActivity));
- mCurrentOverlays.entrySet().removeIf(
- categoryAndPackage -> !THEME_CATEGORIES.contains(categoryAndPackage.getKey()));
- }
- return mCurrentOverlays;
- }
-
- public String getStoredOverlays() {
- return Settings.Secure.getString(mActivity.getContentResolver(),
- ResourceConstants.THEME_SETTING);
- }
-
- public void removeCustomTheme(CustomTheme theme) {
- mProvider.removeCustomTheme(theme);
- }
-
- /**
- * @return an existing ThemeBundle that matches the same packages as the given one, if one
- * exists, or {@code null} otherwise.
- */
- @Nullable
- public ThemeBundle findThemeByPackages(ThemeBundle other) {
- return mProvider.findEquivalent(other);
- }
-
- /**
- * Store empty theme if no theme has been set yet. This will prevent Settings from showing the
- * suggestion to select a theme
- */
- public void storeEmptyTheme() {
- String themeSetting = Settings.Secure.getString(mActivity.getContentResolver(),
- ResourceConstants.THEME_SETTING);
- if (TextUtils.isEmpty(themeSetting)) {
- Settings.Secure.putString(mActivity.getContentResolver(),
- ResourceConstants.THEME_SETTING, new JSONObject().toString());
- }
- }
-}
diff --git a/src/com/android/customization/model/theme/custom/ColorOptionsProvider.java b/src/com/android/customization/model/theme/custom/ColorOptionsProvider.java
deleted file mode 100644
index f3b950b5..00000000
--- a/src/com/android/customization/model/theme/custom/ColorOptionsProvider.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme.custom;
-
-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.ICONS_FOR_PREVIEW;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ANDROID_THEME;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_ANDROID;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SHAPE;
-import static com.android.customization.model.ResourceConstants.PATH_SIZE;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.PathShape;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.core.graphics.PathParser;
-
-import com.android.customization.model.ResourceConstants;
-import com.android.customization.model.theme.OverlayManagerCompat;
-import com.android.customization.model.theme.custom.ThemeComponentOption.ColorOption;
-import com.android.wallpaper.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Implementation of {@link ThemeComponentOptionProvider} that reads {@link ColorOption}s from
- * icon overlays.
- */
-public class ColorOptionsProvider extends ThemeComponentOptionProvider<ColorOption> {
-
- private static final String TAG = "ColorOptionsProvider";
- private final CustomThemeManager mCustomThemeManager;
- private final String mDefaultThemePackage;
-
- public ColorOptionsProvider(Context context, OverlayManagerCompat manager,
- CustomThemeManager customThemeManager) {
- super(context, manager, OVERLAY_CATEGORY_COLOR);
- mCustomThemeManager = customThemeManager;
- // System color is set with a static overlay for android.theme category, so let's try to
- // find that first, and if that's not present, we'll default to System resources.
- // (see #addDefault())
- List<String> themePackages = manager.getOverlayPackagesForCategory(
- OVERLAY_CATEGORY_ANDROID_THEME, UserHandle.myUserId(), ANDROID_PACKAGE);
- mDefaultThemePackage = themePackages.isEmpty() ? null : themePackages.get(0);
- }
-
- @Override
- protected void loadOptions() {
- List<Drawable> previewIcons = new ArrayList<>();
- String iconPackage =
- mCustomThemeManager.getOverlayPackages().get(OVERLAY_CATEGORY_ICON_ANDROID);
- if (TextUtils.isEmpty(iconPackage)) {
- iconPackage = ANDROID_PACKAGE;
- }
- for (String iconName : ICONS_FOR_PREVIEW) {
- try {
- previewIcons.add(loadIconPreviewDrawable(iconName, iconPackage));
- } catch (NameNotFoundException | NotFoundException e) {
- Log.w(TAG, String.format("Couldn't load icon in %s for color preview, will skip it",
- iconPackage), e);
- }
- }
- String shapePackage = mCustomThemeManager.getOverlayPackages().get(OVERLAY_CATEGORY_SHAPE);
- if (TextUtils.isEmpty(shapePackage)) {
- shapePackage = ANDROID_PACKAGE;
- }
- Drawable shape = loadShape(shapePackage);
- addDefault(previewIcons, shape);
- for (String overlayPackage : mOverlayPackages) {
- try {
- Resources overlayRes = getOverlayResources(overlayPackage);
- int lightColor = overlayRes.getColor(
- overlayRes.getIdentifier(ACCENT_COLOR_LIGHT_NAME, "color", overlayPackage),
- null);
- int darkColor = overlayRes.getColor(
- overlayRes.getIdentifier(ACCENT_COLOR_DARK_NAME, "color", overlayPackage),
- null);
- PackageManager pm = mContext.getPackageManager();
- String label = pm.getApplicationInfo(overlayPackage, 0).loadLabel(pm).toString();
- ColorOption option = new ColorOption(overlayPackage, label, lightColor, darkColor);
- option.setPreviewIcons(previewIcons);
- option.setShapeDrawable(shape);
- mOptions.add(option);
- } catch (NameNotFoundException | NotFoundException e) {
- Log.w(TAG, String.format("Couldn't load color overlay %s, will skip it",
- overlayPackage), e);
- }
- }
- }
-
- private void addDefault(List<Drawable> previewIcons, Drawable shape) {
- int lightColor, darkColor;
- Resources system = Resources.getSystem();
- try {
- Resources r = getOverlayResources(mDefaultThemePackage);
- lightColor = r.getColor(
- r.getIdentifier(ACCENT_COLOR_LIGHT_NAME, "color", mDefaultThemePackage),
- null);
- darkColor = r.getColor(
- r.getIdentifier(ACCENT_COLOR_DARK_NAME, "color", mDefaultThemePackage),
- null);
- } catch (NotFoundException | NameNotFoundException e) {
- Log.d(TAG, "Didn't find default color, will use system option", e);
-
- lightColor = system.getColor(
- system.getIdentifier(ACCENT_COLOR_LIGHT_NAME, "color", ANDROID_PACKAGE), null);
-
- darkColor = system.getColor(
- system.getIdentifier(ACCENT_COLOR_DARK_NAME, "color", ANDROID_PACKAGE), null);
- }
- ColorOption option = new ColorOption(null,
- mContext.getString(R.string.default_theme_title), lightColor, darkColor);
- option.setPreviewIcons(previewIcons);
- option.setShapeDrawable(shape);
- mOptions.add(option);
- }
-
- private Drawable loadIconPreviewDrawable(String drawableName, String packageName)
- throws NameNotFoundException, NotFoundException {
-
- Resources overlayRes = getOverlayResources(packageName);
- return overlayRes.getDrawable(
- overlayRes.getIdentifier(drawableName, "drawable", packageName), null);
- }
-
- private Drawable loadShape(String packageName) {
- String path = null;
- try {
- Resources r = getOverlayResources(packageName);
-
- path = ResourceConstants.getIconMask(r, packageName);
- } catch (NameNotFoundException e) {
- Log.d(TAG, String.format("Couldn't load shape icon for %s, skipping.", packageName), e);
- }
- ShapeDrawable shapeDrawable = null;
- if (!TextUtils.isEmpty(path)) {
- PathShape shape = new PathShape(PathParser.createPathFromPathData(path),
- PATH_SIZE, PATH_SIZE);
- shapeDrawable = new ShapeDrawable(shape);
- shapeDrawable.setIntrinsicHeight((int) PATH_SIZE);
- shapeDrawable.setIntrinsicWidth((int) PATH_SIZE);
- }
- return shapeDrawable;
- }
-
-}
diff --git a/src/com/android/customization/model/theme/custom/CustomTheme.java b/src/com/android/customization/model/theme/custom/CustomTheme.java
deleted file mode 100644
index a1ee1066..00000000
--- a/src/com/android/customization/model/theme/custom/CustomTheme.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme.custom;
-
-import android.content.Context;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.customization.model.CustomizationManager;
-import com.android.customization.model.theme.ThemeBundle;
-import com.android.wallpaper.R;
-
-import java.util.Map;
-import java.util.UUID;
-
-public class CustomTheme extends ThemeBundle {
-
- public static String newId() {
- return UUID.randomUUID().toString();
- }
-
- /**
- * Used to uniquely identify a custom theme since names can change.
- */
- private final String mId;
-
- private CustomTheme(@NonNull String id, String title, Map<String, String> overlayPackages,
- @Nullable PreviewInfo previewInfo) {
- super(title, overlayPackages, false, previewInfo);
- mId = id;
- }
-
- public String getId() {
- return mId;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof CustomTheme)) {
- return false;
- }
- CustomTheme other = (CustomTheme) obj;
- return mId.equals(other.mId);
- }
-
- @Override
- public int hashCode() {
- return mId.hashCode();
- }
-
- @Override
- public void bindThumbnailTile(View view) {
- if (isDefined()) {
- super.bindThumbnailTile(view);
- }
- }
-
- @Override
- public int getLayoutResId() {
- return isDefined() ? R.layout.theme_option : R.layout.custom_theme_option;
- }
-
- @Override
- public boolean isActive(CustomizationManager<ThemeBundle> manager) {
- return isDefined() && super.isActive(manager);
- }
-
- @Override
- public boolean isEquivalent(ThemeBundle other) {
- return isDefined() && super.isEquivalent(other);
- }
-
- public boolean isDefined() {
- return getPreviewInfo() != null;
- }
-
- public static class Builder extends ThemeBundle.Builder {
- private String mId;
-
- @Override
- public CustomTheme build(Context context) {
- return new CustomTheme(mId, mTitle, mPackages,
- mPackages.isEmpty() ? null : createPreviewInfo(context));
- }
-
- public Builder setId(String id) {
- mId = id;
- return this;
- }
- }
-}
diff --git a/src/com/android/customization/model/theme/custom/CustomThemeManager.java b/src/com/android/customization/model/theme/custom/CustomThemeManager.java
deleted file mode 100644
index 42d73e60..00000000
--- a/src/com/android/customization/model/theme/custom/CustomThemeManager.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme.custom;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-
-import com.android.customization.model.CustomizationManager;
-import com.android.customization.model.theme.ThemeBundle.PreviewInfo;
-import com.android.customization.model.theme.ThemeBundleProvider;
-import com.android.customization.model.theme.ThemeManager;
-import com.android.customization.model.theme.custom.CustomTheme.Builder;
-
-import org.json.JSONException;
-
-import java.util.Map;
-
-public class CustomThemeManager implements CustomizationManager<ThemeComponentOption> {
-
- private static final String TAG = "CustomThemeManager";
- private static final String KEY_STATE_CURRENT_SELECTION = "CustomThemeManager.currentSelection";
-
- private final CustomTheme mOriginalTheme;
- private CustomTheme.Builder mBuilder;
-
- private CustomThemeManager(Map<String, String> overlayPackages,
- @Nullable CustomTheme originalTheme) {
- mBuilder = new Builder();
- overlayPackages.forEach(mBuilder::addOverlayPackage);
- mOriginalTheme = originalTheme;
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public void apply(ThemeComponentOption option, @Nullable Callback callback) {
- option.buildStep(mBuilder);
- if (callback != null) {
- callback.onSuccess();
- }
- }
-
- public Map<String, String> getOverlayPackages() {
- return mBuilder.getPackages();
- }
-
- public CustomTheme buildPartialCustomTheme(Context context, String id, String title) {
- return ((CustomTheme.Builder)mBuilder.setId(id).setTitle(title)).build(context);
- }
-
- @Override
- public void fetchOptions(OptionsFetchedListener<ThemeComponentOption> callback, boolean reload) {
- //Unused
- }
-
- public CustomTheme getOriginalTheme() {
- return mOriginalTheme;
- }
-
- public PreviewInfo buildCustomThemePreviewInfo(Context context) {
- return mBuilder.createPreviewInfo(context);
- }
-
- /** Saves the custom theme selections while system config changes. */
- public void saveCustomTheme(Context context, Bundle savedInstanceState) {
- CustomTheme customTheme =
- buildPartialCustomTheme(context, /* id= */ null, /* title= */ null);
- savedInstanceState.putString(KEY_STATE_CURRENT_SELECTION,
- customTheme.getSerializedPackages());
- }
-
- /** Reads the saved custom theme after system config changed. */
- public void readCustomTheme(ThemeBundleProvider themeBundleProvider,
- Bundle savedInstanceState) {
- String packages = savedInstanceState.getString(KEY_STATE_CURRENT_SELECTION);
- if (!TextUtils.isEmpty(packages)) {
- try {
- mBuilder = themeBundleProvider.parseCustomTheme(packages);
- } catch (JSONException e) {
- Log.w(TAG, "Couldn't parse provided custom theme.");
- }
- } else {
- Log.w(TAG, "No custom theme being restored.");
- }
- }
-
- public static CustomThemeManager create(
- @Nullable CustomTheme customTheme, ThemeManager themeManager) {
- if (customTheme != null && customTheme.isDefined()) {
- return new CustomThemeManager(customTheme.getPackagesByCategory(), customTheme);
- }
- // Seed the first custom theme with the currently applied theme.
- return new CustomThemeManager(themeManager.getCurrentOverlays(), customTheme);
- }
-
-}
diff --git a/src/com/android/customization/model/theme/custom/FontOptionsProvider.java b/src/com/android/customization/model/theme/custom/FontOptionsProvider.java
deleted file mode 100644
index 53568c9f..00000000
--- a/src/com/android/customization/model/theme/custom/FontOptionsProvider.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme.custom;
-
-import static com.android.customization.model.ResourceConstants.ANDROID_PACKAGE;
-import static com.android.customization.model.ResourceConstants.CONFIG_BODY_FONT_FAMILY;
-import static com.android.customization.model.ResourceConstants.CONFIG_HEADLINE_FONT_FAMILY;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_FONT;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.Typeface;
-import android.util.Log;
-
-import com.android.customization.model.ResourceConstants;
-import com.android.customization.model.theme.OverlayManagerCompat;
-import com.android.customization.model.theme.custom.ThemeComponentOption.FontOption;
-import com.android.wallpaper.R;
-
-/**
- * Implementation of {@link ThemeComponentOptionProvider} that reads {@link FontOption}s from
- * font overlays.
- */
-public class FontOptionsProvider extends ThemeComponentOptionProvider<FontOption> {
-
- private static final String TAG = "FontOptionsProvider";
-
- public FontOptionsProvider(Context context, OverlayManagerCompat manager) {
- super(context, manager, OVERLAY_CATEGORY_FONT);
- }
-
- @Override
- protected void loadOptions() {
- addDefault();
- for (String overlayPackage : mOverlayPackages) {
- try {
- Resources overlayRes = getOverlayResources(overlayPackage);
- Typeface headlineFont = Typeface.create(
- getFontFamily(overlayPackage, overlayRes, CONFIG_HEADLINE_FONT_FAMILY),
- Typeface.NORMAL);
- Typeface bodyFont = Typeface.create(
- getFontFamily(overlayPackage, overlayRes, CONFIG_BODY_FONT_FAMILY),
- Typeface.NORMAL);
- PackageManager pm = mContext.getPackageManager();
- String label = pm.getApplicationInfo(overlayPackage, 0).loadLabel(pm).toString();
- mOptions.add(new FontOption(overlayPackage, label, headlineFont, bodyFont));
- } catch (NameNotFoundException | NotFoundException e) {
- Log.w(TAG, String.format("Couldn't load font overlay %s, will skip it",
- overlayPackage), e);
- }
- }
- }
-
- private void addDefault() {
- Resources system = Resources.getSystem();
- Typeface headlineFont = Typeface.create(system.getString(system.getIdentifier(
- ResourceConstants.CONFIG_HEADLINE_FONT_FAMILY,"string", ANDROID_PACKAGE)),
- Typeface.NORMAL);
- Typeface bodyFont = Typeface.create(system.getString(system.getIdentifier(
- ResourceConstants.CONFIG_BODY_FONT_FAMILY,
- "string", ANDROID_PACKAGE)),
- Typeface.NORMAL);
- mOptions.add(new FontOption(null, mContext.getString(R.string.default_theme_title),
- headlineFont, bodyFont));
- }
-
- private String getFontFamily(String overlayPackage, Resources overlayRes, String configName) {
- return overlayRes.getString(overlayRes.getIdentifier(configName, "string", overlayPackage));
- }
-}
diff --git a/src/com/android/customization/model/theme/custom/IconOptionsProvider.java b/src/com/android/customization/model/theme/custom/IconOptionsProvider.java
deleted file mode 100644
index f7b669b1..00000000
--- a/src/com/android/customization/model/theme/custom/IconOptionsProvider.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme.custom;
-
-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.OVERLAY_CATEGORY_ICON_ANDROID;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_LAUNCHER;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SETTINGS;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SYSUI;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_THEMEPICKER;
-
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
-import android.util.Log;
-
-import com.android.customization.model.ResourceConstants;
-import com.android.customization.model.theme.OverlayManagerCompat;
-import com.android.customization.model.theme.custom.ThemeComponentOption.IconOption;
-import com.android.wallpaper.R;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Implementation of {@link ThemeComponentOptionProvider} that reads {@link IconOption}s from
- * icon overlays.
- */
-public class IconOptionsProvider extends ThemeComponentOptionProvider<IconOption> {
-
- private static final String TAG = "IconOptionsProvider";
-
- private final List<String> mSysUiIconsOverlayPackages = new ArrayList<>();
- private final List<String> mSettingsIconsOverlayPackages = new ArrayList<>();
- private final List<String> mLauncherIconsOverlayPackages = new ArrayList<>();
- private final List<String> mThemePickerIconsOverlayPackages = new ArrayList<>();
-
- public IconOptionsProvider(Context context, OverlayManagerCompat manager) {
- super(context, manager, OVERLAY_CATEGORY_ICON_ANDROID);
- String[] targetPackages = ResourceConstants.getPackagesToOverlay(context);
- mSysUiIconsOverlayPackages.addAll(manager.getOverlayPackagesForCategory(
- OVERLAY_CATEGORY_ICON_SYSUI, UserHandle.myUserId(), targetPackages));
- mSettingsIconsOverlayPackages.addAll(manager.getOverlayPackagesForCategory(
- OVERLAY_CATEGORY_ICON_SETTINGS, UserHandle.myUserId(), targetPackages));
- mLauncherIconsOverlayPackages.addAll(manager.getOverlayPackagesForCategory(
- OVERLAY_CATEGORY_ICON_LAUNCHER, UserHandle.myUserId(), targetPackages));
- mThemePickerIconsOverlayPackages.addAll(manager.getOverlayPackagesForCategory(
- OVERLAY_CATEGORY_ICON_THEMEPICKER, UserHandle.myUserId(), targetPackages));
- }
-
- @Override
- protected void loadOptions() {
- addDefault();
-
- Map<String, IconOption> optionsByPrefix = new HashMap<>();
- for (String overlayPackage : mOverlayPackages) {
- IconOption option = addOrUpdateOption(optionsByPrefix, overlayPackage,
- OVERLAY_CATEGORY_ICON_ANDROID);
- try{
- for (String iconName : ICONS_FOR_PREVIEW) {
- option.addIcon(loadIconPreviewDrawable(iconName, overlayPackage));
- }
- } catch (NotFoundException | NameNotFoundException e) {
- Log.w(TAG, String.format("Couldn't load icon overlay details for %s, will skip it",
- overlayPackage), e);
- }
- }
-
- for (String overlayPackage : mSysUiIconsOverlayPackages) {
- addOrUpdateOption(optionsByPrefix, overlayPackage, OVERLAY_CATEGORY_ICON_SYSUI);
- }
-
- for (String overlayPackage : mSettingsIconsOverlayPackages) {
- addOrUpdateOption(optionsByPrefix, overlayPackage, OVERLAY_CATEGORY_ICON_SETTINGS);
- }
-
- for (String overlayPackage : mLauncherIconsOverlayPackages) {
- addOrUpdateOption(optionsByPrefix, overlayPackage, OVERLAY_CATEGORY_ICON_LAUNCHER);
- }
-
- for (String overlayPackage : mThemePickerIconsOverlayPackages) {
- addOrUpdateOption(optionsByPrefix, overlayPackage, OVERLAY_CATEGORY_ICON_THEMEPICKER);
- }
-
- for (IconOption option : optionsByPrefix.values()) {
- if (option.isValid(mContext)) {
- mOptions.add(option);
- option.setLabel(mContext.getString(R.string.icon_component_label, mOptions.size()));
- }
- }
- }
-
- private IconOption addOrUpdateOption(Map<String, IconOption> optionsByPrefix,
- String overlayPackage, String category) {
- String prefix = overlayPackage.substring(0, overlayPackage.lastIndexOf("."));
- IconOption option;
- if (!optionsByPrefix.containsKey(prefix)) {
- option = new IconOption();
- optionsByPrefix.put(prefix, option);
- } else {
- option = optionsByPrefix.get(prefix);
- }
- option.addOverlayPackage(category, overlayPackage);
- return option;
- }
-
- private Drawable loadIconPreviewDrawable(String drawableName, String packageName)
- throws NameNotFoundException, NotFoundException {
- final Resources resources = ANDROID_PACKAGE.equals(packageName)
- ? Resources.getSystem()
- : mContext.getPackageManager().getResourcesForApplication(packageName);
- return resources.getDrawable(
- resources.getIdentifier(drawableName, "drawable", packageName), null);
- }
-
- private void addDefault() {
- IconOption option = new IconOption();
- option.setLabel(mContext.getString(R.string.default_theme_title));
- try {
- for (String iconName : ICONS_FOR_PREVIEW) {
- option.addIcon(loadIconPreviewDrawable(iconName, ANDROID_PACKAGE));
- }
- } catch (NameNotFoundException | NotFoundException e) {
- Log.w(TAG, "Didn't find SystemUi package icons, will skip option", e);
- }
- option.addOverlayPackage(OVERLAY_CATEGORY_ICON_ANDROID, null);
- option.addOverlayPackage(OVERLAY_CATEGORY_ICON_SYSUI, null);
- option.addOverlayPackage(OVERLAY_CATEGORY_ICON_SETTINGS, null);
- option.addOverlayPackage(OVERLAY_CATEGORY_ICON_LAUNCHER, null);
- option.addOverlayPackage(OVERLAY_CATEGORY_ICON_THEMEPICKER, null);
- mOptions.add(option);
- }
-
-}
diff --git a/src/com/android/customization/model/theme/custom/ShapeOptionsProvider.java b/src/com/android/customization/model/theme/custom/ShapeOptionsProvider.java
deleted file mode 100644
index f93b8920..00000000
--- a/src/com/android/customization/model/theme/custom/ShapeOptionsProvider.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme.custom;
-
-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.OVERLAY_CATEGORY_SHAPE;
-import static com.android.customization.model.ResourceConstants.PATH_SIZE;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.Path;
-import android.graphics.drawable.AdaptiveIconDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.PathShape;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.Dimension;
-import androidx.core.graphics.PathParser;
-
-import com.android.customization.model.ResourceConstants;
-import com.android.customization.model.theme.OverlayManagerCompat;
-import com.android.customization.model.theme.ThemeBundle.PreviewInfo.ShapeAppIcon;
-import com.android.customization.model.theme.custom.ThemeComponentOption.ShapeOption;
-import com.android.customization.widget.DynamicAdaptiveIconDrawable;
-import com.android.wallpaper.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Implementation of {@link ThemeComponentOptionProvider} that reads {@link ShapeOption}s from
- * icon overlays.
- */
-public class ShapeOptionsProvider extends ThemeComponentOptionProvider<ShapeOption> {
-
- private static final String TAG = "ShapeOptionsProvider";
- private final String[] mShapePreviewIconPackages;
- private int mThumbSize;
-
- public ShapeOptionsProvider(Context context, OverlayManagerCompat manager) {
- super(context, manager, OVERLAY_CATEGORY_SHAPE);
- mShapePreviewIconPackages = context.getResources().getStringArray(
- R.array.icon_shape_preview_packages);
- mThumbSize = mContext.getResources().getDimensionPixelSize(
- R.dimen.component_shape_thumb_size);
- }
-
- @Override
- protected void loadOptions() {
- addDefault();
- for (String overlayPackage : mOverlayPackages) {
- try {
- Path path = loadPath(mContext.getPackageManager()
- .getResourcesForApplication(overlayPackage), overlayPackage);
- PackageManager pm = mContext.getPackageManager();
- String label = pm.getApplicationInfo(overlayPackage, 0).loadLabel(pm).toString();
- mOptions.add(new ShapeOption(overlayPackage, label, path,
- loadCornerRadius(overlayPackage), createShapeDrawable(path),
- getShapedAppIcons(path)));
- } catch (NameNotFoundException | NotFoundException e) {
- Log.w(TAG, String.format("Couldn't load shape overlay %s, will skip it",
- overlayPackage), e);
- }
- }
- }
-
- private void addDefault() {
- Resources system = Resources.getSystem();
- Path path = loadPath(system, ANDROID_PACKAGE);
- mOptions.add(new ShapeOption(null, mContext.getString(R.string.default_theme_title), path,
- system.getDimensionPixelOffset(
- system.getIdentifier(ResourceConstants.CONFIG_CORNERRADIUS,
- "dimen", ResourceConstants.ANDROID_PACKAGE)),
- createShapeDrawable(path), getShapedAppIcons(path)));
- }
-
- private ShapeDrawable createShapeDrawable(Path path) {
- PathShape shape = new PathShape(path, PATH_SIZE, PATH_SIZE);
- ShapeDrawable shapeDrawable = new ShapeDrawable(shape);
- shapeDrawable.setIntrinsicHeight(mThumbSize);
- shapeDrawable.setIntrinsicWidth(mThumbSize);
- return shapeDrawable;
- }
-
- private List<ShapeAppIcon> getShapedAppIcons(Path path) {
- List<ShapeAppIcon> shapedAppIcons = new ArrayList<>();
- for (String packageName : mShapePreviewIconPackages) {
- Drawable icon = null;
- CharSequence name = null;
- try {
- Drawable appIcon = mContext.getPackageManager().getApplicationIcon(packageName);
- if (appIcon instanceof AdaptiveIconDrawable) {
- AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) appIcon;
- icon = new DynamicAdaptiveIconDrawable(adaptiveIcon.getBackground(),
- adaptiveIcon.getForeground(), path);
-
- ApplicationInfo appInfo = mContext.getPackageManager()
- .getApplicationInfo(packageName, /* flag= */ 0);
- name = mContext.getPackageManager().getApplicationLabel(appInfo);
- }
- } catch (NameNotFoundException e) {
- Log.d(TAG, "Couldn't find app " + packageName
- + ", won't use it for icon shape preview");
- } finally {
- if (icon != null && !TextUtils.isEmpty(name)) {
- shapedAppIcons.add(new ShapeAppIcon(icon, name));
- }
- }
- }
- return shapedAppIcons;
- }
-
- private Path loadPath(Resources overlayRes, String packageName) {
- String shape = overlayRes.getString(overlayRes.getIdentifier(CONFIG_ICON_MASK, "string",
- packageName));
-
- if (!TextUtils.isEmpty(shape)) {
- return PathParser.createPathFromPathData(shape);
- }
- return null;
- }
-
- @Dimension
- private int loadCornerRadius(String packageName)
- throws NameNotFoundException, NotFoundException {
-
- Resources overlayRes =
- mContext.getPackageManager().getResourcesForApplication(
- packageName);
- return overlayRes.getDimensionPixelOffset(overlayRes.getIdentifier(
- CONFIG_CORNERRADIUS, "dimen", packageName));
- }
-}
diff --git a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java b/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
deleted file mode 100644
index 78be0fc0..00000000
--- a/src/com/android/customization/model/theme/custom/ThemeComponentOption.java
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme.custom;
-
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_FONT;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_ANDROID;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_LAUNCHER;
-import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_ICON_SETTINGS;
-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.getLauncherPackage;
-
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.ColorStateList;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.content.res.Resources.Theme;
-import android.content.res.TypedArray;
-import android.graphics.Path;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.StateListDrawable;
-import android.text.TextUtils;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.CompoundButton;
-import android.widget.ImageView;
-import android.widget.SeekBar;
-import android.widget.Switch;
-import android.widget.TextView;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.Dimension;
-import androidx.annotation.DrawableRes;
-import androidx.annotation.Nullable;
-import androidx.annotation.StringRes;
-import androidx.core.graphics.ColorUtils;
-
-import com.android.customization.model.CustomizationManager;
-import com.android.customization.model.CustomizationOption;
-import com.android.customization.model.ResourceConstants;
-import com.android.customization.model.theme.ThemeBundle.PreviewInfo.ShapeAppIcon;
-import com.android.customization.model.theme.custom.CustomTheme.Builder;
-import com.android.wallpaper.R;
-import com.android.wallpaper.util.ResourceUtils;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Represents an option of a component of a custom Theme (for example, a possible color, or font,
- * shape, etc).
- * Extending classes correspond to each component's options and provide the structure to bind
- * preview and thumbnails.
- * // TODO (santie): refactor the logic to bind preview cards to reuse between ThemeFragment and
- * // here
- */
-public abstract class ThemeComponentOption implements CustomizationOption<ThemeComponentOption> {
-
- protected final Map<String, String> mOverlayPackageNames = new HashMap<>();
-
- protected void addOverlayPackage(String category, String packageName) {
- mOverlayPackageNames.put(category, packageName);
- }
-
- public Map<String, String> getOverlayPackages() {
- return mOverlayPackageNames;
- }
-
- @Override
- public String getTitle() {
- return null;
- }
-
- public abstract void bindPreview(ViewGroup container);
-
- public Builder buildStep(Builder builder) {
- getOverlayPackages().forEach(builder::addOverlayPackage);
- return builder;
- }
-
- public static class FontOption extends ThemeComponentOption {
-
- private final String mLabel;
- private final Typeface mHeadlineFont;
- private final Typeface mBodyFont;
-
- public FontOption(String packageName, String label, Typeface headlineFont,
- Typeface bodyFont) {
- addOverlayPackage(OVERLAY_CATEGORY_FONT, packageName);
- mLabel = label;
- mHeadlineFont = headlineFont;
- mBodyFont = bodyFont;
- }
-
- @Override
- public String getTitle() {
- return null;
- }
-
- @Override
- public void bindThumbnailTile(View view) {
- ((TextView) view.findViewById(R.id.thumbnail_text)).setTypeface(
- mHeadlineFont);
- view.setContentDescription(mLabel);
- }
-
- @Override
- public boolean isActive(CustomizationManager<ThemeComponentOption> manager) {
- CustomThemeManager customThemeManager = (CustomThemeManager) manager;
- return Objects.equals(getOverlayPackages().get(OVERLAY_CATEGORY_FONT),
- customThemeManager.getOverlayPackages().get(OVERLAY_CATEGORY_FONT));
- }
-
- @Override
- public int getLayoutResId() {
- return R.layout.theme_font_option;
- }
-
- @Override
- public void bindPreview(ViewGroup container) {
- container.setContentDescription(
- container.getContext().getString(R.string.font_preview_content_description));
-
- bindPreviewHeader(container, R.string.preview_name_font, R.drawable.ic_font, null);
-
- ViewGroup cardBody = container.findViewById(R.id.theme_preview_card_body_container);
- if (cardBody.getChildCount() == 0) {
- LayoutInflater.from(container.getContext()).inflate(
- R.layout.preview_card_font_content,
- cardBody, true);
- }
- TextView title = container.findViewById(R.id.font_card_title);
- title.setTypeface(mHeadlineFont);
- TextView bodyText = container.findViewById(R.id.font_card_body);
- bodyText.setTypeface(mBodyFont);
- container.findViewById(R.id.font_card_divider).setBackgroundColor(
- title.getCurrentTextColor());
- }
-
- @Override
- public Builder buildStep(Builder builder) {
- builder.setHeadlineFontFamily(mHeadlineFont).setBodyFontFamily(mBodyFont);
- return super.buildStep(builder);
- }
- }
-
- void bindPreviewHeader(ViewGroup container, @StringRes int headerTextResId,
- @DrawableRes int headerIcon, String drawableName) {
- TextView header = container.findViewById(R.id.theme_preview_card_header);
- header.setText(headerTextResId);
-
- Context context = container.getContext();
- Drawable icon;
- if (!TextUtils.isEmpty(drawableName)) {
- try {
- Resources resources = context.getPackageManager()
- .getResourcesForApplication(getLauncherPackage(context));
- icon = resources.getDrawable(resources.getIdentifier(
- drawableName, "drawable", getLauncherPackage(context)), null);
- } catch (NameNotFoundException | NotFoundException e) {
- icon = context.getResources().getDrawable(headerIcon, context.getTheme());
- }
- } else {
- icon = context.getResources().getDrawable(headerIcon, context.getTheme());
- }
- int size = context.getResources().getDimensionPixelSize(R.dimen.card_header_icon_size);
- icon.setBounds(0, 0, size, size);
-
- header.setCompoundDrawables(null, icon, null, null);
- header.setCompoundDrawableTintList(ColorStateList.valueOf(
- header.getCurrentTextColor()));
- }
-
- public static class IconOption extends ThemeComponentOption {
-
- public static final int THUMBNAIL_ICON_POSITION = 0;
- private static int[] mIconIds = {
- R.id.preview_icon_0, R.id.preview_icon_1, R.id.preview_icon_2, R.id.preview_icon_3,
- R.id.preview_icon_4, R.id.preview_icon_5
- };
-
- private List<Drawable> mIcons = new ArrayList<>();
- private String mLabel;
-
- @Override
- public void bindThumbnailTile(View view) {
- Resources res = view.getContext().getResources();
- Drawable icon = mIcons.get(THUMBNAIL_ICON_POSITION)
- .getConstantState().newDrawable().mutate();
- icon.setTint(ResourceUtils.getColorAttr(
- view.getContext(), android.R.attr.textColorSecondary));
- ((ImageView) view.findViewById(R.id.option_icon)).setImageDrawable(
- icon);
- view.setContentDescription(mLabel);
- }
-
- @Override
- public boolean isActive(CustomizationManager<ThemeComponentOption> manager) {
- CustomThemeManager customThemeManager = (CustomThemeManager) manager;
- Map<String, String> themePackages = customThemeManager.getOverlayPackages();
- if (getOverlayPackages().isEmpty()) {
- return themePackages.get(OVERLAY_CATEGORY_ICON_SYSUI) == null &&
- themePackages.get(OVERLAY_CATEGORY_ICON_SETTINGS) == null &&
- themePackages.get(OVERLAY_CATEGORY_ICON_ANDROID) == null &&
- themePackages.get(OVERLAY_CATEGORY_ICON_LAUNCHER) == null &&
- themePackages.get(OVERLAY_CATEGORY_ICON_THEMEPICKER) == null;
- }
- for (Map.Entry<String, String> overlayEntry : getOverlayPackages().entrySet()) {
- if(!Objects.equals(overlayEntry.getValue(),
- themePackages.get(overlayEntry.getKey()))) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public int getLayoutResId() {
- return R.layout.theme_icon_option;
- }
-
- @Override
- public void bindPreview(ViewGroup container) {
- container.setContentDescription(
- container.getContext().getString(R.string.icon_preview_content_description));
-
- bindPreviewHeader(container, R.string.preview_name_icon, R.drawable.ic_widget,
- "ic_widget");
-
- ViewGroup cardBody = container.findViewById(R.id.theme_preview_card_body_container);
- if (cardBody.getChildCount() == 0) {
- LayoutInflater.from(container.getContext()).inflate(
- R.layout.preview_card_icon_content, cardBody, true);
- }
- for (int i = 0; i < mIconIds.length && i < mIcons.size(); i++) {
- ((ImageView) container.findViewById(mIconIds[i])).setImageDrawable(
- mIcons.get(i));
- }
- }
-
- public void addIcon(Drawable previewIcon) {
- mIcons.add(previewIcon);
- }
-
- /**
- * @return whether this icon option has overlays and previews for all the required packages
- */
- public boolean isValid(Context context) {
- return getOverlayPackages().keySet().size() ==
- ResourceConstants.getPackagesToOverlay(context).length;
- }
-
- public void setLabel(String label) {
- mLabel = label;
- }
-
- @Override
- public Builder buildStep(Builder builder) {
- for (Drawable icon : mIcons) {
- builder.addIcon(icon);
- }
- return super.buildStep(builder);
- }
- }
-
- public static class ColorOption extends ThemeComponentOption {
-
- /**
- * Ids of views used to represent quick setting tiles in the color preview screen
- */
- private static int[] COLOR_TILE_IDS = {
- R.id.preview_color_qs_0_bg, R.id.preview_color_qs_1_bg, R.id.preview_color_qs_2_bg
- };
-
- /**
- * Ids of the views for the foreground of the icon, mapping to the corresponding index of
- * the actual icon drawable.
- */
- static int[][] COLOR_TILES_ICON_IDS = {
- new int[]{ R.id.preview_color_qs_0_icon, 0},
- new int[]{ R.id.preview_color_qs_1_icon, 1},
- new int[] { R.id.preview_color_qs_2_icon, 3}
- };
-
- /**
- * Ids of views used to represent control buttons in the color preview screen
- */
- private static int[] COLOR_BUTTON_IDS = {
- R.id.preview_check_selected, R.id.preview_radio_selected,
- R.id.preview_toggle_selected
- };
-
- @ColorInt private int mColorAccentLight;
- @ColorInt private int mColorAccentDark;
- /**
- * Icons shown as example of QuickSettings tiles in the color preview screen.
- */
- private List<Drawable> mIcons = new ArrayList<>();
-
- /**
- * Drawable with the currently selected shape to be used as background of the sample
- * QuickSetting icons in the color preview screen.
- */
- private Drawable mShapeDrawable;
-
- private String mLabel;
-
- ColorOption(String packageName, String label, @ColorInt int lightColor,
- @ColorInt int darkColor) {
- addOverlayPackage(OVERLAY_CATEGORY_COLOR, packageName);
- mLabel = label;
- mColorAccentLight = lightColor;
- mColorAccentDark = darkColor;
- }
-
- @Override
- public void bindThumbnailTile(View view) {
- @ColorInt int color = resolveColor(view.getResources());
- LayerDrawable selectedOption = (LayerDrawable) view.getResources().getDrawable(
- R.drawable.color_chip_hollow, view.getContext().getTheme());
- Drawable unselectedOption = view.getResources().getDrawable(
- R.drawable.color_chip_filled, view.getContext().getTheme());
-
- selectedOption.findDrawableByLayerId(R.id.center_fill).setTintList(
- ColorStateList.valueOf(color));
- unselectedOption.setTintList(ColorStateList.valueOf(color));
-
- StateListDrawable stateListDrawable = new StateListDrawable();
- stateListDrawable.addState(new int[] {android.R.attr.state_activated}, selectedOption);
- stateListDrawable.addState(
- new int[] {-android.R.attr.state_activated}, unselectedOption);
-
- ((ImageView) view.findViewById(R.id.option_tile)).setImageDrawable(stateListDrawable);
- view.setContentDescription(mLabel);
- }
-
- @ColorInt
- private int resolveColor(Resources res) {
- Configuration configuration = res.getConfiguration();
- return (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
- == Configuration.UI_MODE_NIGHT_YES ? mColorAccentDark : mColorAccentLight;
- }
-
- @Override
- public boolean isActive(CustomizationManager<ThemeComponentOption> manager) {
- CustomThemeManager customThemeManager = (CustomThemeManager) manager;
- return Objects.equals(getOverlayPackages().get(OVERLAY_CATEGORY_COLOR),
- customThemeManager.getOverlayPackages().get(OVERLAY_CATEGORY_COLOR));
- }
-
- @Override
- public int getLayoutResId() {
- return R.layout.theme_color_option;
- }
-
- @Override
- public void bindPreview(ViewGroup container) {
- container.setContentDescription(
- container.getContext().getString(R.string.color_preview_content_description));
-
- bindPreviewHeader(container, R.string.preview_name_color, R.drawable.ic_colorize_24px,
- null);
-
- ViewGroup cardBody = container.findViewById(R.id.theme_preview_card_body_container);
- if (cardBody.getChildCount() == 0) {
- LayoutInflater.from(container.getContext()).inflate(
- R.layout.preview_card_color_content, cardBody, true);
- }
- Resources res = container.getResources();
- @ColorInt int accentColor = resolveColor(res);
- @ColorInt int controlGreyColor = ResourceUtils.getColorAttr(
- container.getContext(),
- android.R.attr.textColorTertiary);
- ColorStateList tintList = new ColorStateList(
- new int[][]{
- new int[]{android.R.attr.state_selected},
- new int[]{android.R.attr.state_checked},
- new int[]{-android.R.attr.state_enabled}
- },
- new int[] {
- accentColor,
- accentColor,
- controlGreyColor
- }
- );
-
- for (int i = 0; i < COLOR_BUTTON_IDS.length; i++) {
- CompoundButton button = container.findViewById(COLOR_BUTTON_IDS[i]);
- button.setButtonTintList(tintList);
- }
-
- Switch enabledSwitch = container.findViewById(R.id.preview_toggle_selected);
- enabledSwitch.setThumbTintList(tintList);
- enabledSwitch.setTrackTintList(tintList);
-
- ColorStateList seekbarTintList = ColorStateList.valueOf(accentColor);
- SeekBar seekbar = container.findViewById(R.id.preview_seekbar);
- seekbar.setThumbTintList(seekbarTintList);
- seekbar.setProgressTintList(seekbarTintList);
- seekbar.setProgressBackgroundTintList(seekbarTintList);
- // Disable seekbar
- seekbar.setOnTouchListener((view, motionEvent) -> true);
-
- int iconFgColor = ResourceUtils.getColorAttr(container.getContext(),
- android.R.attr.colorBackground);
- if (!mIcons.isEmpty() && mShapeDrawable != null) {
- for (int i = 0; i < COLOR_TILE_IDS.length; i++) {
- Drawable icon = mIcons.get(COLOR_TILES_ICON_IDS[i][1]).getConstantState()
- .newDrawable();
- icon.setTint(iconFgColor);
- //TODO: load and set the shape.
- Drawable bgShape = mShapeDrawable.getConstantState().newDrawable();
- bgShape.setTint(accentColor);
-
- ImageView bg = container.findViewById(COLOR_TILE_IDS[i]);
- bg.setImageDrawable(bgShape);
- ImageView fg = container.findViewById(COLOR_TILES_ICON_IDS[i][0]);
- fg.setImageDrawable(icon);
- }
- }
- }
-
- public void setPreviewIcons(List<Drawable> icons) {
- mIcons.addAll(icons);
- }
-
- public void setShapeDrawable(@Nullable Drawable shapeDrawable) {
- mShapeDrawable = shapeDrawable;
- }
-
- @Override
- public Builder buildStep(Builder builder) {
- builder.setColorAccentDark(mColorAccentDark).setColorAccentLight(mColorAccentLight);
- return super.buildStep(builder);
- }
- }
-
- public static class ShapeOption extends ThemeComponentOption {
-
- private final LayerDrawable mShape;
- private final List<ShapeAppIcon> mAppIcons;
- private final String mLabel;
- private final Path mPath;
- private final int mCornerRadius;
- private int[] mShapeIconIds = {
- R.id.shape_preview_icon_0, R.id.shape_preview_icon_1, R.id.shape_preview_icon_2,
- R.id.shape_preview_icon_3, R.id.shape_preview_icon_4, R.id.shape_preview_icon_5
- };
-
- ShapeOption(String packageName, String label, Path path,
- @Dimension int cornerRadius, Drawable shapeDrawable,
- List<ShapeAppIcon> appIcons) {
- addOverlayPackage(OVERLAY_CATEGORY_SHAPE, packageName);
- mLabel = label;
- mAppIcons = appIcons;
- mPath = path;
- mCornerRadius = cornerRadius;
- Drawable background = shapeDrawable.getConstantState().newDrawable();
- Drawable foreground = shapeDrawable.getConstantState().newDrawable();
- mShape = new LayerDrawable(new Drawable[]{background, foreground});
- mShape.setLayerGravity(0, Gravity.CENTER);
- mShape.setLayerGravity(1, Gravity.CENTER);
- }
-
- @Override
- public void bindThumbnailTile(View view) {
- ImageView thumb = view.findViewById(R.id.shape_thumbnail);
- Resources res = view.getResources();
- Theme theme = view.getContext().getTheme();
- int borderWidth = 2 * res.getDimensionPixelSize(R.dimen.option_border_width);
-
- Drawable background = mShape.getDrawable(0);
- background.setTintList(res.getColorStateList(R.color.option_border_color, theme));
-
- ShapeDrawable foreground = (ShapeDrawable) mShape.getDrawable(1);
-
- foreground.setIntrinsicHeight(background.getIntrinsicHeight() - borderWidth);
- foreground.setIntrinsicWidth(background.getIntrinsicWidth() - borderWidth);
- TypedArray ta = view.getContext().obtainStyledAttributes(
- new int[]{android.R.attr.colorPrimary});
- int primaryColor = ta.getColor(0, 0);
- ta.recycle();
- int foregroundColor =
- ResourceUtils.getColorAttr(view.getContext(), android.R.attr.textColorPrimary);
-
- foreground.setTint(ColorUtils.blendARGB(primaryColor, foregroundColor, .05f));
-
- thumb.setImageDrawable(mShape);
- view.setContentDescription(mLabel);
- }
-
- @Override
- public boolean isActive(CustomizationManager<ThemeComponentOption> manager) {
- CustomThemeManager customThemeManager = (CustomThemeManager) manager;
- return Objects.equals(getOverlayPackages().get(OVERLAY_CATEGORY_SHAPE),
- customThemeManager.getOverlayPackages().get(OVERLAY_CATEGORY_SHAPE));
- }
-
- @Override
- public int getLayoutResId() {
- return R.layout.theme_shape_option;
- }
-
- @Override
- public void bindPreview(ViewGroup container) {
- container.setContentDescription(
- container.getContext().getString(R.string.shape_preview_content_description));
-
- bindPreviewHeader(container, R.string.preview_name_shape, R.drawable.ic_shapes_24px,
- null);
-
- ViewGroup cardBody = container.findViewById(R.id.theme_preview_card_body_container);
- if (cardBody.getChildCount() == 0) {
- LayoutInflater.from(container.getContext()).inflate(
- R.layout.preview_card_shape_content, cardBody, true);
- }
- for (int i = 0; i < mShapeIconIds.length && i < mAppIcons.size(); i++) {
- ImageView iconView = cardBody.findViewById(mShapeIconIds[i]);
- iconView.setBackground(mAppIcons.get(i).getDrawableCopy());
- }
- }
-
- @Override
- public Builder buildStep(Builder builder) {
- builder.setShapePath(mPath)
- .setBottomSheetCornerRadius(mCornerRadius)
- .setShapePreviewIcons(mAppIcons);
- return super.buildStep(builder);
- }
- }
-}
diff --git a/src/com/android/customization/model/theme/custom/ThemeComponentOptionProvider.java b/src/com/android/customization/model/theme/custom/ThemeComponentOptionProvider.java
deleted file mode 100644
index 992c47cc..00000000
--- a/src/com/android/customization/model/theme/custom/ThemeComponentOptionProvider.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source 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 com.android.customization.model.theme.custom;
-
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.os.UserHandle;
-
-import com.android.customization.model.CustomizationManager.OptionsFetchedListener;
-import com.android.customization.model.ResourceConstants;
-import com.android.customization.model.theme.OverlayManagerCompat;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Base class used to retrieve Custom Theme Component options (eg, different fonts)
- * from the system.
- */
-public abstract class ThemeComponentOptionProvider<T extends ThemeComponentOption> {
-
- protected final Context mContext;
- protected final List<String> mOverlayPackages;
- protected List<T> mOptions;
-
- public ThemeComponentOptionProvider(Context context, OverlayManagerCompat manager,
- String... categories) {
- mContext = context;
- mOverlayPackages = new ArrayList<>();
- for (String category : categories) {
- mOverlayPackages.addAll(manager.getOverlayPackagesForCategory(category,
- UserHandle.myUserId(), ResourceConstants.getPackagesToOverlay(mContext)));
- }
- }
-
- /**
- * Returns whether there are options for this component available in the current setup.
- */
- public boolean isAvailable() {
- return !mOverlayPackages.isEmpty();
- }
-
- /**
- * Retrieve the available options for this component.
- * @param callback called when the themes have been retrieved (or immediately if cached)
- * @param reload whether to reload themes if they're cached.
- */
- public void fetch(OptionsFetchedListener<T> callback, boolean reload) {
- if (mOptions == null || reload) {
- mOptions = new ArrayList<>();
- loadOptions();
- }
-
- if(callback != null) {
- callback.onOptionsLoaded(mOptions);
- }
- }
-
- protected abstract void loadOptions();
-
- protected Resources getOverlayResources(String overlayPackage) throws NameNotFoundException {
- return mContext.getPackageManager().getResourcesForApplication(overlayPackage);
- }
-}