Merge "Set default display timeout if current value is disabled by admin."
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 87d422f..3d9f666 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -57,7 +57,7 @@
     </com.android.settingslib.RestrictedPreference>
 
     <!-- Cross-listed item, if you change this, also change it in power_usage_summary.xml -->
-    <com.android.settings.TimeoutListPreference
+    <com.android.settings.display.TimeoutListPreference
         android:key="screen_timeout"
         android:title="@string/screen_timeout"
         android:summary="@string/summary_placeholder"
diff --git a/res/xml/screen_lock_settings.xml b/res/xml/screen_lock_settings.xml
index 4ef76f4..9b2ef7e 100644
--- a/res/xml/screen_lock_settings.xml
+++ b/res/xml/screen_lock_settings.xml
@@ -26,7 +26,7 @@
         android:title="@string/lockpattern_settings_enable_visible_pattern_title" />
 
     <!-- available in pin/pattern/password -->
-    <com.android.settings.TimeoutListPreference
+    <com.android.settings.display.TimeoutListPreference
         android:key="lock_after_timeout"
         android:title="@string/lock_after_timeout"
         android:summary="@string/summary_placeholder"
diff --git a/src/com/android/settings/TimeoutListPreference.java b/src/com/android/settings/display/TimeoutListPreference.java
similarity index 88%
rename from src/com/android/settings/TimeoutListPreference.java
rename to src/com/android/settings/display/TimeoutListPreference.java
index a0e5906..7512a14 100644
--- a/src/com/android/settings/TimeoutListPreference.java
+++ b/src/com/android/settings/display/TimeoutListPreference.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings;
+package com.android.settings.display;
 
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
@@ -24,13 +24,17 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.View;
 
+import com.android.settings.R;
+import com.android.settings.RestrictedListPreference;
 import com.android.settingslib.RestrictedLockUtils;
 
 import java.util.ArrayList;
 
 public class TimeoutListPreference extends RestrictedListPreference {
+    private static final String TAG = "TimeoutListPreference";
     private EnforcedAdmin mAdmin;
     private final CharSequence[] mInitialEntries;
     private final CharSequence[] mInitialValues;
@@ -115,10 +119,11 @@
                 // If the last one happens to be the same as the max timeout, select that
                 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.
+                // The selected time out value is longer than the max timeout allowed by the admin.
+                // Select the largest value from the list by default.
+                Log.w(TAG, "Default to longest timeout. Value disabled by admin:" + userPreference);
+                setValue(revisedValues.get(revisedValues.size() - 1).toString());
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/display/TimeoutPreferenceController.java b/src/com/android/settings/display/TimeoutPreferenceController.java
index 2beed89..2fbe388 100644
--- a/src/com/android/settings/display/TimeoutPreferenceController.java
+++ b/src/com/android/settings/display/TimeoutPreferenceController.java
@@ -23,7 +23,6 @@
 import android.util.Log;
 
 import com.android.settings.R;
-import com.android.settings.TimeoutListPreference;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -71,12 +70,13 @@
                     dpm.getMaximumTimeToLock(null /* admin */, UserHandle.myUserId());
             timeoutListPreference.removeUnusableTimeouts(maxTimeout, admin);
         }
-        updateTimeoutPreferenceDescription(timeoutListPreference, currentTimeout);
+        updateTimeoutPreferenceDescription(timeoutListPreference,
+                Long.parseLong(timeoutListPreference.getValue()));
 
-        EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
-                        mContext, UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,
-                        UserHandle.myUserId());
-        if(admin != null) {
+        final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
+                mContext, UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,
+                UserHandle.myUserId());
+        if (admin != null) {
             timeoutListPreference.removeUnusableTimeouts(0/* disable all*/, admin);
         }
     }
diff --git a/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java b/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java
index e19ab48..af1c01a 100644
--- a/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java
+++ b/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java
@@ -27,7 +27,7 @@
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
-import com.android.settings.TimeoutListPreference;
+import com.android.settings.display.TimeoutListPreference;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.security.trustagent.TrustAgentManager;
diff --git a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
index 4224462..70cfa21 100644
--- a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java
@@ -61,7 +61,7 @@
     @Test
     public void testDataTitleValid_ReturnsPreferenceTitle() {
         XmlResourceParser parser = getChildByType(R.xml.display_settings,
-                "com.android.settings.TimeoutListPreference");
+                "com.android.settings.display.TimeoutListPreference");
         final AttributeSet attrs = Xml.asAttributeSet(parser);
         String title = PreferenceXmlParserUtils.getDataTitle(mContext, attrs);
         String expTitle = mContext.getString(R.string.screen_timeout);
@@ -80,7 +80,7 @@
     @Test
     public void testDataKeyValid_ReturnsPreferenceKey() {
         XmlResourceParser parser = getChildByType(R.xml.display_settings,
-                "com.android.settings.TimeoutListPreference");
+                "com.android.settings.display.TimeoutListPreference");
         final AttributeSet attrs = Xml.asAttributeSet(parser);
         String key = PreferenceXmlParserUtils.getDataKey(mContext, attrs);
         String expKey = "screen_timeout";
@@ -90,7 +90,7 @@
     @Test
     public void testDataSummaryValid_ReturnsPreferenceSummary() {
         XmlResourceParser parser = getChildByType(R.xml.display_settings,
-                "com.android.settings.TimeoutListPreference");
+                "com.android.settings.display.TimeoutListPreference");
         final AttributeSet attrs = Xml.asAttributeSet(parser);
         String summary = PreferenceXmlParserUtils.getDataSummary(mContext, attrs);
         String expSummary = mContext.getString(R.string.summary_placeholder);
diff --git a/tests/robotests/src/com/android/settings/display/TimeoutListPreferenceTest.java b/tests/robotests/src/com/android/settings/display/TimeoutListPreferenceTest.java
new file mode 100644
index 0000000..0e40fb5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/display/TimeoutListPreferenceTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 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.display;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.robolectric.RuntimeEnvironment.application;
+
+import android.text.TextUtils;
+import android.util.AttributeSet;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+import com.android.settingslib.RestrictedLockUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = ShadowUserManager.class)
+public class TimeoutListPreferenceTest {
+    private static final CharSequence[] VALUES =
+            {"15000", "30000", "60000", "120000", "300000", "600000"};
+    private static final CharSequence[] ENTRIES = {"15s", "30s", "1m", "2m", "5m", "10m"};
+
+    @Mock
+    private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
+
+    private TimeoutListPreference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mPreference = new TimeoutListPreference(application, mock(AttributeSet.class));
+        ReflectionHelpers.setField(mPreference, "mInitialValues", VALUES);
+        ReflectionHelpers.setField(mPreference, "mInitialEntries", ENTRIES);
+        ReflectionHelpers.setField(mPreference, "mEntries", ENTRIES);
+        ReflectionHelpers.setField(mPreference, "mEntryValues", VALUES);
+        ReflectionHelpers.setField(mPreference, "mAdmin", mEnforcedAdmin);
+    }
+
+    @Test
+    public void removeUnusableTimeouts_selectedValueRemoved_shouldSetValueToLargestAllowedValue() {
+        mPreference.setValue("600000"); // set to 10 minutes
+        mPreference.removeUnusableTimeouts(480000L, mEnforcedAdmin); // max allowed is 8 minutes
+
+        // should set to largest allowed value, which is 5 minute
+        assertThat(mPreference.getValue()).isEqualTo("300000");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
index 8627d5f..0447bbb 100644
--- a/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
@@ -18,9 +18,8 @@
 
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
 import static com.google.common.truth.Truth.assertThat;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -31,11 +30,13 @@
 import android.os.UserManager;
 import android.provider.Settings;
 
-import com.android.settings.TimeoutListPreference;
+import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -55,6 +56,7 @@
 
     private static final int TIMEOUT = 30;
     private static final String KEY_SCREEN_TIMEOUT = "screen_timeout";
+    private static final String DEFAULT_TIMEOUT = "300000"; // 5 minutes
 
     private Context mContext;
     @Mock
@@ -69,9 +71,15 @@
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application);
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mPreference.getValue()).thenReturn(DEFAULT_TIMEOUT);
         mController = new TimeoutPreferenceController(mContext, KEY_SCREEN_TIMEOUT);
     }
 
+    @After
+    public void tearDown() {
+          ShadowRestrictedLockUtils.reset();
+    }
+
     @Test
     public void testOnPreferenceChange_SetTimeout_ReturnCorrectTimeout() {
         mController.onPreferenceChange(mPreference, Integer.toString(TIMEOUT));
@@ -125,7 +133,28 @@
 
         verify(mPreference, times(2))
                 .removeUnusableTimeouts(longCaptor.capture(), adminCaptor.capture());
-        assertEquals(0, (long) longCaptor.getValue());
-        assertTrue(adminCaptor.getValue() != null);
+        assertThat((long) longCaptor.getValue()).isEqualTo(0);
+        assertThat(adminCaptor.getValue()).isNotNull();
+    }
+
+    @Test
+    @Config(shadows = ShadowRestrictedLockUtils.class)
+    public void updateState_selectedTimeoutLargerThanAdminMax_shouldSetSummaryToUpdatedPrefValue() {
+        final int profileUserId = UserHandle.myUserId();
+        final long allowedTimeout = 480000L; // 8 minutes
+        when(mUserManager.getProfiles(profileUserId)).thenReturn(Collections.emptyList());
+        ShadowDevicePolicyManager.getShadow().setMaximumTimeToLock(profileUserId, allowedTimeout);
+        ShadowRestrictedLockUtils.setMaximumTimeToLockIsSet(true);
+        final CharSequence[] timeouts = {"15000", "30000", "60000", "120000", "300000", "600000"};
+        final CharSequence[] summaries = {"15s", "30s", "1m", "2m", "5m", "10m"};
+        // set current timeout to be 10 minutes, which is longer than the allowed 8 minutes
+        Settings.System.putLong(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, 600000L);
+        when(mPreference.getEntries()).thenReturn(summaries);
+        when(mPreference.getEntryValues()).thenReturn(timeouts);
+        when(mPreference.getValue()).thenReturn("300000");
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setSummary(mContext.getString(R.string.screen_timeout_summary, "5m"));
     }
 }
diff --git a/tests/robotests/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceControllerTest.java
index 2a4b335..c5e10e0 100644
--- a/tests/robotests/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceControllerTest.java
@@ -30,7 +30,7 @@
 import android.provider.Settings;
 
 import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.TimeoutListPreference;
+import com.android.settings.display.TimeoutListPreference;
 import com.android.settings.security.trustagent.TrustAgentManager;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtils.java
index c6197e7..d1cedec 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtils.java
@@ -33,6 +33,7 @@
     private static boolean sIsRestricted;
     private static boolean sAdminSupportDetailsIntentLaunched;
     private static boolean sHasSystemFeature;
+    private static boolean sMaximumTimeToLockIsSet;
     private static String[] sRestrictedPkgs;
     private static DevicePolicyManager sDevicePolicyManager;
     private static String[] sDisabledTypes;
@@ -45,6 +46,7 @@
         sAdminSupportDetailsIntentLaunched = false;
         sKeyguardDisabledFeatures = 0;
         sDisabledTypes = new String[0];
+        sMaximumTimeToLockIsSet = false;
     }
 
     @Implementation
@@ -101,6 +103,11 @@
         return sIsRestricted ? new EnforcedAdmin() : null;
     }
 
+    @Implementation
+    public static EnforcedAdmin checkIfMaximumTimeToLockIsSet(Context context) {
+        return sMaximumTimeToLockIsSet ? new EnforcedAdmin() : null;
+    }
+
     public static boolean hasAdminSupportDetailsIntentLaunched() {
         return sAdminSupportDetailsIntentLaunched;
     }
@@ -136,4 +143,9 @@
     public static void setKeyguardDisabledFeatures(int features) {
         sKeyguardDisabledFeatures = features;
     }
+
+    public static void setMaximumTimeToLockIsSet(boolean isSet) {
+        sMaximumTimeToLockIsSet = isSet;
+    }
+
 }