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