diff --git a/res/layout/restricted_dialog_singlechoice.xml b/res/layout/restricted_dialog_singlechoice.xml
new file mode 100644
index 00000000000..e5e449b1067
--- /dev/null
+++ b/res/layout/restricted_dialog_singlechoice.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 0456ace86a8..1780765713d 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -49,7 +49,7 @@
settings:keywords="@string/keywords_display_wallpaper"
android:fragment="com.android.settings.WallpaperTypeSettings" />
-
-
-
- = timeout) {
best = i;
}
}
- summary = preference.getContext().getString(R.string.screen_timeout_summary,
- entries[best]);
+ summary = getString(R.string.screen_timeout_summary, entries[best]);
}
}
preference.setSummary(summary);
}
- private void disableUnusableTimeouts(ListPreference screenTimeoutPreference) {
- final DevicePolicyManager dpm =
- (DevicePolicyManager) getActivity().getSystemService(
- Context.DEVICE_POLICY_SERVICE);
- final long maxTimeout = dpm != null ? dpm.getMaximumTimeToLock(null) : 0;
- if (maxTimeout == 0) {
+ private void disableUnusableTimeouts(RestrictedListPreference screenTimeoutPreference) {
+ final EnforcedAdmin admin = RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(
+ getActivity());
+ if (admin == null) {
return; // policy not enforced
}
+
+ final DevicePolicyManager dpm = (DevicePolicyManager) getActivity().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ if (dpm == null) {
+ return;
+ }
+ final long maxTimeout = dpm.getMaximumTimeToLock(null);
final CharSequence[] entries = screenTimeoutPreference.getEntries();
final CharSequence[] values = screenTimeoutPreference.getEntryValues();
- ArrayList revisedEntries = new ArrayList();
- ArrayList revisedValues = new ArrayList();
+ long maxTimeoutSelectable = 0;
+ int maxTimeoutEntryIndex = -1;
for (int i = 0; i < values.length; i++) {
long timeout = Long.parseLong(values[i].toString());
- if (timeout <= maxTimeout) {
- revisedEntries.add(entries[i]);
- revisedValues.add(values[i]);
+ if (timeout > maxTimeout) {
+ break;
}
+ maxTimeoutSelectable = timeout;
+ maxTimeoutEntryIndex = i;
}
- if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) {
- final int userPreference = Integer.parseInt(screenTimeoutPreference.getValue());
- screenTimeoutPreference.setEntries(
- revisedEntries.toArray(new CharSequence[revisedEntries.size()]));
- screenTimeoutPreference.setEntryValues(
- revisedValues.toArray(new CharSequence[revisedValues.size()]));
- if (userPreference <= maxTimeout) {
- screenTimeoutPreference.setValue(String.valueOf(userPreference));
- } else if (revisedValues.size() > 0
- && Long.parseLong(revisedValues.get(revisedValues.size() - 1).toString())
- == maxTimeout) {
- // If the last one happens to be the same as the max timeout, select that
- screenTimeoutPreference.setValue(String.valueOf(maxTimeout));
- } else {
- // There will be no highlighted selection since nothing in the list matches
- // maxTimeout. The user can still select anything less than maxTimeout.
- // TODO: maybe append maxTimeout to the list and mark selected.
- }
+ // If there are no possible options for the user, then set this preference as disabled
+ // by admin, otherwise remove the padlock in case it was set earlier.
+ if (maxTimeoutSelectable == 0) {
+ screenTimeoutPreference.setDisabledByAdmin(admin);
+ return;
+ } else {
+ screenTimeoutPreference.setDisabledByAdmin(null);
+ }
+
+ screenTimeoutPreference.clearRestrictedItems();
+ // Set all the entries after the maximum selectable timeout as disabled by admin.
+ for (int i = maxTimeoutEntryIndex + 1; i < values.length; i++) {
+ screenTimeoutPreference.addRestrictedItem(
+ new RestrictedItem(entries[i], values[i], admin));
+ }
+
+ final int userPreference = Integer.parseInt(screenTimeoutPreference.getValue());
+ if (userPreference <= maxTimeout) {
+ screenTimeoutPreference.setValue(String.valueOf(userPreference));
+ } else if (maxTimeoutSelectable == maxTimeout) {
+ screenTimeoutPreference.setValue(String.valueOf(maxTimeout));
+ } else {
+ // There will be no highlighted selection since nothing in the list matches
+ // maxTimeout. The user can still select anything less than maxTimeout.
+ // TODO: maybe append maxTimeout to the list and mark selected.
}
- screenTimeoutPreference.setEnabled(revisedEntries.size() > 0);
}
int floatToIndex(float val) {
@@ -358,6 +373,13 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
public void onResume() {
super.onResume();
updateState();
+
+ final long currentTimeout = Settings.System.getLong(getActivity().getContentResolver(),
+ SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE);
+ mScreenTimeoutPreference.setValue(String.valueOf(currentTimeout));
+ mScreenTimeoutPreference.setOnPreferenceChangeListener(this);
+ disableUnusableTimeouts(mScreenTimeoutPreference);
+ updateTimeoutPreferenceDescription(currentTimeout);
}
private void updateState() {
diff --git a/src/com/android/settings/RestrictedListPreference.java b/src/com/android/settings/RestrictedListPreference.java
new file mode 100644
index 00000000000..35ee30d10c0
--- /dev/null
+++ b/src/com/android/settings/RestrictedListPreference.java
@@ -0,0 +1,227 @@
+/*
+ * 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.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+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.ArrayAdapter;
+import android.widget.CheckedTextView;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+
+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 mRestrictedItems = new ArrayList<>();
+
+ public RestrictedListPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ 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);
+ }
+
+ @Override
+ public void performClick() {
+ 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 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() {
+ final String selectedValue = getValue();
+ final int selectedIndex =
+ (selectedValue == null) ? -1 : findIndexOfValue(selectedValue);
+ return new RestrictedArrayAdapter(getContext(), getEntries(), selectedIndex);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
+ DialogInterface.OnClickListener listener) {
+ builder.setAdapter(createListAdapter(), listener);
+ }
+
+
+ public class RestrictedArrayAdapter extends ArrayAdapter {
+ 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);
+ padlock.setVisibility(View.VISIBLE);
+ } else {
+ if (position == mSelectedIndex) {
+ text.setChecked(true);
+ }
+ 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 {
+ 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) {
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
+ item.enforcedAdmin);
+ } else {
+ setClickedDialogEntryIndex(which);
+ }
+
+ /*
+ * Clicking on an item simulates the positive button
+ * click, and dismisses the dialog.
+ */
+ RestrictedListPreferenceDialogFragment.this.onClick(dialog,
+ DialogInterface.BUTTON_POSITIVE);
+ dialog.dismiss();
+ }
+ };
+ }
+ }
+
+ 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index d39203d6250..17831363b46 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -39,7 +39,6 @@ import android.provider.Settings;
import android.security.KeyStore;
import android.service.trust.TrustAgentService;
import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
@@ -54,6 +53,7 @@ import android.util.Log;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.RestrictedListPreference;
import com.android.settings.TrustAgentUtils.TrustAgentComponentInfo;
import com.android.settings.fingerprint.FingerprintEnrollIntroduction;
import com.android.settings.fingerprint.FingerprintSettings;
@@ -61,6 +61,7 @@ import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Index;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
+import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.RestrictedSwitchPreference;
@@ -69,6 +70,9 @@ import java.util.List;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static com.android.settings.RestrictedListPreference.RestrictedItem;
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
/**
* Gesture lock pattern settings.
*/
@@ -124,7 +128,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private LockPatternUtils mLockPatternUtils;
- private ListPreference mLockAfter;
+ private RestrictedListPreference mLockAfter;
private SwitchPreference mVisiblePattern;
@@ -267,7 +271,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
}
// lock after preference
- mLockAfter = (ListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT);
+ mLockAfter = (RestrictedListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT);
if (mLockAfter != null) {
setupLockAfterPreference();
updateLockAfterPreferenceSummary();
@@ -552,72 +556,97 @@ public class SecuritySettings extends SettingsPreferenceFragment
Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
mLockAfter.setValue(String.valueOf(currentTimeout));
mLockAfter.setOnPreferenceChangeListener(this);
- final long adminTimeout = (mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0);
- final long displayTimeout = Math.max(0,
- Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
- if (adminTimeout > 0) {
- // This setting is a slave to display timeout when a device policy is enforced.
- // As such, maxLockTimeout = adminTimeout - displayTimeout.
- // If there isn't enough time, shows "immediately" setting.
- disableUnusableTimeouts(Math.max(0, adminTimeout - displayTimeout));
+ final EnforcedAdmin admin = RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(
+ getActivity());
+ if (admin != null) {
+ final long adminTimeout = (mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0);
+ final long displayTimeout = Math.max(0,
+ Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
+ if (adminTimeout > 0) {
+ // This setting is a slave to display timeout when a device policy is enforced.
+ // As such, maxLockTimeout = adminTimeout - displayTimeout.
+ // If there isn't enough time, shows "immediately" setting.
+ disableUnusableTimeouts(Math.max(0, adminTimeout - displayTimeout), admin);
+ }
}
}
private void updateLockAfterPreferenceSummary() {
- // Update summary message with current value
- long currentTimeout = Settings.Secure.getLong(getContentResolver(),
- Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
- final CharSequence[] entries = mLockAfter.getEntries();
- final CharSequence[] values = mLockAfter.getEntryValues();
- int best = 0;
- for (int i = 0; i < values.length; i++) {
- long timeout = Long.valueOf(values[i].toString());
- if (currentTimeout >= timeout) {
- best = i;
- }
- }
-
- Preference preference = getPreferenceScreen().findPreference(KEY_TRUST_AGENT);
- if (preference != null && preference.getTitle().length() > 0) {
- if (Long.valueOf(values[best].toString()) == 0) {
- mLockAfter.setSummary(getString(R.string.lock_immediately_summary_with_exception,
- preference.getTitle()));
- } else {
- mLockAfter.setSummary(getString(R.string.lock_after_timeout_summary_with_exception,
- entries[best], preference.getTitle()));
- }
+ final String summary;
+ if (mLockAfter.isDisabledByAdmin()) {
+ summary = getString(R.string.disabled_by_policy_title);
} else {
- mLockAfter.setSummary(getString(R.string.lock_after_timeout_summary, entries[best]));
+ // Update summary message with current value
+ long currentTimeout = Settings.Secure.getLong(getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
+ final CharSequence[] entries = mLockAfter.getEntries();
+ final CharSequence[] values = mLockAfter.getEntryValues();
+ int best = 0;
+ for (int i = 0; i < values.length; i++) {
+ if (mLockAfter.isRestrictedForEntry(entries[i])) {
+ break;
+ }
+ long timeout = Long.valueOf(values[i].toString());
+ if (currentTimeout >= timeout) {
+ best = i;
+ }
+ }
+
+ Preference preference = getPreferenceScreen().findPreference(KEY_TRUST_AGENT);
+ if (preference != null && preference.getTitle().length() > 0) {
+ if (Long.valueOf(values[best].toString()) == 0) {
+ summary = getString(R.string.lock_immediately_summary_with_exception,
+ preference.getTitle());
+ } else {
+ summary = getString(R.string.lock_after_timeout_summary_with_exception,
+ entries[best], preference.getTitle());
+ }
+ } else {
+ summary = getString(R.string.lock_after_timeout_summary, entries[best]);
+ }
}
+ mLockAfter.setSummary(summary);
}
- private void disableUnusableTimeouts(long maxTimeout) {
+ private void disableUnusableTimeouts(long maxTimeout, EnforcedAdmin admin) {
final CharSequence[] entries = mLockAfter.getEntries();
final CharSequence[] values = mLockAfter.getEntryValues();
- ArrayList revisedEntries = new ArrayList();
- ArrayList revisedValues = new ArrayList();
+ long maxTimeoutSelectable = 0;
+ int maxTimeoutEntryIndex = -1;
for (int i = 0; i < values.length; i++) {
- long timeout = Long.valueOf(values[i].toString());
- if (timeout <= maxTimeout) {
- revisedEntries.add(entries[i]);
- revisedValues.add(values[i]);
+ long timeout = Long.parseLong(values[i].toString());
+ if (timeout > maxTimeout) {
+ break;
}
+ maxTimeoutSelectable = timeout;
+ maxTimeoutEntryIndex = i;
}
- if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) {
- mLockAfter.setEntries(
- revisedEntries.toArray(new CharSequence[revisedEntries.size()]));
- mLockAfter.setEntryValues(
- revisedValues.toArray(new CharSequence[revisedValues.size()]));
- final int userPreference = Integer.valueOf(mLockAfter.getValue());
- if (userPreference <= maxTimeout) {
- mLockAfter.setValue(String.valueOf(userPreference));
- } else {
- // There will be no highlighted selection since nothing in the list matches
- // maxTimeout. The user can still select anything less than maxTimeout.
- // TODO: maybe append maxTimeout to the list and mark selected.
- }
+ // If there are no possible options for the user, then set this preference as
+ // disabled by admin, otherwise remove the padlock in case it was set earlier.
+ if (maxTimeoutSelectable == 0) {
+ mLockAfter.setDisabledByAdmin(admin);
+ return;
+ } else {
+ mLockAfter.setDisabledByAdmin(null);
+ }
+
+ mLockAfter.clearRestrictedItems();
+ // Set all the entries after the maximum selectable timeout as disabled by admin.
+ for (int i = maxTimeoutEntryIndex + 1; i < values.length; i++) {
+ mLockAfter.addRestrictedItem(
+ new RestrictedItem(entries[i], values[i], admin));
+ }
+
+ final int userPreference = Integer.valueOf(mLockAfter.getValue());
+ if (userPreference <= maxTimeout) {
+ mLockAfter.setValue(String.valueOf(userPreference));
+ } else if (maxTimeoutSelectable == maxTimeout) {
+ mLockAfter.setValue(String.valueOf(maxTimeout));
+ } else {
+ // There will be no highlighted selection since nothing in the list matches
+ // maxTimeout. The user can still select anything less than maxTimeout.
+ // TODO: maybe append maxTimeout to the list and mark selected.
}
- mLockAfter.setEnabled(revisedEntries.size() > 0);
}
@Override
@@ -651,7 +680,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
}
- if (mResetCredentials != null && !mResetCredentials.isDisabledByAdmin()) {
+ if (mResetCredentials != null) {
mResetCredentials.setEnabled(!mKeyStore.isEmpty());
}
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index d8b9b9195ed..cb3c151c351 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -476,7 +476,10 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
preference.setKey(UUID.randomUUID().toString());
}
DialogFragment f = null;
- if (preference instanceof CustomListPreference) {
+ if (preference instanceof RestrictedListPreference) {
+ f = RestrictedListPreference.RestrictedListPreferenceDialogFragment
+ .newInstance(preference.getKey());
+ } else if (preference instanceof CustomListPreference) {
f = CustomListPreference.CustomListPreferenceDialogFragment
.newInstance(preference.getKey());
} else if (preference instanceof CustomDialogPreference) {