1 /*
2  * Copyright (C) 2016 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.settings;
18 
19 import android.app.AlertDialog;
20 import android.content.Context;
21 import android.content.DialogInterface;
22 import android.os.Bundle;
23 import android.support.v14.preference.ListPreferenceDialogFragment;
24 import android.support.v7.preference.PreferenceViewHolder;
25 import android.util.AttributeSet;
26 import android.view.View;
27 import android.view.ViewGroup;
28 import android.widget.AdapterView;
29 import android.widget.ArrayAdapter;
30 import android.widget.CheckedTextView;
31 import android.widget.ImageView;
32 import android.widget.ListAdapter;
33 import android.widget.ListView;
34 
35 import com.android.settingslib.RestrictedLockUtils;
36 import com.android.settingslib.RestrictedPreferenceHelper;
37 
38 import java.util.ArrayList;
39 import java.util.List;
40 
41 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
42 
43 public class RestrictedListPreference extends CustomListPreference {
44     private final RestrictedPreferenceHelper mHelper;
45     private final List<RestrictedItem> mRestrictedItems = new ArrayList<>();
46 
RestrictedListPreference(Context context, AttributeSet attrs)47     public RestrictedListPreference(Context context, AttributeSet attrs) {
48         super(context, attrs);
49         mHelper = new RestrictedPreferenceHelper(context, this, attrs);
50     }
51 
RestrictedListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)52     public RestrictedListPreference(Context context, AttributeSet attrs,
53             int defStyleAttr, int defStyleRes) {
54         super(context, attrs, defStyleAttr, defStyleRes);
55         mHelper = new RestrictedPreferenceHelper(context, this, attrs);
56     }
57 
58     @Override
onBindViewHolder(PreferenceViewHolder holder)59     public void onBindViewHolder(PreferenceViewHolder holder) {
60         super.onBindViewHolder(holder);
61         mHelper.onBindViewHolder(holder);
62     }
63 
64     @Override
performClick()65     public void performClick() {
66         if (!mHelper.performClick()) {
67             super.performClick();
68         }
69     }
70 
71     @Override
setEnabled(boolean enabled)72     public void setEnabled(boolean enabled) {
73         if (enabled && isDisabledByAdmin()) {
74             mHelper.setDisabledByAdmin(null);
75             return;
76         }
77         super.setEnabled(enabled);
78     }
79 
setDisabledByAdmin(EnforcedAdmin admin)80     public void setDisabledByAdmin(EnforcedAdmin admin) {
81         if (mHelper.setDisabledByAdmin(admin)) {
82             notifyChanged();
83         }
84     }
85 
isDisabledByAdmin()86     public boolean isDisabledByAdmin() {
87         return mHelper.isDisabledByAdmin();
88     }
89 
isRestrictedForEntry(CharSequence entry)90     public boolean isRestrictedForEntry(CharSequence entry) {
91         if (entry == null) {
92             return false;
93         }
94         for (RestrictedItem item : mRestrictedItems) {
95             if (entry.equals(item.entry)) {
96                 return true;
97             }
98         }
99         return false;
100     }
101 
addRestrictedItem(RestrictedItem item)102     public void addRestrictedItem(RestrictedItem item) {
103         mRestrictedItems.add(item);
104     }
105 
clearRestrictedItems()106     public void clearRestrictedItems() {
107         mRestrictedItems.clear();
108     }
109 
getRestrictedItemForEntryValue(CharSequence entryValue)110     private RestrictedItem getRestrictedItemForEntryValue(CharSequence entryValue) {
111         if (entryValue == null) {
112             return null;
113         }
114         for (RestrictedItem item : mRestrictedItems) {
115             if (entryValue.equals(item.entryValue)) {
116                 return item;
117             }
118         }
119         return null;
120     }
121 
createListAdapter()122     protected ListAdapter createListAdapter() {
123         return new RestrictedArrayAdapter(getContext(), getEntries(),
124                 getSelectedValuePos());
125     }
126 
getSelectedValuePos()127     public int getSelectedValuePos() {
128         final String selectedValue = getValue();
129         final int selectedIndex =
130                 (selectedValue == null) ? -1 : findIndexOfValue(selectedValue);
131         return selectedIndex;
132     }
133 
134     @Override
onPrepareDialogBuilder(AlertDialog.Builder builder, DialogInterface.OnClickListener listener)135     protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
136             DialogInterface.OnClickListener listener) {
137         builder.setAdapter(createListAdapter(), listener);
138     }
139 
140 
141     public class RestrictedArrayAdapter extends ArrayAdapter<CharSequence> {
142         private final int mSelectedIndex;
RestrictedArrayAdapter(Context context, CharSequence[] objects, int selectedIndex)143         public RestrictedArrayAdapter(Context context, CharSequence[] objects, int selectedIndex) {
144             super(context, R.layout.restricted_dialog_singlechoice, R.id.text1, objects);
145             mSelectedIndex = selectedIndex;
146         }
147 
148         @Override
getView(int position, View convertView, ViewGroup parent)149         public View getView(int position, View convertView, ViewGroup parent) {
150             View root = super.getView(position, convertView, parent);
151             CharSequence entry = getItem(position);
152             CheckedTextView text = (CheckedTextView) root.findViewById(R.id.text1);
153             ImageView padlock = (ImageView) root.findViewById(R.id.restricted_lock_icon);
154             if (isRestrictedForEntry(entry)) {
155                 text.setEnabled(false);
156                 text.setChecked(false);
157                 padlock.setVisibility(View.VISIBLE);
158             } else {
159                 if (mSelectedIndex != -1) {
160                     text.setChecked(position == mSelectedIndex);
161                 }
162                 if (!text.isEnabled()) {
163                     text.setEnabled(true);
164                 }
165                 padlock.setVisibility(View.GONE);
166             }
167             return root;
168         }
169 
170         @Override
hasStableIds()171         public boolean hasStableIds() {
172             return true;
173         }
174 
175         @Override
getItemId(int position)176         public long getItemId(int position) {
177             return position;
178         }
179     }
180 
181     public static class RestrictedListPreferenceDialogFragment extends
182             CustomListPreference.CustomListPreferenceDialogFragment {
183         private int mLastCheckedPosition = AdapterView.INVALID_POSITION;
184 
newInstance(String key)185         public static ListPreferenceDialogFragment newInstance(String key) {
186             final ListPreferenceDialogFragment fragment
187                     = new RestrictedListPreferenceDialogFragment();
188             final Bundle b = new Bundle(1);
189             b.putString(ARG_KEY, key);
190             fragment.setArguments(b);
191             return fragment;
192         }
193 
getCustomizablePreference()194         private RestrictedListPreference getCustomizablePreference() {
195             return (RestrictedListPreference) getPreference();
196         }
197 
198         @Override
getOnItemClickListener()199         protected DialogInterface.OnClickListener getOnItemClickListener() {
200             return new DialogInterface.OnClickListener() {
201                 public void onClick(DialogInterface dialog, int which) {
202                     final RestrictedListPreference preference = getCustomizablePreference();
203                     if (which < 0 || which >= preference.getEntryValues().length) {
204                         return;
205                     }
206                     String entryValue = preference.getEntryValues()[which].toString();
207                     RestrictedItem item = preference.getRestrictedItemForEntryValue(entryValue);
208                     if (item != null) {
209                         ListView listView = ((AlertDialog) dialog).getListView();
210                         listView.setItemChecked(getLastCheckedPosition(), true);
211                         RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
212                                 item.enforcedAdmin);
213                     } else {
214                         setClickedDialogEntryIndex(which);
215                     }
216 
217                     if (getCustomizablePreference().isAutoClosePreference()) {
218                         /*
219                          * Clicking on an item simulates the positive button
220                          * click, and dismisses the dialog.
221                          */
222                         RestrictedListPreferenceDialogFragment.this.onClick(dialog,
223                                 DialogInterface.BUTTON_POSITIVE);
224                         dialog.dismiss();
225                     }
226                 }
227             };
228         }
229 
getLastCheckedPosition()230         private int getLastCheckedPosition() {
231             if (mLastCheckedPosition == AdapterView.INVALID_POSITION) {
232                 mLastCheckedPosition = ((RestrictedListPreference) getCustomizablePreference())
233                         .getSelectedValuePos();
234             }
235             return mLastCheckedPosition;
236         }
237 
setCheckedPosition(int checkedPosition)238         private void setCheckedPosition(int checkedPosition) {
239             mLastCheckedPosition = checkedPosition;
240         }
241 
242         @Override
setClickedDialogEntryIndex(int which)243         protected void setClickedDialogEntryIndex(int which) {
244             super.setClickedDialogEntryIndex(which);
245             mLastCheckedPosition = which;
246         }
247     }
248 
249     public static class RestrictedItem {
250         public final CharSequence entry;
251         public final CharSequence entryValue;
252         public final EnforcedAdmin enforcedAdmin;
253 
254         public RestrictedItem(CharSequence entry, CharSequence entryValue,
255                 EnforcedAdmin enforcedAdmin) {
256             this.entry = entry;
257             this.entryValue = entryValue;
258             this.enforcedAdmin = enforcedAdmin;
259         }
260     }
261 }