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.TileUtils.META_DATA_PREFERENCE_KEYHINT; 20 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY; 21 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE; 22 23 import android.content.ContentProvider; 24 import android.content.ContentValues; 25 import android.content.Context; 26 import android.content.pm.ProviderInfo; 27 import android.database.Cursor; 28 import android.net.Uri; 29 import android.os.Bundle; 30 import android.text.TextUtils; 31 import android.util.Log; 32 33 import java.util.ArrayList; 34 import java.util.LinkedHashMap; 35 import java.util.List; 36 import java.util.Map; 37 38 /** 39 * An abstract class for injecting entries to Settings. 40 */ 41 public abstract class EntriesProvider extends ContentProvider { 42 private static final String TAG = "EntriesProvider"; 43 44 public static final String METHOD_GET_ENTRY_DATA = "getEntryData"; 45 public static final String METHOD_GET_PROVIDER_ICON = "getProviderIcon"; 46 public static final String METHOD_GET_DYNAMIC_TITLE = "getDynamicTitle"; 47 public static final String METHOD_GET_DYNAMIC_SUMMARY = "getDynamicSummary"; 48 public static final String METHOD_IS_CHECKED = "isChecked"; 49 public static final String METHOD_ON_CHECKED_CHANGED = "onCheckedChanged"; 50 51 /** 52 * @deprecated use {@link #METHOD_GET_ENTRY_DATA} instead. 53 */ 54 @Deprecated 55 public static final String METHOD_GET_SWITCH_DATA = "getSwitchData"; 56 57 public static final String EXTRA_ENTRY_DATA = "entry_data"; 58 public static final String EXTRA_SWITCH_CHECKED_STATE = "checked_state"; 59 public static final String EXTRA_SWITCH_SET_CHECKED_ERROR = "set_checked_error"; 60 public static final String EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE = "set_checked_error_message"; 61 62 /** 63 * @deprecated use {@link #EXTRA_ENTRY_DATA} instead. 64 */ 65 @Deprecated 66 public static final String EXTRA_SWITCH_DATA = "switch_data"; 67 68 private String mAuthority; 69 private final Map<String, EntryController> mControllerMap = new LinkedHashMap<>(); 70 private final List<Bundle> mEntryDataList = new ArrayList<>(); 71 72 /** 73 * Get a list of {@link EntryController} for this provider. 74 */ createEntryControllers()75 protected abstract List<? extends EntryController> createEntryControllers(); 76 getController(String key)77 protected EntryController getController(String key) { 78 return mControllerMap.get(key); 79 } 80 81 @Override attachInfo(Context context, ProviderInfo info)82 public void attachInfo(Context context, ProviderInfo info) { 83 mAuthority = info.authority; 84 Log.i(TAG, mAuthority); 85 super.attachInfo(context, info); 86 } 87 88 @Override onCreate()89 public boolean onCreate() { 90 final List<? extends EntryController> controllers = createEntryControllers(); 91 if (controllers == null || controllers.isEmpty()) { 92 throw new IllegalArgumentException(); 93 } 94 95 for (EntryController controller : controllers) { 96 final String key = controller.getKey(); 97 if (TextUtils.isEmpty(key)) { 98 throw new NullPointerException("Entry key cannot be null: " 99 + controller.getClass().getSimpleName()); 100 } else if (mControllerMap.containsKey(key)) { 101 throw new IllegalArgumentException("Entry key " + key + " is duplicated by: " 102 + controller.getClass().getSimpleName()); 103 } 104 105 controller.setAuthority(mAuthority); 106 mControllerMap.put(key, controller); 107 if (!(controller instanceof PrimarySwitchController)) { 108 mEntryDataList.add(controller.getBundle()); 109 } 110 } 111 return true; 112 } 113 114 @Override call(String method, String uriString, Bundle extras)115 public Bundle call(String method, String uriString, Bundle extras) { 116 final Bundle bundle = new Bundle(); 117 final String key = extras != null 118 ? extras.getString(META_DATA_PREFERENCE_KEYHINT) 119 : null; 120 if (TextUtils.isEmpty(key)) { 121 switch (method) { 122 case METHOD_GET_ENTRY_DATA: 123 bundle.putParcelableList(EXTRA_ENTRY_DATA, mEntryDataList); 124 return bundle; 125 case METHOD_GET_SWITCH_DATA: 126 bundle.putParcelableList(EXTRA_SWITCH_DATA, mEntryDataList); 127 return bundle; 128 default: 129 return null; 130 } 131 } 132 133 final EntryController controller = mControllerMap.get(key); 134 if (controller == null) { 135 return null; 136 } 137 138 switch (method) { 139 case METHOD_GET_ENTRY_DATA: 140 case METHOD_GET_SWITCH_DATA: 141 if (!(controller instanceof PrimarySwitchController)) { 142 return controller.getBundle(); 143 } 144 break; 145 case METHOD_GET_PROVIDER_ICON: 146 if (controller instanceof ProviderIcon) { 147 return ((ProviderIcon) controller).getProviderIcon(); 148 } 149 break; 150 case METHOD_GET_DYNAMIC_TITLE: 151 if (controller instanceof DynamicTitle) { 152 bundle.putString(META_DATA_PREFERENCE_TITLE, 153 ((DynamicTitle) controller).getDynamicTitle()); 154 return bundle; 155 } 156 break; 157 case METHOD_GET_DYNAMIC_SUMMARY: 158 if (controller instanceof DynamicSummary) { 159 bundle.putString(META_DATA_PREFERENCE_SUMMARY, 160 ((DynamicSummary) controller).getDynamicSummary()); 161 return bundle; 162 } 163 break; 164 case METHOD_IS_CHECKED: 165 if (controller instanceof ProviderSwitch) { 166 bundle.putBoolean(EXTRA_SWITCH_CHECKED_STATE, 167 ((ProviderSwitch) controller).isSwitchChecked()); 168 return bundle; 169 } 170 break; 171 case METHOD_ON_CHECKED_CHANGED: 172 if (controller instanceof ProviderSwitch) { 173 return onSwitchCheckedChanged(extras.getBoolean(EXTRA_SWITCH_CHECKED_STATE), 174 (ProviderSwitch) controller); 175 } 176 break; 177 } 178 return null; 179 } 180 onSwitchCheckedChanged(boolean checked, ProviderSwitch controller)181 private Bundle onSwitchCheckedChanged(boolean checked, ProviderSwitch controller) { 182 final boolean success = controller.onSwitchCheckedChanged(checked); 183 final Bundle bundle = new Bundle(); 184 bundle.putBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR, !success); 185 if (success) { 186 if (controller instanceof DynamicSummary) { 187 ((EntryController) controller).notifySummaryChanged(getContext()); 188 } 189 } else { 190 bundle.putString(EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE, 191 controller.getSwitchErrorMessage(checked)); 192 } 193 return bundle; 194 } 195 196 @Override query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)197 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 198 String sortOrder) { 199 throw new UnsupportedOperationException(); 200 } 201 202 @Override getType(Uri uri)203 public String getType(Uri uri) { 204 throw new UnsupportedOperationException(); 205 } 206 207 @Override insert(Uri uri, ContentValues values)208 public Uri insert(Uri uri, ContentValues values) { 209 throw new UnsupportedOperationException(); 210 } 211 212 @Override delete(Uri uri, String selection, String[] selectionArgs)213 public int delete(Uri uri, String selection, String[] selectionArgs) { 214 throw new UnsupportedOperationException(); 215 } 216 217 @Override update(Uri uri, ContentValues values, String selection, String[] selectionArgs)218 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 219 throw new UnsupportedOperationException(); 220 } 221 } 222 223