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