1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.customization.model.theme.custom; 17 18 import android.content.Context; 19 import android.os.Bundle; 20 import android.text.TextUtils; 21 import android.util.Log; 22 23 import androidx.annotation.Nullable; 24 25 import com.android.customization.model.CustomizationManager; 26 import com.android.customization.model.theme.ThemeBundle.PreviewInfo; 27 import com.android.customization.model.theme.ThemeBundleProvider; 28 import com.android.customization.model.theme.ThemeManager; 29 import com.android.customization.model.theme.custom.CustomTheme.Builder; 30 31 import org.json.JSONException; 32 33 import java.util.Map; 34 35 public class CustomThemeManager implements CustomizationManager<ThemeComponentOption> { 36 37 private static final String TAG = "CustomThemeManager"; 38 private static final String KEY_STATE_CURRENT_SELECTION = "CustomThemeManager.currentSelection"; 39 40 private final CustomTheme mOriginalTheme; 41 private CustomTheme.Builder mBuilder; 42 CustomThemeManager(Map<String, String> overlayPackages, @Nullable CustomTheme originalTheme)43 private CustomThemeManager(Map<String, String> overlayPackages, 44 @Nullable CustomTheme originalTheme) { 45 mBuilder = new Builder(); 46 overlayPackages.forEach(mBuilder::addOverlayPackage); 47 mOriginalTheme = originalTheme; 48 } 49 50 @Override isAvailable()51 public boolean isAvailable() { 52 return true; 53 } 54 55 @Override apply(ThemeComponentOption option, @Nullable Callback callback)56 public void apply(ThemeComponentOption option, @Nullable Callback callback) { 57 option.buildStep(mBuilder); 58 if (callback != null) { 59 callback.onSuccess(); 60 } 61 } 62 getOverlayPackages()63 public Map<String, String> getOverlayPackages() { 64 return mBuilder.getPackages(); 65 } 66 buildPartialCustomTheme(Context context, String id, String title)67 public CustomTheme buildPartialCustomTheme(Context context, String id, String title) { 68 return ((CustomTheme.Builder)mBuilder.setId(id).setTitle(title)).build(context); 69 } 70 71 @Override fetchOptions(OptionsFetchedListener<ThemeComponentOption> callback, boolean reload)72 public void fetchOptions(OptionsFetchedListener<ThemeComponentOption> callback, boolean reload) { 73 //Unused 74 } 75 getOriginalTheme()76 public CustomTheme getOriginalTheme() { 77 return mOriginalTheme; 78 } 79 buildCustomThemePreviewInfo(Context context)80 public PreviewInfo buildCustomThemePreviewInfo(Context context) { 81 return mBuilder.createPreviewInfo(context); 82 } 83 84 /** Saves the custom theme selections while system config changes. */ saveCustomTheme(Context context, Bundle savedInstanceState)85 public void saveCustomTheme(Context context, Bundle savedInstanceState) { 86 CustomTheme customTheme = 87 buildPartialCustomTheme(context, /* id= */ null, /* title= */ null); 88 savedInstanceState.putString(KEY_STATE_CURRENT_SELECTION, 89 customTheme.getSerializedPackages()); 90 } 91 92 /** Reads the saved custom theme after system config changed. */ readCustomTheme(ThemeBundleProvider themeBundleProvider, Bundle savedInstanceState)93 public void readCustomTheme(ThemeBundleProvider themeBundleProvider, 94 Bundle savedInstanceState) { 95 String packages = savedInstanceState.getString(KEY_STATE_CURRENT_SELECTION); 96 if (!TextUtils.isEmpty(packages)) { 97 try { 98 mBuilder = themeBundleProvider.parseCustomTheme(packages); 99 } catch (JSONException e) { 100 Log.w(TAG, "Couldn't parse provided custom theme."); 101 } 102 } else { 103 Log.w(TAG, "No custom theme being restored."); 104 } 105 } 106 create( @ullable CustomTheme customTheme, ThemeManager themeManager)107 public static CustomThemeManager create( 108 @Nullable CustomTheme customTheme, ThemeManager themeManager) { 109 if (customTheme != null && customTheme.isDefined()) { 110 return new CustomThemeManager(customTheme.getPackagesByCategory(), customTheme); 111 } 112 // Seed the first custom theme with the currently applied theme. 113 return new CustomThemeManager(themeManager.getCurrentOverlays(), customTheme); 114 } 115 116 } 117