1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.display; 18 19 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; 20 21 import static androidx.test.core.app.ApplicationProvider.getApplicationContext; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import static org.mockito.ArgumentMatchers.any; 26 import static org.mockito.ArgumentMatchers.anyInt; 27 import static org.mockito.ArgumentMatchers.isA; 28 import static org.mockito.Mockito.atLeast; 29 import static org.mockito.Mockito.doNothing; 30 import static org.mockito.Mockito.doReturn; 31 import static org.mockito.Mockito.never; 32 import static org.mockito.Mockito.spy; 33 import static org.mockito.Mockito.verify; 34 import static org.mockito.Mockito.when; 35 36 import android.app.KeyguardManager; 37 import android.app.admin.DevicePolicyManager; 38 import android.content.ContentResolver; 39 import android.content.Context; 40 import android.content.Intent; 41 import android.content.pm.PackageManager; 42 import android.content.pm.ResolveInfo; 43 import android.content.pm.ServiceInfo; 44 import android.content.res.Resources; 45 import android.platform.test.annotations.RequiresFlagsEnabled; 46 import android.platform.test.flag.junit.CheckFlagsRule; 47 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 48 import android.provider.SearchIndexableResource; 49 import android.provider.Settings; 50 51 import androidx.preference.PreferenceScreen; 52 53 import com.android.settings.R; 54 import com.android.settings.flags.Flags; 55 import com.android.settings.testutils.FakeFeatureFactory; 56 import com.android.settingslib.RestrictedLockUtils; 57 import com.android.settingslib.widget.CandidateInfo; 58 import com.android.settingslib.widget.FooterPreference; 59 60 import org.junit.Before; 61 import org.junit.Rule; 62 import org.junit.Test; 63 import org.junit.runner.RunWith; 64 import org.mockito.Mock; 65 import org.mockito.MockitoAnnotations; 66 import org.robolectric.RobolectricTestRunner; 67 import org.robolectric.Shadows; 68 import org.robolectric.annotation.Config; 69 import org.robolectric.shadows.ShadowKeyguardManager; 70 71 import java.util.List; 72 73 @RunWith(RobolectricTestRunner.class) 74 @Config(shadows = { 75 com.android.settings.testutils.shadow.ShadowFragment.class, 76 ShadowKeyguardManager.class 77 }) 78 public class ScreenTimeoutSettingsTest { 79 80 @Rule 81 public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); 82 83 private static final String[] TIMEOUT_ENTRIES = new String[]{"15 secs", "30 secs"}; 84 private static final String[] TIMEOUT_VALUES = new String[]{"15000", "30000"}; 85 86 private ScreenTimeoutSettings mSettings; 87 private Context mContext; 88 private ContentResolver mContentResolver; 89 private Resources mResources; 90 91 @Mock 92 private PreferenceScreen mPreferenceScreen; 93 94 @Mock 95 AdaptiveSleepPermissionPreferenceController mPermissionPreferenceController; 96 97 @Mock 98 AdaptiveSleepPreferenceController mAdaptiveSleepPreferenceController; 99 100 @Mock 101 AdaptiveSleepCameraStatePreferenceController mAdaptiveSleepCameraStatePreferenceController; 102 103 @Mock 104 AdaptiveSleepBatterySaverPreferenceController mAdaptiveSleepBatterySaverPreferenceController; 105 106 @Mock 107 FooterPreference mDisableOptionsPreference; 108 109 @Mock 110 FooterPreference mPowerConsumptionPreference; 111 112 @Mock 113 private PackageManager mPackageManager; 114 115 @Before setup()116 public void setup() { 117 MockitoAnnotations.initMocks(this); 118 FakeFeatureFactory.setupForTest(); 119 mContext = spy(getApplicationContext()); 120 mSettings = spy(new ScreenTimeoutSettings()); 121 mSettings.mContext = mContext; 122 mContentResolver = mContext.getContentResolver(); 123 mResources = spy(mContext.getResources()); 124 125 doReturn(mPackageManager).when(mContext).getPackageManager(); 126 when(mPackageManager.getAttentionServicePackageName()).thenReturn("some.package"); 127 when(mPackageManager.checkPermission(any(), any())).thenReturn( 128 PackageManager.PERMISSION_GRANTED); 129 final ResolveInfo attentionServiceResolveInfo = new ResolveInfo(); 130 attentionServiceResolveInfo.serviceInfo = new ServiceInfo(); 131 when(mPackageManager.resolveService(isA(Intent.class), anyInt())).thenReturn( 132 attentionServiceResolveInfo); 133 134 doReturn(TIMEOUT_ENTRIES).when(mResources).getStringArray(R.array.screen_timeout_entries); 135 doReturn(TIMEOUT_VALUES).when(mResources).getStringArray(R.array.screen_timeout_entries); 136 doReturn(true).when(mResources).getBoolean( 137 com.android.internal.R.bool.config_adaptive_sleep_available); 138 139 doReturn(null).when(mContext).getSystemService(DevicePolicyManager.class); 140 doReturn(mResources).when(mContext).getResources(); 141 142 doReturn(mResources).when(mSettings).getResources(); 143 doReturn(mContext).when(mSettings).getContext(); 144 doReturn(mPreferenceScreen).when(mSettings).getPreferenceScreen(); 145 146 mSettings.mAdaptiveSleepController = mAdaptiveSleepPreferenceController; 147 mSettings.mAdaptiveSleepPermissionController = mPermissionPreferenceController; 148 mSettings.mAdaptiveSleepCameraStatePreferenceController = 149 mAdaptiveSleepCameraStatePreferenceController; 150 mSettings.mAdaptiveSleepBatterySaverPreferenceController = 151 mAdaptiveSleepBatterySaverPreferenceController; 152 } 153 154 @Test searchIndexProvider_shouldIndexResource()155 public void searchIndexProvider_shouldIndexResource() { 156 final List<SearchIndexableResource> indexRes = 157 ScreenTimeoutSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex( 158 mContext, true /* enabled */); 159 160 assertThat(indexRes).isNotNull(); 161 assertThat(indexRes.get(0).xmlResId).isEqualTo(mSettings.getPreferenceScreenResId()); 162 } 163 164 @Test getDefaultKey_returnCurrentTimeout()165 public void getDefaultKey_returnCurrentTimeout() { 166 long timeout = Long.parseLong(TIMEOUT_VALUES[1]); 167 Settings.System.putLong(mContentResolver, SCREEN_OFF_TIMEOUT, timeout); 168 169 String key = mSettings.getDefaultKey(); 170 171 assertThat(key).isEqualTo(TIMEOUT_VALUES[1]); 172 } 173 174 @Test updateCandidates_screenAttentionAvailable_showAdaptiveSleepPreference()175 public void updateCandidates_screenAttentionAvailable_showAdaptiveSleepPreference() { 176 mSettings.updateCandidates(); 177 178 verify(mSettings.mAdaptiveSleepController).addToScreen(mPreferenceScreen); 179 } 180 181 @Test updateCandidates_screenAttentionNotAvailable_doNotShowAdaptiveSleepPreference()182 public void updateCandidates_screenAttentionNotAvailable_doNotShowAdaptiveSleepPreference() { 183 doReturn(false).when(mResources).getBoolean( 184 com.android.internal.R.bool.config_adaptive_sleep_available); 185 186 mSettings.updateCandidates(); 187 188 verify(mSettings.mAdaptiveSleepController, never()).addToScreen(mPreferenceScreen); 189 } 190 191 @Test updateCandidates_AttentionServiceNotInstalled_doNoShowAdaptiveSleepPreference()192 public void updateCandidates_AttentionServiceNotInstalled_doNoShowAdaptiveSleepPreference() { 193 when(mPackageManager.resolveService(isA(Intent.class), anyInt())).thenReturn(null); 194 195 verify(mSettings.mAdaptiveSleepController, never()).addToScreen(mPreferenceScreen); 196 } 197 198 @Test updateCandidates_enforcedAdmin_showDisabledByAdminPreference()199 public void updateCandidates_enforcedAdmin_showDisabledByAdminPreference() { 200 mSettings.mAdmin = new RestrictedLockUtils.EnforcedAdmin(); 201 mSettings.mDisableOptionsPreference = mDisableOptionsPreference; 202 mSettings.mPowerConsumptionPreference = mPowerConsumptionPreference; 203 doNothing().when(mSettings).setupDisabledFooterPreference(); 204 doNothing().when(mSettings).setupPowerConsumptionFooterPreference(); 205 206 mSettings.updateCandidates(); 207 208 verify(mPreferenceScreen, atLeast(1)).addPreference(mDisableOptionsPreference); 209 verify(mPreferenceScreen, never()).addPreference(mPowerConsumptionPreference); 210 } 211 212 @Test updateCandidates_withoutAdmin_showPowerConsumptionPreference()213 public void updateCandidates_withoutAdmin_showPowerConsumptionPreference() { 214 mSettings.mAdmin = null; 215 mSettings.mDisableOptionsPreference = mDisableOptionsPreference; 216 mSettings.mPowerConsumptionPreference = mPowerConsumptionPreference; 217 doNothing().when(mSettings).setupDisabledFooterPreference(); 218 doNothing().when(mSettings).setupPowerConsumptionFooterPreference(); 219 220 mSettings.updateCandidates(); 221 222 verify(mPreferenceScreen, never()).addPreference(mDisableOptionsPreference); 223 verify(mPreferenceScreen, atLeast(1)).addPreference(mPowerConsumptionPreference); 224 } 225 226 @Test setDefaultKey_controlCurrentScreenTimeout()227 public void setDefaultKey_controlCurrentScreenTimeout() { 228 mSettings.setDefaultKey(TIMEOUT_VALUES[0]); 229 230 long timeout = Settings.System.getLong(mContentResolver, SCREEN_OFF_TIMEOUT, 231 30000 /* default */); 232 233 assertThat(Long.toString(timeout)).isEqualTo(TIMEOUT_VALUES[0]); 234 } 235 236 @Test 237 @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) onClick_whenUserAlreadyAuthenticated_buttonChecked()238 public void onClick_whenUserAlreadyAuthenticated_buttonChecked() { 239 String key = "222"; 240 String defaultKey = "1"; 241 mSettings.setDefaultKey(defaultKey); 242 CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); 243 ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = 244 new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( 245 mContext, info.getKey(), mSettings); 246 mSettings.bindPreference(pref, info.getKey(), info, defaultKey); 247 mSettings.setUserAuthenticated(true); 248 249 pref.onClick(); 250 251 assertThat(mSettings.getDefaultKey()).isEqualTo(key); 252 } 253 254 @Test 255 @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) onClick_whenButtonAlreadyChecked_noAuthNeeded()256 public void onClick_whenButtonAlreadyChecked_noAuthNeeded() { 257 String key = "222"; 258 mSettings.setDefaultKey(key); 259 CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); 260 ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = 261 new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( 262 mContext, info.getKey(), mSettings); 263 mSettings.bindPreference(pref, info.getKey(), info, key); 264 mSettings.setUserAuthenticated(false); 265 setAuthPassesAutomatically(); 266 267 pref.onClick(); 268 269 assertThat(mSettings.isUserAuthenticated()).isFalse(); 270 } 271 272 @Test 273 @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) onClick_whenReducingTimeout_noAuthNeeded()274 public void onClick_whenReducingTimeout_noAuthNeeded() { 275 String key = "1"; 276 String defaultKey = "222"; 277 mSettings.setDefaultKey(defaultKey); 278 CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); 279 ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = 280 new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( 281 mContext, info.getKey(), mSettings); 282 mSettings.bindPreference(pref, info.getKey(), info, defaultKey); 283 mSettings.setUserAuthenticated(false); 284 setAuthPassesAutomatically(); 285 286 pref.onClick(); 287 288 assertThat(mSettings.isUserAuthenticated()).isFalse(); 289 assertThat(mSettings.getDefaultKey()).isEqualTo(key); 290 } 291 292 @Test 293 @RequiresFlagsEnabled(Flags.FLAG_PROTECT_SCREEN_TIMEOUT_WITH_AUTH) onClick_whenIncreasingTimeout_authNeeded()294 public void onClick_whenIncreasingTimeout_authNeeded() { 295 String key = "222"; 296 String defaultKey = "1"; 297 mSettings.setDefaultKey(defaultKey); 298 CandidateInfo info = new ScreenTimeoutSettings.TimeoutCandidateInfo("label", key, false); 299 ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference pref = 300 new ScreenTimeoutSettings.ProtectedSelectorWithWidgetPreference( 301 mContext, info.getKey(), mSettings); 302 mSettings.bindPreference(pref, info.getKey(), info, defaultKey); 303 mSettings.setUserAuthenticated(false); 304 setAuthPassesAutomatically(); 305 306 pref.onClick(); 307 308 assertThat(mSettings.getDefaultKey()).isEqualTo(key); 309 assertThat(mSettings.isUserAuthenticated()).isTrue(); 310 } 311 setAuthPassesAutomatically()312 private void setAuthPassesAutomatically() { 313 Shadows.shadowOf(mContext.getSystemService(KeyguardManager.class)) 314 .setIsKeyguardSecure(false); 315 } 316 } 317