Rather than check for the state of the work profile in LockScreenNotificationPreferenceController#handlePreferenceTreeClick, do so in the RestrictedListPreference#performClick. The drawback of checking the state in handlePreferenceTreeClick is that the preferences are displayed first and then the requirement to unlock/enable the work profile is displayed on top of it. This is rather poor UX, so switch to doing the check in performClick and returning early if the work profile needs to be unlocked/enabled. This is similar to Patchset 1 from ag/3805482. The main difference is that the user is returned to the settings screen both after enabling the work profile and unlocking it. Test: Manually with TestDPC Test: atest SettingsRoboTests:RestrictedListPreferenceTest Bug: 77408805 Merged-In: Id168911b082fffac193cd7c7a658ab92d6ce2c15 Change-Id: I0a3a4ec4dda78e28ee88a11d383eda49e9cf50a6
302 lines
11 KiB
Java
302 lines
11 KiB
Java
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.settings;
|
|
|
|
import android.app.ActivityManager;
|
|
import android.app.AlertDialog;
|
|
import android.app.KeyguardManager;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.os.Bundle;
|
|
import android.os.RemoteException;
|
|
import android.os.UserManager;
|
|
import android.support.annotation.VisibleForTesting;
|
|
import android.support.v14.preference.ListPreferenceDialogFragment;
|
|
import android.support.v7.preference.PreferenceViewHolder;
|
|
import android.util.AttributeSet;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.AdapterView;
|
|
import android.widget.ArrayAdapter;
|
|
import android.widget.CheckedTextView;
|
|
import android.widget.ImageView;
|
|
import android.widget.ListAdapter;
|
|
import android.widget.ListView;
|
|
|
|
import com.android.settings.Utils;
|
|
import com.android.settingslib.RestrictedLockUtils;
|
|
import com.android.settingslib.RestrictedPreferenceHelper;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
|
|
|
public class RestrictedListPreference extends CustomListPreference {
|
|
private final RestrictedPreferenceHelper mHelper;
|
|
private final List<RestrictedItem> mRestrictedItems = new ArrayList<>();
|
|
private boolean mRequiresActiveUnlockedProfile = false;
|
|
private int mProfileUserId;
|
|
|
|
public RestrictedListPreference(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
setWidgetLayoutResource(R.layout.restricted_icon);
|
|
mHelper = new RestrictedPreferenceHelper(context, this, attrs);
|
|
}
|
|
|
|
public RestrictedListPreference(Context context, AttributeSet attrs,
|
|
int defStyleAttr, int defStyleRes) {
|
|
super(context, attrs, defStyleAttr, defStyleRes);
|
|
mHelper = new RestrictedPreferenceHelper(context, this, attrs);
|
|
}
|
|
|
|
@Override
|
|
public void onBindViewHolder(PreferenceViewHolder holder) {
|
|
super.onBindViewHolder(holder);
|
|
mHelper.onBindViewHolder(holder);
|
|
final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
|
|
if (restrictedIcon != null) {
|
|
restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void performClick() {
|
|
if (mRequiresActiveUnlockedProfile) {
|
|
// Check if the profile is started, first.
|
|
if (Utils.startQuietModeDialogIfNecessary(getContext(), UserManager.get(getContext()),
|
|
mProfileUserId)) {
|
|
return;
|
|
}
|
|
|
|
// Next, check if the profile is unlocked.
|
|
KeyguardManager manager =
|
|
(KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
|
|
if (manager.isDeviceLocked(mProfileUserId)) {
|
|
Intent intent = manager.createConfirmDeviceCredentialIntent(
|
|
null, null, mProfileUserId);
|
|
getContext().startActivity(intent);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!mHelper.performClick()) {
|
|
super.performClick();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setEnabled(boolean enabled) {
|
|
if (enabled && isDisabledByAdmin()) {
|
|
mHelper.setDisabledByAdmin(null);
|
|
return;
|
|
}
|
|
super.setEnabled(enabled);
|
|
}
|
|
|
|
public void setDisabledByAdmin(EnforcedAdmin admin) {
|
|
if (mHelper.setDisabledByAdmin(admin)) {
|
|
notifyChanged();
|
|
}
|
|
}
|
|
|
|
public boolean isDisabledByAdmin() {
|
|
return mHelper.isDisabledByAdmin();
|
|
}
|
|
|
|
public void setRequiresActiveUnlockedProfile(boolean reqState) {
|
|
mRequiresActiveUnlockedProfile = reqState;
|
|
}
|
|
|
|
public void setProfileUserId(int profileUserId) {
|
|
mProfileUserId = profileUserId;
|
|
}
|
|
|
|
public boolean isRestrictedForEntry(CharSequence entry) {
|
|
if (entry == null) {
|
|
return false;
|
|
}
|
|
for (RestrictedItem item : mRestrictedItems) {
|
|
if (entry.equals(item.entry)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void addRestrictedItem(RestrictedItem item) {
|
|
mRestrictedItems.add(item);
|
|
}
|
|
|
|
public void clearRestrictedItems() {
|
|
mRestrictedItems.clear();
|
|
}
|
|
|
|
private RestrictedItem getRestrictedItemForEntryValue(CharSequence entryValue) {
|
|
if (entryValue == null) {
|
|
return null;
|
|
}
|
|
for (RestrictedItem item : mRestrictedItems) {
|
|
if (entryValue.equals(item.entryValue)) {
|
|
return item;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
protected ListAdapter createListAdapter() {
|
|
return new RestrictedArrayAdapter(getContext(), getEntries(),
|
|
getSelectedValuePos());
|
|
}
|
|
|
|
public int getSelectedValuePos() {
|
|
final String selectedValue = getValue();
|
|
final int selectedIndex =
|
|
(selectedValue == null) ? -1 : findIndexOfValue(selectedValue);
|
|
return selectedIndex;
|
|
}
|
|
|
|
@Override
|
|
protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
|
|
DialogInterface.OnClickListener listener) {
|
|
builder.setAdapter(createListAdapter(), listener);
|
|
}
|
|
|
|
|
|
public class RestrictedArrayAdapter extends ArrayAdapter<CharSequence> {
|
|
private final int mSelectedIndex;
|
|
public RestrictedArrayAdapter(Context context, CharSequence[] objects, int selectedIndex) {
|
|
super(context, R.layout.restricted_dialog_singlechoice, R.id.text1, objects);
|
|
mSelectedIndex = selectedIndex;
|
|
}
|
|
|
|
@Override
|
|
public View getView(int position, View convertView, ViewGroup parent) {
|
|
View root = super.getView(position, convertView, parent);
|
|
CharSequence entry = getItem(position);
|
|
CheckedTextView text = (CheckedTextView) root.findViewById(R.id.text1);
|
|
ImageView padlock = (ImageView) root.findViewById(R.id.restricted_lock_icon);
|
|
if (isRestrictedForEntry(entry)) {
|
|
text.setEnabled(false);
|
|
text.setChecked(false);
|
|
padlock.setVisibility(View.VISIBLE);
|
|
} else {
|
|
if (mSelectedIndex != -1) {
|
|
text.setChecked(position == mSelectedIndex);
|
|
}
|
|
if (!text.isEnabled()) {
|
|
text.setEnabled(true);
|
|
}
|
|
padlock.setVisibility(View.GONE);
|
|
}
|
|
return root;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasStableIds() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public long getItemId(int position) {
|
|
return position;
|
|
}
|
|
}
|
|
|
|
public static class RestrictedListPreferenceDialogFragment extends
|
|
CustomListPreference.CustomListPreferenceDialogFragment {
|
|
private int mLastCheckedPosition = AdapterView.INVALID_POSITION;
|
|
|
|
public static ListPreferenceDialogFragment newInstance(String key) {
|
|
final ListPreferenceDialogFragment fragment
|
|
= new RestrictedListPreferenceDialogFragment();
|
|
final Bundle b = new Bundle(1);
|
|
b.putString(ARG_KEY, key);
|
|
fragment.setArguments(b);
|
|
return fragment;
|
|
}
|
|
|
|
private RestrictedListPreference getCustomizablePreference() {
|
|
return (RestrictedListPreference) getPreference();
|
|
}
|
|
|
|
@Override
|
|
protected DialogInterface.OnClickListener getOnItemClickListener() {
|
|
return new DialogInterface.OnClickListener() {
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
final RestrictedListPreference preference = getCustomizablePreference();
|
|
if (which < 0 || which >= preference.getEntryValues().length) {
|
|
return;
|
|
}
|
|
String entryValue = preference.getEntryValues()[which].toString();
|
|
RestrictedItem item = preference.getRestrictedItemForEntryValue(entryValue);
|
|
if (item != null) {
|
|
ListView listView = ((AlertDialog) dialog).getListView();
|
|
listView.setItemChecked(getLastCheckedPosition(), true);
|
|
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
|
|
item.enforcedAdmin);
|
|
} else {
|
|
setClickedDialogEntryIndex(which);
|
|
}
|
|
|
|
if (getCustomizablePreference().isAutoClosePreference()) {
|
|
/*
|
|
* Clicking on an item simulates the positive button
|
|
* click, and dismisses the dialog.
|
|
*/
|
|
RestrictedListPreferenceDialogFragment.this.onClick(dialog,
|
|
DialogInterface.BUTTON_POSITIVE);
|
|
dialog.dismiss();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
private int getLastCheckedPosition() {
|
|
if (mLastCheckedPosition == AdapterView.INVALID_POSITION) {
|
|
mLastCheckedPosition = ((RestrictedListPreference) getCustomizablePreference())
|
|
.getSelectedValuePos();
|
|
}
|
|
return mLastCheckedPosition;
|
|
}
|
|
|
|
private void setCheckedPosition(int checkedPosition) {
|
|
mLastCheckedPosition = checkedPosition;
|
|
}
|
|
|
|
@Override
|
|
protected void setClickedDialogEntryIndex(int which) {
|
|
super.setClickedDialogEntryIndex(which);
|
|
mLastCheckedPosition = which;
|
|
}
|
|
}
|
|
|
|
public static class RestrictedItem {
|
|
public final CharSequence entry;
|
|
public final CharSequence entryValue;
|
|
public final EnforcedAdmin enforcedAdmin;
|
|
|
|
public RestrictedItem(CharSequence entry, CharSequence entryValue,
|
|
EnforcedAdmin enforcedAdmin) {
|
|
this.entry = entry;
|
|
this.entryValue = entryValue;
|
|
this.enforcedAdmin = enforcedAdmin;
|
|
}
|
|
}
|
|
}
|