1 /*
2  * Copyright (C) 2023 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 
17 package com.android.settingslib.drawer;
18 
19 import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_SUMMARY;
20 import static com.android.settingslib.drawer.SwitchesProvider.METHOD_GET_DYNAMIC_TITLE;
21 import static com.android.settingslib.drawer.TileUtils.EXTRA_CATEGORY_KEY;
22 import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER;
23 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
24 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB;
25 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT;
26 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE;
27 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
28 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
29 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_PENDING_INTENT;
30 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
31 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI;
32 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SWITCH_URI;
33 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
34 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE_URI;
35 
36 import android.app.PendingIntent;
37 import android.content.ContentResolver;
38 import android.content.Context;
39 import android.net.Uri;
40 import android.os.Bundle;
41 
42 import androidx.annotation.DrawableRes;
43 import androidx.annotation.NonNull;
44 import androidx.annotation.StringRes;
45 
46 /**
47  * A controller that manages events for switch.
48  */
49 public abstract class EntryController {
50 
51     private String mAuthority;
52 
53     /**
54      * Returns the key for this switch.
55      */
getKey()56     public abstract String getKey();
57 
58     /**
59      * Returns the {@link MetaData} for this switch.
60      */
getMetaData()61     protected abstract MetaData getMetaData();
62 
63     /**
64      * Notify registered observers that title was updated and attempt to sync changes.
65      */
notifyTitleChanged(Context context)66     public void notifyTitleChanged(Context context) {
67         if (this instanceof DynamicTitle) {
68             notifyChanged(context, METHOD_GET_DYNAMIC_TITLE);
69         }
70     }
71 
72     /**
73      * Notify registered observers that summary was updated and attempt to sync changes.
74      */
notifySummaryChanged(Context context)75     public void notifySummaryChanged(Context context) {
76         if (this instanceof DynamicSummary) {
77             notifyChanged(context, METHOD_GET_DYNAMIC_SUMMARY);
78         }
79     }
80 
setAuthority(String authority)81     void setAuthority(String authority) {
82         mAuthority = authority;
83     }
84 
getBundle()85     Bundle getBundle() {
86         final MetaData metaData = getMetaData();
87         if (metaData == null) {
88             throw new NullPointerException("Should not return null in getMetaData()");
89         }
90 
91         final Bundle bundle = metaData.build();
92         final String uriString = new Uri.Builder()
93                 .scheme(ContentResolver.SCHEME_CONTENT)
94                 .authority(mAuthority)
95                 .build()
96                 .toString();
97         bundle.putString(META_DATA_PREFERENCE_KEYHINT, getKey());
98         if (this instanceof ProviderIcon) {
99             bundle.putString(META_DATA_PREFERENCE_ICON_URI, uriString);
100         }
101         if (this instanceof DynamicTitle) {
102             bundle.putString(META_DATA_PREFERENCE_TITLE_URI, uriString);
103         }
104         if (this instanceof DynamicSummary) {
105             bundle.putString(META_DATA_PREFERENCE_SUMMARY_URI, uriString);
106         }
107         if (this instanceof ProviderSwitch) {
108             bundle.putString(META_DATA_PREFERENCE_SWITCH_URI, uriString);
109         }
110         return bundle;
111     }
112 
notifyChanged(Context context, String method)113     private void notifyChanged(Context context, String method) {
114         final Uri uri = TileUtils.buildUri(mAuthority, method, getKey());
115         context.getContentResolver().notifyChange(uri, null);
116     }
117 
118     /**
119      * Collects all meta data of the item.
120      */
121     protected static class MetaData {
122         private String mCategory;
123         private int mOrder;
124         @DrawableRes
125         private int mIcon;
126         private int mIconBackgroundHint;
127         private int mIconBackgroundArgb;
128         private Boolean mIconTintable;
129         @StringRes
130         private int mTitleId;
131         private String mTitle;
132         @StringRes
133         private int mSummaryId;
134         private String mSummary;
135         private PendingIntent mPendingIntent;
136 
137         /**
138          * @param category the category of the switch. This value must be from {@link CategoryKey}.
139          */
MetaData(@onNull String category)140         public MetaData(@NonNull String category) {
141             mCategory = category;
142         }
143 
144         /**
145          * Set the order of the item that should be displayed on screen. Bigger value items displays
146          * closer on top.
147          */
setOrder(int order)148         public MetaData setOrder(int order) {
149             mOrder = order;
150             return this;
151         }
152 
153         /** Set the icon that should be displayed for the item. */
setIcon(@rawableRes int icon)154         public MetaData setIcon(@DrawableRes int icon) {
155             mIcon = icon;
156             return this;
157         }
158 
159         /** Set the icon background color. The value may or may not be used by Settings app. */
setIconBackgoundHint(int hint)160         public MetaData setIconBackgoundHint(int hint) {
161             mIconBackgroundHint = hint;
162             return this;
163         }
164 
165         /** Set the icon background color as raw ARGB. */
setIconBackgoundArgb(int argb)166         public MetaData setIconBackgoundArgb(int argb) {
167             mIconBackgroundArgb = argb;
168             return this;
169         }
170 
171         /** Specify whether the icon is tintable. */
setIconTintable(boolean tintable)172         public MetaData setIconTintable(boolean tintable) {
173             mIconTintable = tintable;
174             return this;
175         }
176 
177         /** Set the title that should be displayed for the item. */
setTitle(@tringRes int id)178         public MetaData setTitle(@StringRes int id) {
179             mTitleId = id;
180             return this;
181         }
182 
183         /** Set the title that should be displayed for the item. */
setTitle(String title)184         public MetaData setTitle(String title) {
185             mTitle = title;
186             return this;
187         }
188 
189         /** Set the summary text that should be displayed for the item. */
setSummary(@tringRes int id)190         public MetaData setSummary(@StringRes int id) {
191             mSummaryId = id;
192             return this;
193         }
194 
195         /** Set the summary text that should be displayed for the item. */
setSummary(String summary)196         public MetaData setSummary(String summary) {
197             mSummary = summary;
198             return this;
199         }
200 
setPendingIntent(PendingIntent pendingIntent)201         public MetaData setPendingIntent(PendingIntent pendingIntent) {
202             mPendingIntent = pendingIntent;
203             return this;
204         }
205 
build()206         protected Bundle build() {
207             final Bundle bundle = new Bundle();
208             bundle.putString(EXTRA_CATEGORY_KEY, mCategory);
209 
210             if (mOrder != 0) {
211                 bundle.putInt(META_DATA_KEY_ORDER, mOrder);
212             }
213 
214             if (mIcon != 0) {
215                 bundle.putInt(META_DATA_PREFERENCE_ICON, mIcon);
216             }
217             if (mIconBackgroundHint != 0) {
218                 bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_HINT, mIconBackgroundHint);
219             }
220             if (mIconBackgroundArgb != 0) {
221                 bundle.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB, mIconBackgroundArgb);
222             }
223             if (mIconTintable != null) {
224                 bundle.putBoolean(META_DATA_PREFERENCE_ICON_TINTABLE, mIconTintable);
225             }
226 
227             if (mTitleId != 0) {
228                 bundle.putInt(META_DATA_PREFERENCE_TITLE, mTitleId);
229             } else if (mTitle != null) {
230                 bundle.putString(META_DATA_PREFERENCE_TITLE, mTitle);
231             }
232 
233             if (mSummaryId != 0) {
234                 bundle.putInt(META_DATA_PREFERENCE_SUMMARY, mSummaryId);
235             } else if (mSummary != null) {
236                 bundle.putString(META_DATA_PREFERENCE_SUMMARY, mSummary);
237             }
238 
239             if (mPendingIntent != null) {
240                 bundle.putParcelable(META_DATA_PREFERENCE_PENDING_INTENT, mPendingIntent);
241             }
242 
243             return bundle;
244         }
245     }
246 }
247