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