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