Loading aconfig/settings_display_flag_declarations.aconfig 0 → 100644 +9 −0 Original line number Diff line number Diff line package: "com.android.settings.flags" flag { name: "protect_screen_timeout_with_auth" namespace: "safety_center" description: "Require an auth challenge for increasing screen timeout." bug: "315937886" } src/com/android/settings/display/ScreenTimeoutSettings.java +103 −47 Original line number Diff line number Diff line Loading @@ -37,10 +37,12 @@ import android.util.Log; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.flags.Flags; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.support.actionbar.HelpResourceProvider; import com.android.settings.widget.RadioButtonPickerFragment; import com.android.settings.wifi.dpp.WifiDppUtils; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; Loading @@ -55,13 +57,12 @@ import com.google.common.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; /** * Fragment that is used to control screen timeout. */ /** Fragment that is used to control screen timeout. */ @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements HelpResourceProvider { public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements HelpResourceProvider { private static final String TAG = "ScreenTimeout"; /** If there is no setting in the provider, use this. */ public static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000; Loading @@ -72,7 +73,8 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements private FooterPreference mPrivacyPreference; private final MetricsFeatureProvider mMetricsFeatureProvider; private SensorPrivacyManager mPrivacyManager; private final BroadcastReceiver mReceiver = new BroadcastReceiver() { private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { mAdaptiveSleepBatterySaverPreferenceController.updateVisibility(); Loading @@ -82,15 +84,13 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements private DevicePolicyManager mDevicePolicyManager; private SensorPrivacyManager.OnSensorPrivacyChangedListener mPrivacyChangedListener; private boolean mIsUserAuthenticated = false; @VisibleForTesting Context mContext; @VisibleForTesting Context mContext; @VisibleForTesting RestrictedLockUtils.EnforcedAdmin mAdmin; @VisibleForTesting RestrictedLockUtils.EnforcedAdmin mAdmin; @VisibleForTesting FooterPreference mDisableOptionsPreference; @VisibleForTesting FooterPreference mDisableOptionsPreference; @VisibleForTesting FooterPreference mPowerConsumptionPreference; Loading @@ -101,16 +101,14 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements @VisibleForTesting AdaptiveSleepCameraStatePreferenceController mAdaptiveSleepCameraStatePreferenceController; @VisibleForTesting AdaptiveSleepPreferenceController mAdaptiveSleepController; @VisibleForTesting AdaptiveSleepPreferenceController mAdaptiveSleepController; @VisibleForTesting AdaptiveSleepBatterySaverPreferenceController mAdaptiveSleepBatterySaverPreferenceController; public ScreenTimeoutSettings() { super(); mMetricsFeatureProvider = FeatureFactory.getFeatureFactory() .getMetricsFeatureProvider(); mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); } @Override Loading @@ -121,8 +119,8 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements mInitialEntries = getResources().getStringArray(R.array.screen_timeout_entries); mInitialValues = getResources().getStringArray(R.array.screen_timeout_values); mAdaptiveSleepController = new AdaptiveSleepPreferenceController(context); mAdaptiveSleepPermissionController = new AdaptiveSleepPermissionPreferenceController( context); mAdaptiveSleepPermissionController = new AdaptiveSleepPermissionPreferenceController(context); mAdaptiveSleepCameraStatePreferenceController = new AdaptiveSleepCameraStatePreferenceController(context, getLifecycle()); mAdaptiveSleepBatterySaverPreferenceController = Loading @@ -144,8 +142,9 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements if (mInitialValues != null) { for (int i = 0; i < mInitialValues.length; ++i) { if (Long.parseLong(mInitialValues[i].toString()) <= maxTimeout) { candidates.add(new TimeoutCandidateInfo(mInitialEntries[i], mInitialValues[i].toString(), true)); candidates.add( new TimeoutCandidateInfo( mInitialEntries[i], mInitialValues[i].toString(), true)); } } } else { Loading @@ -161,9 +160,10 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements mAdaptiveSleepCameraStatePreferenceController.updateVisibility(); mAdaptiveSleepBatterySaverPreferenceController.updateVisibility(); mAdaptiveSleepController.updatePreference(); mContext.registerReceiver(mReceiver, new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)); mContext.registerReceiver( mReceiver, new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)); mPrivacyManager.addSensorPrivacyListener(CAMERA, mPrivacyChangedListener); mIsUserAuthenticated = false; } @Override Loading @@ -185,19 +185,21 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements } for (CandidateInfo info : candidateList) { SelectorWithWidgetPreference pref = new SelectorWithWidgetPreference(getPrefContext()); ProtectedSelectorWithWidgetPreference pref = new ProtectedSelectorWithWidgetPreference( getPrefContext(), info.getKey(), this); bindPreference(pref, info.getKey(), info, defaultKey); screen.addPreference(pref); } final long selectedTimeout = Long.parseLong(defaultKey); final long selectedTimeout = getTimeoutFromKey(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 SelectorWithWidgetPreference preferenceWithLargestTimeout = (SelectorWithWidgetPreference) screen.getPreference(candidateList.size() - 1); final ProtectedSelectorWithWidgetPreference preferenceWithLargestTimeout = (ProtectedSelectorWithWidgetPreference) screen.getPreference(candidateList.size() - 1); preferenceWithLargestTimeout.setChecked(true); } Loading Loading @@ -225,18 +227,32 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements } } boolean isUserAuthenticated() { return mIsUserAuthenticated; } void setUserAuthenticated(boolean isUserAuthenticated) { mIsUserAuthenticated = isUserAuthenticated; } @VisibleForTesting void setupDisabledFooterPreference() { final String textDisabledByAdmin = mDevicePolicyManager.getResources().getString( OTHER_OPTIONS_DISABLED_BY_ADMIN, () -> getResources().getString( R.string.admin_disabled_other_options)); final String textDisabledByAdmin = mDevicePolicyManager .getResources() .getString( OTHER_OPTIONS_DISABLED_BY_ADMIN, () -> getResources() .getString(R.string.admin_disabled_other_options)); final String textMoreDetails = getResources().getString(R.string.admin_more_details); mDisableOptionsPreference = new FooterPreference(getContext()); mDisableOptionsPreference.setTitle(textDisabledByAdmin); mDisableOptionsPreference.setSelectable(false); mDisableOptionsPreference.setLearnMoreText(textMoreDetails); mDisableOptionsPreference.setLearnMoreAction(v -> { mDisableOptionsPreference.setLearnMoreAction( v -> { RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(), mAdmin); }); mDisableOptionsPreference.setIcon(R.drawable.ic_info_outline_24dp); Loading Loading @@ -303,17 +319,20 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements if (context == null) { return Long.toString(FALLBACK_SCREEN_TIMEOUT_VALUE); } else { return Long.toString(Settings.System.getLong(context.getContentResolver(), SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE)); return Long.toString( Settings.System.getLong( context.getContentResolver(), SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE)); } } private void setCurrentSystemScreenTimeout(Context context, String key) { try { if (context != null) { final long value = Long.parseLong(key); mMetricsFeatureProvider.action(context, SettingsEnums.ACTION_SCREEN_TIMEOUT_CHANGED, (int) value); final long value = getTimeoutFromKey(key); mMetricsFeatureProvider.action( context, SettingsEnums.ACTION_SCREEN_TIMEOUT_CHANGED, (int) value); Settings.System.putLong(context.getContentResolver(), SCREEN_OFF_TIMEOUT, value); } } catch (NumberFormatException e) { Loading @@ -325,7 +344,12 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements return AdaptiveSleepPreferenceController.isAdaptiveSleepSupported(context); } private static class TimeoutCandidateInfo extends CandidateInfo { private static long getTimeoutFromKey(String key) { return Long.parseLong(key); } @VisibleForTesting static class TimeoutCandidateInfo extends CandidateInfo { private final CharSequence mLabel; private final String mKey; Loading @@ -351,10 +375,42 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements } } @VisibleForTesting static class ProtectedSelectorWithWidgetPreference extends SelectorWithWidgetPreference { private final long mTimeoutMs; private final ScreenTimeoutSettings mScreenTimeoutSettings; ProtectedSelectorWithWidgetPreference( Context context, String key, ScreenTimeoutSettings screenTimeoutSettings) { super(context); mTimeoutMs = getTimeoutFromKey(key); mScreenTimeoutSettings = screenTimeoutSettings; } @Override public void onClick() { if (Flags.protectScreenTimeoutWithAuth() && !mScreenTimeoutSettings.isUserAuthenticated() && !isChecked() && mTimeoutMs > getTimeoutFromKey(mScreenTimeoutSettings.getDefaultKey())) { WifiDppUtils.showLockScreen( getContext(), () -> { mScreenTimeoutSettings.setUserAuthenticated(true); super.onClick(); }); } else { super.onClick(); } } } public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.screen_timeout_settings) { public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) { public List<SearchIndexableRaw> getRawDataToIndex( Context context, boolean enabled) { if (!isScreenAttentionAvailable(context)) { return null; } Loading tests/robotests/src/com/android/settings/display/ScreenTimeoutSettingsTest.java +95 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.KeyguardManager; import android.app.admin.DevicePolicyManager; import android.content.ContentResolver; import android.content.Context; Loading @@ -41,31 +42,44 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.res.Resources; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.SearchIndexableResource; import android.provider.Settings; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.flags.Flags; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.widget.CandidateInfo; import com.android.settingslib.widget.FooterPreference; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowKeyguardManager; import java.util.List; @RunWith(RobolectricTestRunner.class) @Config(shadows = { com.android.settings.testutils.shadow.ShadowFragment.class, ShadowKeyguardManager.class }) public class ScreenTimeoutSettingsTest { @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); private static final String[] TIMEOUT_ENTRIES = new String[]{"15 secs", "30 secs"}; private static final String[] TIMEOUT_VALUES = new String[]{"15000", "30000"}; Loading Loading @@ -218,4 +232,85 @@ public class ScreenTimeoutSettingsTest { assertThat(Long.toString(timeout)).isEqualTo(TIMEOUT_VALUES[0]); } @Test @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) public void onClick_whenUserAlreadyAuthenticated_buttonChecked() { String key = "222"; String defaultKey = "1"; mSettings.setDefaultKey(defaultKey); CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( mContext, info.getKey(), mSettings); mSettings.bindPreference(pref, info.getKey(), info, defaultKey); mSettings.setUserAuthenticated(true); pref.onClick(); assertThat(mSettings.getDefaultKey()).isEqualTo(key); } @Test @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) public void onClick_whenButtonAlreadyChecked_noAuthNeeded() { String key = "222"; mSettings.setDefaultKey(key); CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( mContext, info.getKey(), mSettings); mSettings.bindPreference(pref, info.getKey(), info, key); mSettings.setUserAuthenticated(false); setAuthPassesAutomatically(); pref.onClick(); assertThat(mSettings.isUserAuthenticated()).isFalse(); } @Test @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) public void onClick_whenReducingTimeout_noAuthNeeded() { String key = "1"; String defaultKey = "222"; mSettings.setDefaultKey(defaultKey); CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( mContext, info.getKey(), mSettings); mSettings.bindPreference(pref, info.getKey(), info, defaultKey); mSettings.setUserAuthenticated(false); setAuthPassesAutomatically(); pref.onClick(); assertThat(mSettings.isUserAuthenticated()).isFalse(); assertThat(mSettings.getDefaultKey()).isEqualTo(key); } @Test @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) public void onClick_whenIncreasingTimeout_authNeeded() { String key = "222"; String defaultKey = "1"; mSettings.setDefaultKey(defaultKey); CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( mContext, info.getKey(), mSettings); mSettings.bindPreference(pref, info.getKey(), info, defaultKey); mSettings.setUserAuthenticated(false); setAuthPassesAutomatically(); pref.onClick(); assertThat(mSettings.getDefaultKey()).isEqualTo(key); assertThat(mSettings.isUserAuthenticated()).isTrue(); } private void setAuthPassesAutomatically() { Shadows.shadowOf(mContext.getSystemService(KeyguardManager.class)) .setIsKeyguardSecure(false); } } Loading
aconfig/settings_display_flag_declarations.aconfig 0 → 100644 +9 −0 Original line number Diff line number Diff line package: "com.android.settings.flags" flag { name: "protect_screen_timeout_with_auth" namespace: "safety_center" description: "Require an auth challenge for increasing screen timeout." bug: "315937886" }
src/com/android/settings/display/ScreenTimeoutSettings.java +103 −47 Original line number Diff line number Diff line Loading @@ -37,10 +37,12 @@ import android.util.Log; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.flags.Flags; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.support.actionbar.HelpResourceProvider; import com.android.settings.widget.RadioButtonPickerFragment; import com.android.settings.wifi.dpp.WifiDppUtils; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; Loading @@ -55,13 +57,12 @@ import com.google.common.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; /** * Fragment that is used to control screen timeout. */ /** Fragment that is used to control screen timeout. */ @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements HelpResourceProvider { public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements HelpResourceProvider { private static final String TAG = "ScreenTimeout"; /** If there is no setting in the provider, use this. */ public static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000; Loading @@ -72,7 +73,8 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements private FooterPreference mPrivacyPreference; private final MetricsFeatureProvider mMetricsFeatureProvider; private SensorPrivacyManager mPrivacyManager; private final BroadcastReceiver mReceiver = new BroadcastReceiver() { private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { mAdaptiveSleepBatterySaverPreferenceController.updateVisibility(); Loading @@ -82,15 +84,13 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements private DevicePolicyManager mDevicePolicyManager; private SensorPrivacyManager.OnSensorPrivacyChangedListener mPrivacyChangedListener; private boolean mIsUserAuthenticated = false; @VisibleForTesting Context mContext; @VisibleForTesting Context mContext; @VisibleForTesting RestrictedLockUtils.EnforcedAdmin mAdmin; @VisibleForTesting RestrictedLockUtils.EnforcedAdmin mAdmin; @VisibleForTesting FooterPreference mDisableOptionsPreference; @VisibleForTesting FooterPreference mDisableOptionsPreference; @VisibleForTesting FooterPreference mPowerConsumptionPreference; Loading @@ -101,16 +101,14 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements @VisibleForTesting AdaptiveSleepCameraStatePreferenceController mAdaptiveSleepCameraStatePreferenceController; @VisibleForTesting AdaptiveSleepPreferenceController mAdaptiveSleepController; @VisibleForTesting AdaptiveSleepPreferenceController mAdaptiveSleepController; @VisibleForTesting AdaptiveSleepBatterySaverPreferenceController mAdaptiveSleepBatterySaverPreferenceController; public ScreenTimeoutSettings() { super(); mMetricsFeatureProvider = FeatureFactory.getFeatureFactory() .getMetricsFeatureProvider(); mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); } @Override Loading @@ -121,8 +119,8 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements mInitialEntries = getResources().getStringArray(R.array.screen_timeout_entries); mInitialValues = getResources().getStringArray(R.array.screen_timeout_values); mAdaptiveSleepController = new AdaptiveSleepPreferenceController(context); mAdaptiveSleepPermissionController = new AdaptiveSleepPermissionPreferenceController( context); mAdaptiveSleepPermissionController = new AdaptiveSleepPermissionPreferenceController(context); mAdaptiveSleepCameraStatePreferenceController = new AdaptiveSleepCameraStatePreferenceController(context, getLifecycle()); mAdaptiveSleepBatterySaverPreferenceController = Loading @@ -144,8 +142,9 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements if (mInitialValues != null) { for (int i = 0; i < mInitialValues.length; ++i) { if (Long.parseLong(mInitialValues[i].toString()) <= maxTimeout) { candidates.add(new TimeoutCandidateInfo(mInitialEntries[i], mInitialValues[i].toString(), true)); candidates.add( new TimeoutCandidateInfo( mInitialEntries[i], mInitialValues[i].toString(), true)); } } } else { Loading @@ -161,9 +160,10 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements mAdaptiveSleepCameraStatePreferenceController.updateVisibility(); mAdaptiveSleepBatterySaverPreferenceController.updateVisibility(); mAdaptiveSleepController.updatePreference(); mContext.registerReceiver(mReceiver, new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)); mContext.registerReceiver( mReceiver, new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)); mPrivacyManager.addSensorPrivacyListener(CAMERA, mPrivacyChangedListener); mIsUserAuthenticated = false; } @Override Loading @@ -185,19 +185,21 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements } for (CandidateInfo info : candidateList) { SelectorWithWidgetPreference pref = new SelectorWithWidgetPreference(getPrefContext()); ProtectedSelectorWithWidgetPreference pref = new ProtectedSelectorWithWidgetPreference( getPrefContext(), info.getKey(), this); bindPreference(pref, info.getKey(), info, defaultKey); screen.addPreference(pref); } final long selectedTimeout = Long.parseLong(defaultKey); final long selectedTimeout = getTimeoutFromKey(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 SelectorWithWidgetPreference preferenceWithLargestTimeout = (SelectorWithWidgetPreference) screen.getPreference(candidateList.size() - 1); final ProtectedSelectorWithWidgetPreference preferenceWithLargestTimeout = (ProtectedSelectorWithWidgetPreference) screen.getPreference(candidateList.size() - 1); preferenceWithLargestTimeout.setChecked(true); } Loading Loading @@ -225,18 +227,32 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements } } boolean isUserAuthenticated() { return mIsUserAuthenticated; } void setUserAuthenticated(boolean isUserAuthenticated) { mIsUserAuthenticated = isUserAuthenticated; } @VisibleForTesting void setupDisabledFooterPreference() { final String textDisabledByAdmin = mDevicePolicyManager.getResources().getString( OTHER_OPTIONS_DISABLED_BY_ADMIN, () -> getResources().getString( R.string.admin_disabled_other_options)); final String textDisabledByAdmin = mDevicePolicyManager .getResources() .getString( OTHER_OPTIONS_DISABLED_BY_ADMIN, () -> getResources() .getString(R.string.admin_disabled_other_options)); final String textMoreDetails = getResources().getString(R.string.admin_more_details); mDisableOptionsPreference = new FooterPreference(getContext()); mDisableOptionsPreference.setTitle(textDisabledByAdmin); mDisableOptionsPreference.setSelectable(false); mDisableOptionsPreference.setLearnMoreText(textMoreDetails); mDisableOptionsPreference.setLearnMoreAction(v -> { mDisableOptionsPreference.setLearnMoreAction( v -> { RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(), mAdmin); }); mDisableOptionsPreference.setIcon(R.drawable.ic_info_outline_24dp); Loading Loading @@ -303,17 +319,20 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements if (context == null) { return Long.toString(FALLBACK_SCREEN_TIMEOUT_VALUE); } else { return Long.toString(Settings.System.getLong(context.getContentResolver(), SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE)); return Long.toString( Settings.System.getLong( context.getContentResolver(), SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE)); } } private void setCurrentSystemScreenTimeout(Context context, String key) { try { if (context != null) { final long value = Long.parseLong(key); mMetricsFeatureProvider.action(context, SettingsEnums.ACTION_SCREEN_TIMEOUT_CHANGED, (int) value); final long value = getTimeoutFromKey(key); mMetricsFeatureProvider.action( context, SettingsEnums.ACTION_SCREEN_TIMEOUT_CHANGED, (int) value); Settings.System.putLong(context.getContentResolver(), SCREEN_OFF_TIMEOUT, value); } } catch (NumberFormatException e) { Loading @@ -325,7 +344,12 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements return AdaptiveSleepPreferenceController.isAdaptiveSleepSupported(context); } private static class TimeoutCandidateInfo extends CandidateInfo { private static long getTimeoutFromKey(String key) { return Long.parseLong(key); } @VisibleForTesting static class TimeoutCandidateInfo extends CandidateInfo { private final CharSequence mLabel; private final String mKey; Loading @@ -351,10 +375,42 @@ public class ScreenTimeoutSettings extends RadioButtonPickerFragment implements } } @VisibleForTesting static class ProtectedSelectorWithWidgetPreference extends SelectorWithWidgetPreference { private final long mTimeoutMs; private final ScreenTimeoutSettings mScreenTimeoutSettings; ProtectedSelectorWithWidgetPreference( Context context, String key, ScreenTimeoutSettings screenTimeoutSettings) { super(context); mTimeoutMs = getTimeoutFromKey(key); mScreenTimeoutSettings = screenTimeoutSettings; } @Override public void onClick() { if (Flags.protectScreenTimeoutWithAuth() && !mScreenTimeoutSettings.isUserAuthenticated() && !isChecked() && mTimeoutMs > getTimeoutFromKey(mScreenTimeoutSettings.getDefaultKey())) { WifiDppUtils.showLockScreen( getContext(), () -> { mScreenTimeoutSettings.setUserAuthenticated(true); super.onClick(); }); } else { super.onClick(); } } } public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.screen_timeout_settings) { public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) { public List<SearchIndexableRaw> getRawDataToIndex( Context context, boolean enabled) { if (!isScreenAttentionAvailable(context)) { return null; } Loading
tests/robotests/src/com/android/settings/display/ScreenTimeoutSettingsTest.java +95 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.KeyguardManager; import android.app.admin.DevicePolicyManager; import android.content.ContentResolver; import android.content.Context; Loading @@ -41,31 +42,44 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.res.Resources; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.SearchIndexableResource; import android.provider.Settings; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.flags.Flags; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.widget.CandidateInfo; import com.android.settingslib.widget.FooterPreference; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowKeyguardManager; import java.util.List; @RunWith(RobolectricTestRunner.class) @Config(shadows = { com.android.settings.testutils.shadow.ShadowFragment.class, ShadowKeyguardManager.class }) public class ScreenTimeoutSettingsTest { @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); private static final String[] TIMEOUT_ENTRIES = new String[]{"15 secs", "30 secs"}; private static final String[] TIMEOUT_VALUES = new String[]{"15000", "30000"}; Loading Loading @@ -218,4 +232,85 @@ public class ScreenTimeoutSettingsTest { assertThat(Long.toString(timeout)).isEqualTo(TIMEOUT_VALUES[0]); } @Test @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) public void onClick_whenUserAlreadyAuthenticated_buttonChecked() { String key = "222"; String defaultKey = "1"; mSettings.setDefaultKey(defaultKey); CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( mContext, info.getKey(), mSettings); mSettings.bindPreference(pref, info.getKey(), info, defaultKey); mSettings.setUserAuthenticated(true); pref.onClick(); assertThat(mSettings.getDefaultKey()).isEqualTo(key); } @Test @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) public void onClick_whenButtonAlreadyChecked_noAuthNeeded() { String key = "222"; mSettings.setDefaultKey(key); CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( mContext, info.getKey(), mSettings); mSettings.bindPreference(pref, info.getKey(), info, key); mSettings.setUserAuthenticated(false); setAuthPassesAutomatically(); pref.onClick(); assertThat(mSettings.isUserAuthenticated()).isFalse(); } @Test @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) public void onClick_whenReducingTimeout_noAuthNeeded() { String key = "1"; String defaultKey = "222"; mSettings.setDefaultKey(defaultKey); CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( mContext, info.getKey(), mSettings); mSettings.bindPreference(pref, info.getKey(), info, defaultKey); mSettings.setUserAuthenticated(false); setAuthPassesAutomatically(); pref.onClick(); assertThat(mSettings.isUserAuthenticated()).isFalse(); assertThat(mSettings.getDefaultKey()).isEqualTo(key); } @Test @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) public void onClick_whenIncreasingTimeout_authNeeded() { String key = "222"; String defaultKey = "1"; mSettings.setDefaultKey(defaultKey); CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( mContext, info.getKey(), mSettings); mSettings.bindPreference(pref, info.getKey(), info, defaultKey); mSettings.setUserAuthenticated(false); setAuthPassesAutomatically(); pref.onClick(); assertThat(mSettings.getDefaultKey()).isEqualTo(key); assertThat(mSettings.isUserAuthenticated()).isTrue(); } private void setAuthPassesAutomatically() { Shadows.shadowOf(mContext.getSystemService(KeyguardManager.class)) .setIsKeyguardSecure(false); } }