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 }