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