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.datetime; 18 19 import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE; 20 import static android.app.time.Capabilities.CAPABILITY_NOT_SUPPORTED; 21 import static android.app.time.Capabilities.CAPABILITY_POSSESSED; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.verifyZeroInteractions; 28 import static org.mockito.Mockito.when; 29 30 import android.app.time.Capabilities; 31 import android.app.time.TimeManager; 32 import android.app.time.TimeZoneCapabilities; 33 import android.app.time.TimeZoneCapabilitiesAndConfig; 34 import android.app.time.TimeZoneConfiguration; 35 import android.content.Context; 36 import android.location.LocationManager; 37 import android.os.UserHandle; 38 39 import com.android.settings.R; 40 import com.android.settings.core.InstrumentedPreferenceFragment; 41 import com.android.settingslib.core.lifecycle.Lifecycle; 42 43 import org.junit.Before; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 import org.mockito.Answers; 47 import org.mockito.Mock; 48 import org.mockito.MockitoAnnotations; 49 import org.robolectric.RobolectricTestRunner; 50 import org.robolectric.RuntimeEnvironment; 51 52 @RunWith(RobolectricTestRunner.class) 53 public class LocationTimeZoneDetectionPreferenceControllerTest { 54 @Mock 55 private TimeManager mTimeManager; 56 @Mock 57 private LocationManager mLocationManager; 58 private Context mContext; 59 private LocationTimeZoneDetectionPreferenceController mController; 60 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 61 private InstrumentedPreferenceFragment mFragment; 62 @Mock 63 private Lifecycle mLifecycle; 64 65 @Before setUp()66 public void setUp() { 67 MockitoAnnotations.initMocks(this); 68 mContext = spy(RuntimeEnvironment.application); 69 when(mContext.getSystemService(TimeManager.class)).thenReturn(mTimeManager); 70 when(mContext.getSystemService(LocationManager.class)).thenReturn(mLocationManager); 71 mController = new LocationTimeZoneDetectionPreferenceController(mContext); 72 mController.setFragment(mFragment); 73 } 74 75 @Test setChecked_withTrue_shouldUpdateSetting_whenLocationIsEnabled()76 public void setChecked_withTrue_shouldUpdateSetting_whenLocationIsEnabled() { 77 when(mLocationManager.isLocationEnabled()).thenReturn(true); 78 79 // Simulate the UI being clicked. 80 mController.setChecked(true); 81 82 // Verify the TimeManager was updated with the UI value. 83 TimeZoneConfiguration expectedConfiguration = new TimeZoneConfiguration.Builder() 84 .setGeoDetectionEnabled(true) 85 .build(); 86 verify(mTimeManager).updateTimeZoneConfiguration(expectedConfiguration); 87 } 88 89 @Test isNotSliceable()90 public void isNotSliceable() { 91 assertThat(mController.isSliceable()).isFalse(); 92 } 93 94 @Test setChecked_withTrue_shouldDoNothing_whenLocationIsDisabled()95 public void setChecked_withTrue_shouldDoNothing_whenLocationIsDisabled() { 96 when(mLocationManager.isLocationEnabled()).thenReturn(false); 97 98 // Simulate the UI being clicked. 99 mController.setChecked(true); 100 101 // Verify the TimeManager was not called. 102 verifyZeroInteractions(mTimeManager); 103 } 104 105 @Test setChecked_withFalse_shouldUpdateSetting()106 public void setChecked_withFalse_shouldUpdateSetting() { 107 // Simulate the UI being clicked. 108 mController.setChecked(false); 109 110 // Verify the TimeManager was updated with the UI value. 111 TimeZoneConfiguration expectedConfiguration = new TimeZoneConfiguration.Builder() 112 .setGeoDetectionEnabled(false) 113 .build(); 114 verify(mTimeManager).updateTimeZoneConfiguration(expectedConfiguration); 115 } 116 117 @Test testLocationTimeZoneDetection_supported_shouldBeShown()118 public void testLocationTimeZoneDetection_supported_shouldBeShown() { 119 TimeZoneCapabilities capabilities = 120 createTimeZoneCapabilities(CAPABILITY_POSSESSED); 121 TimeZoneConfiguration configuration = createTimeZoneConfig(/* geoDetectionEnabled= */ true); 122 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = 123 new TimeZoneCapabilitiesAndConfig(capabilities, configuration); 124 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 125 126 assertThat(mController.isAvailable()).isTrue(); 127 } 128 129 @Test testLocationTimeZoneDetection_unsupported_shouldNotBeShown()130 public void testLocationTimeZoneDetection_unsupported_shouldNotBeShown() { 131 TimeZoneCapabilities capabilities = 132 createTimeZoneCapabilities(CAPABILITY_NOT_SUPPORTED); 133 TimeZoneConfiguration configuration = createTimeZoneConfig(/* geoDetectionEnabled= */ true); 134 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = 135 new TimeZoneCapabilitiesAndConfig(capabilities, configuration); 136 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 137 138 assertThat(mController.isAvailable()).isFalse(); 139 } 140 141 /** 142 * Tests that the summary is set in just one of many cases. Exhaustive testing would be brittle. 143 */ 144 @Test testLocationTimeZoneDetection_summary_geoDetectionEnabled()145 public void testLocationTimeZoneDetection_summary_geoDetectionEnabled() { 146 TimeZoneCapabilities capabilities = 147 createTimeZoneCapabilities(CAPABILITY_POSSESSED); 148 TimeZoneConfiguration configuration = createTimeZoneConfig(/* geoDetectionEnabled= */ true); 149 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = 150 new TimeZoneCapabilitiesAndConfig(capabilities, configuration); 151 152 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 153 assertThat(mController.getSummary().toString()).isEmpty(); 154 } 155 156 @Test testLocationTimeZoneDetection_toggleIsOn_whenGeoDetectionEnabledAnsMlsIsOff()157 public void testLocationTimeZoneDetection_toggleIsOn_whenGeoDetectionEnabledAnsMlsIsOff() { 158 TimeZoneCapabilities capabilities = 159 createTimeZoneCapabilities(CAPABILITY_NOT_APPLICABLE); 160 TimeZoneConfiguration configuration = createTimeZoneConfig(/* geoDetectionEnabled= */ true); 161 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = 162 new TimeZoneCapabilitiesAndConfig(capabilities, configuration); 163 164 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 165 when(mLocationManager.isLocationEnabled()).thenReturn(false); 166 167 assertThat(mController.isChecked()).isTrue(); 168 assertThat(mController.getSummary()).isEqualTo( 169 mContext.getString(R.string.location_app_permission_summary_location_off)); 170 } 171 createTimeZoneCapabilities( @apabilities.CapabilityState int geoDetectionCapability)172 private static TimeZoneCapabilities createTimeZoneCapabilities( 173 @Capabilities.CapabilityState int geoDetectionCapability) { 174 UserHandle arbitraryUserHandle = UserHandle.of(123); 175 return new TimeZoneCapabilities.Builder(arbitraryUserHandle) 176 .setConfigureAutoDetectionEnabledCapability(CAPABILITY_POSSESSED) 177 .setConfigureGeoDetectionEnabledCapability(geoDetectionCapability) 178 .setSuggestManualTimeZoneCapability(CAPABILITY_NOT_APPLICABLE) 179 .build(); 180 } 181 createTimeZoneConfig(boolean geoDetectionEnabled)182 private static TimeZoneConfiguration createTimeZoneConfig(boolean geoDetectionEnabled) { 183 return new TimeZoneConfiguration.Builder() 184 .setAutoDetectionEnabled(true) 185 .setGeoDetectionEnabled(geoDetectionEnabled) 186 .build(); 187 } 188 } 189