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