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.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 switches to Settings.
40  */
41 public abstract class SwitchesProvider extends ContentProvider {
42     private static final String TAG = "SwitchesProvider";
43 
44     public static final String METHOD_GET_SWITCH_DATA = "getSwitchData";
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     public static final String EXTRA_SWITCH_DATA = "switch_data";
52     public static final String EXTRA_SWITCH_CHECKED_STATE = "checked_state";
53     public static final String EXTRA_SWITCH_SET_CHECKED_ERROR = "set_checked_error";
54     public static final String EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE = "set_checked_error_message";
55 
56     private String mAuthority;
57     private final Map<String, SwitchController> mControllerMap = new LinkedHashMap<>();
58     private final List<Bundle> mSwitchDataList = new ArrayList<>();
59 
60     /**
61      * Get a list of {@link SwitchController} for this provider.
62      */
createSwitchControllers()63     protected abstract List<SwitchController> createSwitchControllers();
64 
65     @Override
attachInfo(Context context, ProviderInfo info)66     public void attachInfo(Context context, ProviderInfo info) {
67         mAuthority = info.authority;
68         Log.i(TAG, mAuthority);
69         super.attachInfo(context, info);
70     }
71 
72     @Override
onCreate()73     public boolean onCreate() {
74         final List<SwitchController> controllers = createSwitchControllers();
75         if (controllers == null || controllers.isEmpty()) {
76             throw new IllegalArgumentException();
77         }
78 
79         controllers.forEach(controller -> {
80             final String key = controller.getSwitchKey();
81             if (TextUtils.isEmpty(key)) {
82                 throw new NullPointerException("Switch key cannot be null: "
83                         + controller.getClass().getSimpleName());
84             } else if (mControllerMap.containsKey(key)) {
85                 throw new IllegalArgumentException("Switch key " + key + " is duplicated by: "
86                         + controller.getClass().getSimpleName());
87             }
88 
89             controller.setAuthority(mAuthority);
90             mControllerMap.put(key, controller);
91             if (!(controller instanceof PrimarySwitchController)) {
92                 mSwitchDataList.add(controller.getBundle());
93             }
94         });
95         return true;
96     }
97 
98     @Override
call(String method, String uriString, Bundle extras)99     public Bundle call(String method, String uriString, Bundle extras) {
100         final Bundle bundle = new Bundle();
101         final String key = extras != null
102                 ? extras.getString(META_DATA_PREFERENCE_KEYHINT)
103                 : null;
104         if (TextUtils.isEmpty(key)) {
105             if (METHOD_GET_SWITCH_DATA.equals(method)) {
106                 bundle.putParcelableList(EXTRA_SWITCH_DATA, mSwitchDataList);
107                 return bundle;
108             }
109             return null;
110         }
111 
112         final SwitchController controller = mControllerMap.get(key);
113         if (controller == null) {
114             return null;
115         }
116 
117         switch (method) {
118             case METHOD_GET_SWITCH_DATA:
119                 if (!(controller instanceof PrimarySwitchController)) {
120                     return controller.getBundle();
121                 }
122                 break;
123             case METHOD_GET_PROVIDER_ICON:
124                 if (controller instanceof ProviderIcon) {
125                     return ((ProviderIcon) controller).getProviderIcon();
126                 }
127                 break;
128             case METHOD_GET_DYNAMIC_TITLE:
129                 if (controller instanceof DynamicTitle) {
130                     bundle.putString(META_DATA_PREFERENCE_TITLE,
131                             ((DynamicTitle) controller).getDynamicTitle());
132                     return bundle;
133                 }
134                 break;
135             case METHOD_GET_DYNAMIC_SUMMARY:
136                 if (controller instanceof DynamicSummary) {
137                     bundle.putString(META_DATA_PREFERENCE_SUMMARY,
138                             ((DynamicSummary) controller).getDynamicSummary());
139                     return bundle;
140                 }
141                 break;
142             case METHOD_IS_CHECKED:
143                 bundle.putBoolean(EXTRA_SWITCH_CHECKED_STATE, controller.isChecked());
144                 return bundle;
145             case METHOD_ON_CHECKED_CHANGED:
146                 return onCheckedChanged(extras.getBoolean(EXTRA_SWITCH_CHECKED_STATE), controller);
147         }
148         return null;
149     }
150 
onCheckedChanged(boolean checked, SwitchController controller)151     private Bundle onCheckedChanged(boolean checked, SwitchController controller) {
152         final boolean success = controller.onCheckedChanged(checked);
153         final Bundle bundle = new Bundle();
154         bundle.putBoolean(EXTRA_SWITCH_SET_CHECKED_ERROR, !success);
155         if (success) {
156             if (controller instanceof DynamicSummary) {
157                 controller.notifySummaryChanged(getContext());
158             }
159         } else {
160             bundle.putString(EXTRA_SWITCH_SET_CHECKED_ERROR_MESSAGE,
161                     controller.getErrorMessage(checked));
162         }
163         return bundle;
164     }
165 
166     @Override
query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)167     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
168             String sortOrder) {
169         throw new UnsupportedOperationException();
170     }
171 
172     @Override
getType(Uri uri)173     public String getType(Uri uri) {
174         throw new UnsupportedOperationException();
175     }
176 
177     @Override
insert(Uri uri, ContentValues values)178     public Uri insert(Uri uri, ContentValues values) {
179         throw new UnsupportedOperationException();
180     }
181 
182     @Override
delete(Uri uri, String selection, String[] selectionArgs)183     public int delete(Uri uri, String selection, String[] selectionArgs) {
184         throw new UnsupportedOperationException();
185     }
186 
187     @Override
update(Uri uri, ContentValues values, String selection, String[] selectionArgs)188     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
189         throw new UnsupportedOperationException();
190     }
191 }
192