1 /* 2 * Copyright (C) 2022 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_RUNNING; 20 import static android.app.time.DetectorStatusTypes.DETECTOR_STATUS_RUNNING; 21 import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_IS_CERTAIN; 22 import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_IS_UNCERTAIN; 23 import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS; 24 import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS; 25 import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_OK; 26 27 import static com.google.common.truth.Truth.assertThat; 28 29 import static org.mockito.Mockito.spy; 30 import static org.mockito.Mockito.when; 31 32 import android.app.time.Capabilities; 33 import android.app.time.Capabilities.CapabilityState; 34 import android.app.time.LocationTimeZoneAlgorithmStatus; 35 import android.app.time.LocationTimeZoneAlgorithmStatus.ProviderStatus; 36 import android.app.time.TelephonyTimeZoneAlgorithmStatus; 37 import android.app.time.TimeManager; 38 import android.app.time.TimeZoneCapabilities; 39 import android.app.time.TimeZoneCapabilitiesAndConfig; 40 import android.app.time.TimeZoneConfiguration; 41 import android.app.time.TimeZoneDetectorStatus; 42 import android.content.Context; 43 import android.os.UserHandle; 44 import android.service.timezone.TimeZoneProviderStatus; 45 import android.service.timezone.TimeZoneProviderStatus.DependencyStatus; 46 47 import androidx.annotation.Nullable; 48 49 import com.android.settings.R; 50 import com.android.settings.core.BasePreferenceController; 51 52 import org.junit.Before; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.mockito.Mock; 56 import org.mockito.MockitoAnnotations; 57 import org.robolectric.RobolectricTestRunner; 58 import org.robolectric.RuntimeEnvironment; 59 60 @RunWith(RobolectricTestRunner.class) 61 public class LocationProviderStatusPreferenceControllerTest { 62 63 private Context mContext; 64 @Mock 65 private TimeManager mTimeManager; 66 67 @Before setUp()68 public void setUp() { 69 MockitoAnnotations.initMocks(this); 70 mContext = spy(RuntimeEnvironment.application); 71 72 when(mContext.getSystemService(TimeManager.class)).thenReturn(mTimeManager); 73 when(mContext.getString( 74 R.string.location_time_zone_detection_status_summary_blocked_by_settings)) 75 .thenReturn("BBS"); 76 when(mContext.getString( 77 R.string.location_time_zone_detection_status_summary_degraded_by_settings)) 78 .thenReturn("DBS"); 79 } 80 81 @Test testProviderStatus_primaryCertain()82 public void testProviderStatus_primaryCertain() { 83 LocationProviderStatusPreferenceController controller = 84 new LocationProviderStatusPreferenceController(mContext, "LPSPC"); 85 86 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig(false, 87 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_OK, 88 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_OK); 89 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 90 91 assertThat(controller.getAvailabilityStatus()).isEqualTo( 92 BasePreferenceController.CONDITIONALLY_UNAVAILABLE); 93 94 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 95 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_OK, 96 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_OK); 97 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 98 99 assertThat(controller.getAvailabilityStatus()).isEqualTo( 100 BasePreferenceController.CONDITIONALLY_UNAVAILABLE); 101 102 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 103 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_OK, 104 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS); 105 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 106 107 assertThat(controller.getAvailabilityStatus()).isEqualTo( 108 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 109 110 // Test whether reportable statuses that can still result in the LTZP being "certain" are 111 // reported. 112 113 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 114 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS, 115 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_OK); 116 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 117 118 assertThat(controller.getAvailabilityStatus()).isEqualTo( 119 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 120 121 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 122 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS, 123 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS); 124 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 125 126 assertThat(controller.getAvailabilityStatus()).isEqualTo( 127 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 128 129 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 130 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS, 131 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS); 132 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 133 134 assertThat(controller.getAvailabilityStatus()).isEqualTo( 135 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 136 137 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 138 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_OK, 139 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS); 140 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 141 142 assertThat(controller.getAvailabilityStatus()).isEqualTo( 143 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 144 } 145 146 @Test testProviderStatus_primaryUncertain()147 public void testProviderStatus_primaryUncertain() { 148 LocationProviderStatusPreferenceController controller = 149 new LocationProviderStatusPreferenceController(mContext, "LPSPC"); 150 151 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig(false, 152 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_OK, 153 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_OK); 154 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 155 156 assertThat(controller.getAvailabilityStatus()).isEqualTo( 157 BasePreferenceController.CONDITIONALLY_UNAVAILABLE); 158 159 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 160 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_OK, 161 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS); 162 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 163 164 assertThat(controller.getAvailabilityStatus()).isEqualTo( 165 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 166 167 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 168 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS, 169 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_OK); 170 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 171 172 assertThat(controller.getAvailabilityStatus()).isEqualTo( 173 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 174 175 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 176 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS, 177 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_OK); 178 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 179 180 assertThat(controller.getAvailabilityStatus()).isEqualTo( 181 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 182 183 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 184 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS, 185 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS); 186 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 187 188 assertThat(controller.getAvailabilityStatus()).isEqualTo( 189 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 190 } 191 192 @Test testProviderStatus_nullProviderStatuses()193 public void testProviderStatus_nullProviderStatuses() { 194 LocationProviderStatusPreferenceController controller = 195 new LocationProviderStatusPreferenceController(mContext, "LPSPC"); 196 197 TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig(false, 198 PROVIDER_STATUS_IS_CERTAIN, null, 199 PROVIDER_STATUS_IS_CERTAIN, null); 200 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 201 202 assertThat(controller.getAvailabilityStatus()).isEqualTo( 203 BasePreferenceController.CONDITIONALLY_UNAVAILABLE); 204 205 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 206 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_OK, 207 PROVIDER_STATUS_IS_UNCERTAIN, null); 208 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 209 210 assertThat(controller.getAvailabilityStatus()).isEqualTo( 211 BasePreferenceController.CONDITIONALLY_UNAVAILABLE); 212 213 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 214 PROVIDER_STATUS_IS_CERTAIN, DEPENDENCY_STATUS_OK, 215 PROVIDER_STATUS_IS_CERTAIN, null); 216 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 217 218 assertThat(controller.getAvailabilityStatus()).isEqualTo( 219 BasePreferenceController.CONDITIONALLY_UNAVAILABLE); 220 221 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 222 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS, 223 PROVIDER_STATUS_IS_CERTAIN, null); 224 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 225 226 assertThat(controller.getAvailabilityStatus()).isEqualTo( 227 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 228 229 capabilitiesAndConfig = createCapabilitiesAndConfig(false, 230 PROVIDER_STATUS_IS_CERTAIN, null, 231 PROVIDER_STATUS_IS_UNCERTAIN, DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS); 232 when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); 233 234 assertThat(controller.getAvailabilityStatus()).isEqualTo( 235 BasePreferenceController.AVAILABLE_UNSEARCHABLE); 236 } 237 createCapabilitiesAndConfig( boolean userCanConfigureGeoDetection, @ProviderStatus int primaryProviderStatus, @Nullable @DependencyStatus Integer primaryProviderLocationStatus, @ProviderStatus int secondaryProviderStatus, @Nullable @DependencyStatus Integer secondaryProviderLocationStatus)238 private static TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig( 239 boolean userCanConfigureGeoDetection, 240 @ProviderStatus int primaryProviderStatus, 241 @Nullable @DependencyStatus Integer primaryProviderLocationStatus, 242 @ProviderStatus int secondaryProviderStatus, 243 @Nullable @DependencyStatus Integer secondaryProviderLocationStatus) { 244 TelephonyTimeZoneAlgorithmStatus telephonyTimeZoneAlgorithmStatus = 245 new TelephonyTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING); 246 247 LocationTimeZoneAlgorithmStatus locationTimeZoneAlgorithmStatus = 248 new LocationTimeZoneAlgorithmStatus(DETECTION_ALGORITHM_STATUS_RUNNING, 249 primaryProviderStatus, 250 createTimeZoneProviderStatusOrNull(primaryProviderLocationStatus), 251 secondaryProviderStatus, 252 createTimeZoneProviderStatusOrNull(secondaryProviderLocationStatus)); 253 254 TimeZoneDetectorStatus status = new TimeZoneDetectorStatus(DETECTOR_STATUS_RUNNING, 255 telephonyTimeZoneAlgorithmStatus, locationTimeZoneAlgorithmStatus); 256 257 @CapabilityState int configureGeoDetectionEnabledCapability = userCanConfigureGeoDetection 258 ? Capabilities.CAPABILITY_POSSESSED : Capabilities.CAPABILITY_NOT_SUPPORTED; 259 TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder(UserHandle.SYSTEM) 260 .setConfigureAutoDetectionEnabledCapability(Capabilities.CAPABILITY_POSSESSED) 261 .setUseLocationEnabled(true) 262 .setConfigureGeoDetectionEnabledCapability(configureGeoDetectionEnabledCapability) 263 .setSetManualTimeZoneCapability(Capabilities.CAPABILITY_POSSESSED) 264 .build(); 265 266 return new TimeZoneCapabilitiesAndConfig(status, capabilities, 267 new TimeZoneConfiguration.Builder().build()); 268 } 269 createTimeZoneProviderStatusOrNull( @ullable @ependencyStatus Integer locationDependencyStatusOrNull)270 private static TimeZoneProviderStatus createTimeZoneProviderStatusOrNull( 271 @Nullable @DependencyStatus Integer locationDependencyStatusOrNull) { 272 if (locationDependencyStatusOrNull == null) { 273 return null; 274 } 275 return new TimeZoneProviderStatus.Builder() 276 .setLocationDetectionDependencyStatus(locationDependencyStatusOrNull) 277 .build(); 278 } 279 } 280