1 /* 2 * Copyright (C) 2016 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.datetime; 18 19 import static android.app.time.DetectorStatusTypes.DETECTION_ALGORITHM_STATUS_NOT_SUPPORTED; 20 import static android.app.time.DetectorStatusTypes.DETECTION_ALGORITHM_STATUS_RUNNING; 21 import static android.app.time.DetectorStatusTypes.DETECTOR_STATUS_RUNNING; 22 import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_NOT_PRESENT; 23 import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_NOT_READY; 24 25 import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING; 26 27 import static com.google.common.truth.Truth.assertThat; 28 29 import static org.mockito.Mockito.spy; 30 import static org.mockito.Mockito.verify; 31 import static org.mockito.Mockito.when; 32 33 import android.app.time.Capabilities; 34 import android.app.time.LocationTimeZoneAlgorithmStatus; 35 import android.app.time.TelephonyTimeZoneAlgorithmStatus; 36 import android.app.time.TimeManager; 37 import android.app.time.TimeZoneCapabilities; 38 import android.app.time.TimeZoneCapabilitiesAndConfig; 39 import android.app.time.TimeZoneConfiguration; 40 import android.app.time.TimeZoneDetectorStatus; 41 import android.content.Context; 42 import android.os.UserHandle; 43 44 import androidx.preference.Preference; 45 46 import com.android.settings.R; 47 48 import org.junit.Before; 49 import org.junit.Test; 50 import org.junit.runner.RunWith; 51 import org.mockito.Mock; 52 import org.mockito.Mockito; 53 import org.mockito.MockitoAnnotations; 54 import org.robolectric.RobolectricTestRunner; 55 import org.robolectric.RuntimeEnvironment; 56 57 @RunWith(RobolectricTestRunner.class) 58 public class AutoTimeZonePreferenceControllerTest { 59 60 @Mock 61 private UpdateTimeAndDateCallback mCallback; 62 private Context mContext; 63 private Preference mPreference; 64 @Mock 65 private TimeManager mTimeManager; 66 67 private AutoTimeZonePreferenceController mController; 68 69 @Before setUp()70 public void setUp() { 71 MockitoAnnotations.initMocks(this); 72 mContext = spy(RuntimeEnvironment.application); 73 74 mPreference = new Preference(mContext); 75 76 when(mContext.getSystemService(TimeManager.class)).thenReturn(mTimeManager); 77 78 mController = new AutoTimeZonePreferenceController(mContext, "test_key"); 79 mController.setFromSUW(false); 80 } 81 82 @Test isFromSUW_notAvailable()83 public void isFromSUW_notAvailable() { 84 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 85 /* autoSupported= */true, /* autoEnabled= */false); 86 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 87 88 mController.setFromSUW(true); 89 90 assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); 91 } 92 93 @Test notFromSUW_isAvailable()94 public void notFromSUW_isAvailable() { 95 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 96 /* autoSupported= */true, /* autoEnabled= */false); 97 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 98 99 mController.setFromSUW(false); 100 101 assertThat(mController.isAvailable()).isTrue(); 102 } 103 104 @Test autoTimeZoneNotSupported_notAvailable()105 public void autoTimeZoneNotSupported_notAvailable() { 106 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 107 /* autoSupported= */false, /* autoEnabled= */false); 108 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 109 110 assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); 111 } 112 113 @Test isFromSUW_notEnable()114 public void isFromSUW_notEnable() { 115 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 116 /* autoSupported= */false, /* autoEnabled= */false); 117 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 118 119 mController.setFromSUW(true); 120 121 assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); 122 } 123 124 @Test isFromSUW_isEnable()125 public void isFromSUW_isEnable() { 126 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 127 /* autoSupported= */false, /* autoEnabled= */true); 128 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 129 130 mController.setFromSUW(true); 131 132 assertThat(mController.isAvailable()).isTrue(); 133 } 134 135 @Test autoTimeZoneNotSupported_notEnable()136 public void autoTimeZoneNotSupported_notEnable() { 137 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 138 /* autoSupported= */false, /* autoEnabled= */false); 139 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 140 141 assertThat(mController.isEnabled()).isFalse(); 142 } 143 144 @Test isEnabled_autoEnabledIsFalse_shouldReadFromTimeManagerConfig()145 public void isEnabled_autoEnabledIsFalse_shouldReadFromTimeManagerConfig() { 146 // Disabled 147 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 148 /* autoSupported= */true, /* autoEnabled= */false); 149 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 150 151 assertThat(mController.isEnabled()).isFalse(); 152 } 153 154 @Test isEnabled_autoEnabledIsTrue_shouldReadFromTimeManagerConfig()155 public void isEnabled_autoEnabledIsTrue_shouldReadFromTimeManagerConfig() { 156 // Enabled 157 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 158 /* autoSupported= */true, /* autoEnabled= */true); 159 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 160 161 assertThat(mController.isEnabled()).isTrue(); 162 } 163 164 @Test updatePreferenceChange_prefIsChecked_shouldUpdatePreferenceAndNotifyCallback()165 public void updatePreferenceChange_prefIsChecked_shouldUpdatePreferenceAndNotifyCallback() { 166 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 167 /* autoSupported= */true, /* autoEnabled= */false); 168 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 169 when(mTimeManager.updateTimeZoneConfiguration(Mockito.any())).thenReturn(true); 170 171 mController.setTimeAndDateCallback(mCallback); 172 173 assertThat(mController.onPreferenceChange(mPreference, true)).isTrue(); 174 verify(mCallback).updateTimeAndDateDisplay(mContext); 175 176 // Check the service was asked to change the configuration correctly. 177 TimeZoneConfiguration timeZoneConfiguration = new TimeZoneConfiguration.Builder() 178 .setAutoDetectionEnabled(true) 179 .build(); 180 verify(mTimeManager).updateTimeZoneConfiguration(timeZoneConfiguration); 181 182 // Update the mTimeManager mock so that it now returns the expected updated config. 183 TimeZoneCapabilitiesAndConfig capabilitiesAndConfigAfterUpdate = 184 createCapabilitiesAndConfig(/* autoSupported= */true, /* autoEnabled= */true); 185 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()) 186 .thenReturn(capabilitiesAndConfigAfterUpdate); 187 188 assertThat(mController.isEnabled()).isTrue(); 189 } 190 191 @Test updatePreferenceChange_prefIsUnchecked_shouldUpdatePreferenceAndNotifyCallback()192 public void updatePreferenceChange_prefIsUnchecked_shouldUpdatePreferenceAndNotifyCallback() { 193 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 194 /* autoSupported= */true, /* autoEnabled= */true); 195 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 196 when(mTimeManager.updateTimeZoneConfiguration(Mockito.any())).thenReturn(true); 197 198 mController.setTimeAndDateCallback(mCallback); 199 200 assertThat(mController.onPreferenceChange(mPreference, false)).isTrue(); 201 verify(mCallback).updateTimeAndDateDisplay(mContext); 202 203 // Check the service was asked to change the configuration correctly. 204 TimeZoneConfiguration timeZoneConfiguration = new TimeZoneConfiguration.Builder() 205 .setAutoDetectionEnabled(false) 206 .build(); 207 verify(mTimeManager).updateTimeZoneConfiguration(timeZoneConfiguration); 208 209 // Update the mTimeManager mock so that it now returns the expected updated config. 210 TimeZoneCapabilitiesAndConfig capabilitiesAndConfigAfterUpdate = 211 createCapabilitiesAndConfig(/* autoSupported= */true, /* autoEnabled= */false); 212 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()) 213 .thenReturn(capabilitiesAndConfigAfterUpdate); 214 215 assertThat(mController.isEnabled()).isFalse(); 216 } 217 218 @Test getSummary()219 public void getSummary() { 220 mController.setTimeAndDateCallback(mCallback); 221 222 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 223 /* autoSupported= */true, /* autoEnabled= */true, /* telephonySupported= */ 224 true); 225 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 226 when(mTimeManager.updateTimeZoneConfiguration(Mockito.any())).thenReturn(true); 227 228 assertThat(mController.getSummary().toString()).isEqualTo( 229 mContext.getString(R.string.zone_auto_title_summary)); 230 231 capabilitiesAndConfig = createCapabilitiesAndConfig( 232 /* autoSupported= */true, /* autoEnabled= */true, /* telephonySupported= */ 233 false); 234 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 235 when(mTimeManager.updateTimeZoneConfiguration(Mockito.any())).thenReturn(true); 236 237 assertThat(mController.getSummary().toString()).isEqualTo( 238 mContext.getString(R.string.auto_zone_requires_location_summary)); 239 } 240 241 @Test toggleOff_revampFlagOn_shouldToggleOffUseLocation()242 public void toggleOff_revampFlagOn_shouldToggleOffUseLocation() { 243 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig( 244 /* autoSupported= */ true, 245 /* autoEnabled= */ true, 246 /* telephonySupported= */ true, 247 /* locationSupported= */ true); 248 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 249 250 mController.setChecked(false); 251 252 TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder() 253 .setAutoDetectionEnabled(false) 254 .setGeoDetectionEnabled(false) 255 .build(); 256 257 verify(mTimeManager).updateTimeZoneConfiguration(configuration); 258 } 259 createCapabilitiesAndConfig( boolean autoSupported, boolean autoEnabled, boolean telephonySupported)260 private static TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig( 261 boolean autoSupported, boolean autoEnabled, boolean telephonySupported) { 262 return createCapabilitiesAndConfig(autoSupported, autoEnabled, telephonySupported, false); 263 } 264 createCapabilitiesAndConfig( boolean autoSupported, boolean autoEnabled, boolean telephonySupported, boolean locationSupported)265 private static TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig( 266 boolean autoSupported, boolean autoEnabled, boolean telephonySupported, 267 boolean locationSupported) { 268 TimeZoneDetectorStatus status = new TimeZoneDetectorStatus(DETECTOR_STATUS_RUNNING, 269 new TelephonyTimeZoneAlgorithmStatus( 270 telephonySupported ? DETECTION_ALGORITHM_STATUS_RUNNING 271 : DETECTION_ALGORITHM_STATUS_NOT_SUPPORTED), 272 new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING, 273 PROVIDER_STATUS_NOT_READY, null, 274 PROVIDER_STATUS_NOT_PRESENT, null)); 275 int configureAutoDetectionEnabledCapability = 276 autoSupported ? Capabilities.CAPABILITY_POSSESSED 277 : Capabilities.CAPABILITY_NOT_SUPPORTED; 278 TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder(UserHandle.SYSTEM) 279 .setConfigureAutoDetectionEnabledCapability(configureAutoDetectionEnabledCapability) 280 .setUseLocationEnabled(true) 281 .setConfigureGeoDetectionEnabledCapability( 282 locationSupported ? Capabilities.CAPABILITY_POSSESSED 283 : Capabilities.CAPABILITY_NOT_SUPPORTED) 284 .setSetManualTimeZoneCapability(Capabilities.CAPABILITY_POSSESSED) 285 .setConfigureNotificationsEnabledCapability(Capabilities.CAPABILITY_POSSESSED) 286 .build(); 287 TimeZoneConfiguration config = new TimeZoneConfiguration.Builder() 288 .setAutoDetectionEnabled(autoEnabled) 289 .setGeoDetectionEnabled(locationSupported) 290 .setNotificationsEnabled(true) 291 .build(); 292 return new TimeZoneCapabilitiesAndConfig(status, capabilities, config); 293 } 294 createCapabilitiesAndConfig( boolean autoSupported, boolean autoEnabled)295 private static TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig( 296 boolean autoSupported, boolean autoEnabled) { 297 return createCapabilitiesAndConfig(autoSupported, autoEnabled, false); 298 } 299 } 300