From e9717d265e82b01ff40c0fecf07c7df3a8f499d1 Mon Sep 17 00:00:00 2001 From: Alex Johnston Date: Wed, 7 Apr 2021 12:16:03 +0000 Subject: [PATCH] Fix maximum time to lock Changes * Restore previous timeout behaviour. This behaviour was modified in Android S and was previously working on Android R. * If the selected timeout is less than the max timeout set by the admin, select the largest possible timeout. * If there are no possible timeouts for the user, disable the preference. Manual testing steps * Download CtsVerifier and CtsEmptyDeviceOwner apks * Set device owner * Run Policy transparency test > set max time to lock * Set max time to lock and verify correct value is shown in Settings. Compare behaviour with Android R. Bug: 184104507 Test: manual testing atest com.android.settings.display.ScreenTimeoutSettingsTest Change-Id: I8d0e66ccce14cca244bcd380fd225a31df0b8999 --- .../ScreenTimeoutPreferenceController.java | 82 ++++++++++++++----- .../display/ScreenTimeoutSettings.java | 10 +++ 2 files changed, 72 insertions(+), 20 deletions(-) diff --git a/src/com/android/settings/display/ScreenTimeoutPreferenceController.java b/src/com/android/settings/display/ScreenTimeoutPreferenceController.java index c44376cc52c..2a3359a04b3 100644 --- a/src/com/android/settings/display/ScreenTimeoutPreferenceController.java +++ b/src/com/android/settings/display/ScreenTimeoutPreferenceController.java @@ -40,8 +40,13 @@ import com.android.settingslib.RestrictedPreference; public class ScreenTimeoutPreferenceController extends BasePreferenceController { public static String PREF_NAME = "screen_timeout"; + private final CharSequence[] mTimeoutEntries; + private final CharSequence[] mTimeoutValues; + public ScreenTimeoutPreferenceController(Context context, String key) { super(context, key); + mTimeoutEntries = context.getResources().getStringArray(R.array.screen_timeout_entries); + mTimeoutValues = context.getResources().getStringArray(R.array.screen_timeout_values); } @Override @@ -51,33 +56,51 @@ public class ScreenTimeoutPreferenceController extends BasePreferenceController @Override public void updateState(Preference preference) { - final RestrictedLockUtils.EnforcedAdmin admin = getEnforcedAdmin(); + final long maxTimeout = getMaxScreenTimeout(); + final RestrictedLockUtils.EnforcedAdmin admin = getPreferenceDisablingAdmin(maxTimeout); if (admin != null) { preference.setEnabled(false); + preference.setSummary(mContext.getText(R.string.disabled_by_policy_title)); ((RestrictedPreference) preference).setDisabledByAdmin(admin); + } else { + preference.setSummary(getTimeoutSummary(maxTimeout)); } - preference.setSummary(getTimeoutSummary()); } - private CharSequence getTimeoutSummary() { + private CharSequence getTimeoutSummary(long maxTimeout) { final long currentTimeout = getCurrentScreenTimeout(); - final CharSequence[] timeoutEntries = mContext.getResources().getStringArray( - R.array.screen_timeout_entries); - final CharSequence[] timeoutValues = mContext.getResources().getStringArray( - R.array.screen_timeout_values); - final CharSequence description = getTimeoutDescription( - currentTimeout, timeoutEntries, timeoutValues); + final CharSequence description = getTimeoutDescription(currentTimeout, maxTimeout); return mContext.getString(R.string.screen_timeout_summary, description); } - private RestrictedLockUtils.EnforcedAdmin getEnforcedAdmin() { + private Long getMaxScreenTimeout() { + if (RestrictedLockUtilsInternal.checkIfMaximumTimeToLockIsSet(mContext) != null) { + final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class); + if (dpm != null) { + return dpm.getMaximumTimeToLock(null /* admin */, UserHandle.myUserId()); + } + } + return Long.MAX_VALUE; + } + + /** + * Returns the admin that causes the preference to be disabled completely. This could be due to + * either an admin that has set the {@link UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT} + * restriction, or an admin that has set a very small MaximumTimeToLock timeout resulting in + * no possible options for the user. + */ + private RestrictedLockUtils.EnforcedAdmin getPreferenceDisablingAdmin(long maxTimeout) { final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class); + RestrictedLockUtils.EnforcedAdmin admin = null; if (dpm != null) { - return RestrictedLockUtilsInternal.checkIfRestrictionEnforced( + admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced( mContext, UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT, UserHandle.myUserId()); + if (admin == null && getLargestTimeout(maxTimeout) == null) { + admin = RestrictedLockUtilsInternal.checkIfMaximumTimeToLockIsSet(mContext); + } } - return null; + return admin; } private long getCurrentScreenTimeout() { @@ -85,19 +108,38 @@ public class ScreenTimeoutPreferenceController extends BasePreferenceController SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE); } - private static CharSequence getTimeoutDescription( - long currentTimeout, CharSequence[] entries, CharSequence[] values) { - if (currentTimeout < 0 || entries == null || values == null - || values.length != entries.length) { + private CharSequence getTimeoutDescription(long currentTimeout, long maxTimeout) { + if (currentTimeout < 0 || mTimeoutEntries == null || mTimeoutValues == null + || mTimeoutValues.length != mTimeoutEntries.length) { return null; } - for (int i = 0; i < values.length; i++) { - long timeout = Long.parseLong(values[i].toString()); - if (currentTimeout == timeout) { - return entries[i]; + if (currentTimeout > maxTimeout) { + // The selected time out value is longer than the max timeout allowed by the admin. + // Select the largest value from the list by default. + return getLargestTimeout(maxTimeout); + } else { + return getCurrentTimeout(currentTimeout); + } + } + + private CharSequence getCurrentTimeout(long currentTimeout) { + for (int i = 0; i < mTimeoutValues.length; i++) { + if (currentTimeout == Long.parseLong(mTimeoutValues[i].toString())) { + return mTimeoutEntries[i]; } } return null; } + + private CharSequence getLargestTimeout(long maxTimeout) { + CharSequence largestTimeout = null; + // The list of timeouts is sorted + for (int i = 0; i < mTimeoutValues.length; ++i) { + if (Long.parseLong(mTimeoutValues[i].toString()) <= maxTimeout) { + largestTimeout = mTimeoutEntries[i]; + } + } + return largestTimeout; + } } diff --git a/src/com/android/settings/display/ScreenTimeoutSettings.java b/src/com/android/settings/display/ScreenTimeoutSettings.java index a15a7a03f6b..f4f052b5c64 100644 --- a/src/com/android/settings/display/ScreenTimeoutSettings.java +++ b/src/com/android/settings/display/ScreenTimeoutSettings.java @@ -145,6 +145,16 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements screen.addPreference(pref); } + final long selectedTimeout = Long.parseLong(defaultKey); + final long maxTimeout = getMaxScreenTimeout(getContext()); + if (!candidateList.isEmpty() && (selectedTimeout > maxTimeout)) { + // The selected time out value is longer than the max timeout allowed by the admin. + // Select the largest value from the list by default. + final RadioButtonPreference preferenceWithLargestTimeout = + (RadioButtonPreference) screen.getPreference(candidateList.size() - 1); + preferenceWithLargestTimeout.setChecked(true); + } + if (isScreenAttentionAvailable(getContext())) { mAdaptiveSleepPermissionController.addToScreen(screen); mAdaptiveSleepController.addToScreen(screen);