blob: bd3cd17432fb42271e83220057fd864e67a09804 [file] [log] [blame]
Sudheer Shanka550d0682016-01-13 15:16:55 +00001/*
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
17package com.android.settings;
18
Fan Zhangc7162cd2018-06-18 15:21:41 -070019import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
20
Eran Messerid204af12018-04-02 23:10:00 +030021import android.app.KeyguardManager;
Sudheer Shanka550d0682016-01-13 15:16:55 +000022import android.content.Context;
23import android.content.DialogInterface;
Eran Messerid204af12018-04-02 23:10:00 +030024import android.content.Intent;
Sudheer Shanka550d0682016-01-13 15:16:55 +000025import android.os.Bundle;
Eran Messerid204af12018-04-02 23:10:00 +030026import android.os.UserManager;
Sudheer Shanka550d0682016-01-13 15:16:55 +000027import android.util.AttributeSet;
28import android.view.View;
29import android.view.ViewGroup;
Sudheer Shanka54dc9d52016-03-04 13:53:24 -080030import android.widget.AdapterView;
Sudheer Shanka550d0682016-01-13 15:16:55 +000031import android.widget.ArrayAdapter;
32import android.widget.CheckedTextView;
33import android.widget.ImageView;
34import android.widget.ListAdapter;
Sudheer Shanka54dc9d52016-03-04 13:53:24 -080035import android.widget.ListView;
Sudheer Shanka550d0682016-01-13 15:16:55 +000036
Fan Zhang23f8d592018-08-28 15:11:40 -070037import androidx.appcompat.app.AlertDialog;
38import androidx.appcompat.app.AlertDialog.Builder;
39import androidx.preference.ListPreferenceDialogFragmentCompat;
40import androidx.preference.PreferenceViewHolder;
41
Sudheer Shanka550d0682016-01-13 15:16:55 +000042import com.android.settingslib.RestrictedLockUtils;
43import com.android.settingslib.RestrictedPreferenceHelper;
44
45import java.util.ArrayList;
46import java.util.List;
47
Sudheer Shanka550d0682016-01-13 15:16:55 +000048public class RestrictedListPreference extends CustomListPreference {
49 private final RestrictedPreferenceHelper mHelper;
50 private final List<RestrictedItem> mRestrictedItems = new ArrayList<>();
Eran Messerid204af12018-04-02 23:10:00 +030051 private boolean mRequiresActiveUnlockedProfile = false;
52 private int mProfileUserId;
Sudheer Shanka550d0682016-01-13 15:16:55 +000053
54 public RestrictedListPreference(Context context, AttributeSet attrs) {
55 super(context, attrs);
Tony Mak2f170852016-06-28 16:30:38 +010056 setWidgetLayoutResource(R.layout.restricted_icon);
Sudheer Shanka550d0682016-01-13 15:16:55 +000057 mHelper = new RestrictedPreferenceHelper(context, this, attrs);
58 }
59
60 public RestrictedListPreference(Context context, AttributeSet attrs,
61 int defStyleAttr, int defStyleRes) {
62 super(context, attrs, defStyleAttr, defStyleRes);
63 mHelper = new RestrictedPreferenceHelper(context, this, attrs);
64 }
65
66 @Override
67 public void onBindViewHolder(PreferenceViewHolder holder) {
68 super.onBindViewHolder(holder);
69 mHelper.onBindViewHolder(holder);
Tony Mak2f170852016-06-28 16:30:38 +010070 final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
71 if (restrictedIcon != null) {
72 restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
73 }
Sudheer Shanka550d0682016-01-13 15:16:55 +000074 }
75
76 @Override
77 public void performClick() {
Eran Messerid204af12018-04-02 23:10:00 +030078 if (mRequiresActiveUnlockedProfile) {
79 // Check if the profile is started, first.
80 if (Utils.startQuietModeDialogIfNecessary(getContext(), UserManager.get(getContext()),
81 mProfileUserId)) {
82 return;
83 }
84
85 // Next, check if the profile is unlocked.
86 KeyguardManager manager =
87 (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
88 if (manager.isDeviceLocked(mProfileUserId)) {
89 Intent intent = manager.createConfirmDeviceCredentialIntent(
90 null, null, mProfileUserId);
91 getContext().startActivity(intent);
92 return;
93 }
94 }
95
Sudheer Shanka550d0682016-01-13 15:16:55 +000096 if (!mHelper.performClick()) {
97 super.performClick();
98 }
99 }
100
101 @Override
102 public void setEnabled(boolean enabled) {
103 if (enabled && isDisabledByAdmin()) {
104 mHelper.setDisabledByAdmin(null);
105 return;
106 }
107 super.setEnabled(enabled);
108 }
109
110 public void setDisabledByAdmin(EnforcedAdmin admin) {
111 if (mHelper.setDisabledByAdmin(admin)) {
112 notifyChanged();
113 }
114 }
115
116 public boolean isDisabledByAdmin() {
117 return mHelper.isDisabledByAdmin();
118 }
119
Eran Messerid204af12018-04-02 23:10:00 +0300120 public void setRequiresActiveUnlockedProfile(boolean reqState) {
121 mRequiresActiveUnlockedProfile = reqState;
122 }
123
124 public void setProfileUserId(int profileUserId) {
125 mProfileUserId = profileUserId;
126 }
127
Sudheer Shanka550d0682016-01-13 15:16:55 +0000128 public boolean isRestrictedForEntry(CharSequence entry) {
129 if (entry == null) {
130 return false;
131 }
132 for (RestrictedItem item : mRestrictedItems) {
133 if (entry.equals(item.entry)) {
134 return true;
135 }
136 }
137 return false;
138 }
139
140 public void addRestrictedItem(RestrictedItem item) {
141 mRestrictedItems.add(item);
142 }
143
144 public void clearRestrictedItems() {
145 mRestrictedItems.clear();
146 }
147
148 private RestrictedItem getRestrictedItemForEntryValue(CharSequence entryValue) {
149 if (entryValue == null) {
150 return null;
151 }
152 for (RestrictedItem item : mRestrictedItems) {
153 if (entryValue.equals(item.entryValue)) {
154 return item;
155 }
156 }
157 return null;
158 }
159
Raff Tsai953e3902019-03-05 12:07:50 +0800160 protected ListAdapter createListAdapter(Context context) {
161 return new RestrictedArrayAdapter(context, getEntries(),
Sudheer Shanka54dc9d52016-03-04 13:53:24 -0800162 getSelectedValuePos());
163 }
164
165 public int getSelectedValuePos() {
Sudheer Shanka550d0682016-01-13 15:16:55 +0000166 final String selectedValue = getValue();
167 final int selectedIndex =
168 (selectedValue == null) ? -1 : findIndexOfValue(selectedValue);
Sudheer Shanka54dc9d52016-03-04 13:53:24 -0800169 return selectedIndex;
Sudheer Shanka550d0682016-01-13 15:16:55 +0000170 }
171
172 @Override
tmfang27c84de2018-06-28 11:39:05 +0800173 protected void onPrepareDialogBuilder(Builder builder,
Sudheer Shanka550d0682016-01-13 15:16:55 +0000174 DialogInterface.OnClickListener listener) {
Raff Tsai953e3902019-03-05 12:07:50 +0800175 builder.setAdapter(createListAdapter(builder.getContext()), listener);
Sudheer Shanka550d0682016-01-13 15:16:55 +0000176 }
177
Sudheer Shanka550d0682016-01-13 15:16:55 +0000178 public class RestrictedArrayAdapter extends ArrayAdapter<CharSequence> {
179 private final int mSelectedIndex;
180 public RestrictedArrayAdapter(Context context, CharSequence[] objects, int selectedIndex) {
181 super(context, R.layout.restricted_dialog_singlechoice, R.id.text1, objects);
182 mSelectedIndex = selectedIndex;
183 }
184
185 @Override
186 public View getView(int position, View convertView, ViewGroup parent) {
187 View root = super.getView(position, convertView, parent);
188 CharSequence entry = getItem(position);
189 CheckedTextView text = (CheckedTextView) root.findViewById(R.id.text1);
190 ImageView padlock = (ImageView) root.findViewById(R.id.restricted_lock_icon);
191 if (isRestrictedForEntry(entry)) {
192 text.setEnabled(false);
Sudheer Shankaa412f472016-01-28 17:53:53 +0000193 text.setChecked(false);
Sudheer Shanka550d0682016-01-13 15:16:55 +0000194 padlock.setVisibility(View.VISIBLE);
195 } else {
Adrian Roosd553f4f2016-02-22 13:03:42 -0800196 if (mSelectedIndex != -1) {
197 text.setChecked(position == mSelectedIndex);
198 }
199 if (!text.isEnabled()) {
200 text.setEnabled(true);
201 }
Sudheer Shanka550d0682016-01-13 15:16:55 +0000202 padlock.setVisibility(View.GONE);
203 }
204 return root;
205 }
206
207 @Override
208 public boolean hasStableIds() {
209 return true;
210 }
211
212 @Override
213 public long getItemId(int position) {
214 return position;
215 }
216 }
217
218 public static class RestrictedListPreferenceDialogFragment extends
219 CustomListPreference.CustomListPreferenceDialogFragment {
Sudheer Shanka54dc9d52016-03-04 13:53:24 -0800220 private int mLastCheckedPosition = AdapterView.INVALID_POSITION;
221
tmfang27c84de2018-06-28 11:39:05 +0800222 public static ListPreferenceDialogFragmentCompat newInstance(String key) {
223 final ListPreferenceDialogFragmentCompat fragment
Sudheer Shanka550d0682016-01-13 15:16:55 +0000224 = new RestrictedListPreferenceDialogFragment();
225 final Bundle b = new Bundle(1);
226 b.putString(ARG_KEY, key);
227 fragment.setArguments(b);
228 return fragment;
229 }
230
231 private RestrictedListPreference getCustomizablePreference() {
232 return (RestrictedListPreference) getPreference();
233 }
234
235 @Override
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) {
Sudheer Shanka54dc9d52016-03-04 13:53:24 -0800246 ListView listView = ((AlertDialog) dialog).getListView();
247 listView.setItemChecked(getLastCheckedPosition(), true);
Sudheer Shanka550d0682016-01-13 15:16:55 +0000248 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
249 item.enforcedAdmin);
250 } else {
251 setClickedDialogEntryIndex(which);
252 }
253
Adrian Roosd553f4f2016-02-22 13:03:42 -0800254 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 }
Sudheer Shanka550d0682016-01-13 15:16:55 +0000263 }
264 };
265 }
Sudheer Shanka54dc9d52016-03-04 13:53:24 -0800266
267 private int getLastCheckedPosition() {
268 if (mLastCheckedPosition == AdapterView.INVALID_POSITION) {
269 mLastCheckedPosition = ((RestrictedListPreference) getCustomizablePreference())
270 .getSelectedValuePos();
271 }
272 return mLastCheckedPosition;
273 }
274
275 private void setCheckedPosition(int checkedPosition) {
276 mLastCheckedPosition = checkedPosition;
277 }
278
279 @Override
280 protected void setClickedDialogEntryIndex(int which) {
281 super.setClickedDialogEntryIndex(which);
282 mLastCheckedPosition = which;
283 }
Sudheer Shanka550d0682016-01-13 15:16:55 +0000284 }
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 }
Eran Messerid204af12018-04-02 23:10:00 +0300298}