1 /*
2  * Copyright (C) 2021 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.uwb;
18 
19 import static android.uwb.UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_POLICY;
20 import static android.uwb.UwbManager.AdapterStateCallback.STATE_CHANGED_REASON_SYSTEM_REGULATION;
21 import static android.uwb.UwbManager.AdapterStateCallback.STATE_DISABLED;
22 import static android.uwb.UwbManager.AdapterStateCallback.STATE_ENABLED_ACTIVE;
23 import static android.uwb.UwbManager.AdapterStateCallback.STATE_ENABLED_INACTIVE;
24 
25 import static com.google.common.truth.Truth.assertThat;
26 
27 import static org.mockito.Mockito.any;
28 import static org.mockito.Mockito.anyString;
29 import static org.mockito.Mockito.clearInvocations;
30 import static org.mockito.Mockito.doReturn;
31 import static org.mockito.Mockito.mock;
32 import static org.mockito.Mockito.never;
33 import static org.mockito.Mockito.times;
34 import static org.mockito.Mockito.verify;
35 import static org.mockito.Mockito.when;
36 
37 import android.content.BroadcastReceiver;
38 import android.content.Context;
39 import android.content.Intent;
40 import android.content.pm.PackageManager;
41 import android.content.res.Resources;
42 import android.os.test.TestLooper;
43 import android.uwb.UwbManager;
44 
45 import androidx.preference.Preference;
46 import androidx.preference.PreferenceScreen;
47 
48 import com.android.settings.R;
49 import com.android.settings.core.BasePreferenceController;
50 
51 import org.junit.Before;
52 import org.junit.Rule;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 import org.mockito.ArgumentCaptor;
56 import org.mockito.Mock;
57 import org.mockito.junit.MockitoJUnit;
58 import org.mockito.junit.MockitoRule;
59 import org.robolectric.RobolectricTestRunner;
60 import org.robolectric.annotation.LooperMode;
61 
62 /** Unit tests for UWB preference toggle. */
63 @RunWith(RobolectricTestRunner.class)
64 @LooperMode(LooperMode.Mode.INSTRUMENTATION_TEST)
65 public class UwbPreferenceControllerTest {
66     private static final String TEST_SUMMARY = "uwb";
67     private static final String TEST_AIRPLANE_SUMMARY = "apm_uwb";
68     private static final String TEST_NO_UWB_REGULATORY_SUMMARY = "regulatory_uwb";
69     @Rule
70     public MockitoRule rule = MockitoJUnit.rule();
71 
72     @Mock
73     private Context mContext;
74     @Mock
75     private PackageManager mPackageManager;
76     private UwbPreferenceController mController;
77     private ArgumentCaptor<UwbManager.AdapterStateCallback> mAdapterStateCallbackArgumentCaptor =
78             ArgumentCaptor.forClass(UwbManager.AdapterStateCallback.class);
79     private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverArgumentCaptor =
80             ArgumentCaptor.forClass(BroadcastReceiver.class);
81     private TestLooper mTestLooper;
82     @Mock
83     private UwbManager mUwbManager;
84     @Mock
85     private UwbUtils mUwbUtils;
86     @Mock
87     private Preference mPreference;
88     @Mock
89     private PreferenceScreen mPreferenceScreen;
90     @Mock
91     private Resources mResources;
92 
93     @Before
setUp()94     public void setUp() throws Exception {
95         mTestLooper = new TestLooper();
96         doReturn(mPackageManager).when(mContext).getPackageManager();
97         doReturn(true).when(mPackageManager)
98                 .hasSystemFeature(PackageManager.FEATURE_UWB);
99         when(mResources.getString(R.string.uwb_settings_summary))
100                 .thenReturn(TEST_SUMMARY);
101         when(mResources.getString(R.string.uwb_settings_summary_airplane_mode))
102                 .thenReturn(TEST_AIRPLANE_SUMMARY);
103         when(mResources.getString(R.string.uwb_settings_summary_no_uwb_regulatory))
104                 .thenReturn(TEST_NO_UWB_REGULATORY_SUMMARY);
105         when(mContext.getMainLooper()).thenReturn(mTestLooper.getLooper());
106         when(mContext.getSystemService(UwbManager.class)).thenReturn(mUwbManager);
107         when(mContext.getResources()).thenReturn(mResources);
108         when(mUwbUtils.isAirplaneModeOn(any())).thenReturn(false);
109         doReturn(STATE_ENABLED_ACTIVE).when(mUwbManager).getAdapterState();
110         mController = new UwbPreferenceController(mContext, "uwb_settings", mUwbUtils);
111         when(mPreferenceScreen.findPreference(anyString())).thenReturn(mPreference);
112         mController.displayPreference(mPreferenceScreen);
113     }
114 
startControllerAndCaptureCallbacks()115     private void startControllerAndCaptureCallbacks() {
116         mController.onStart();
117         verify(mContext).registerReceiver(
118                 mBroadcastReceiverArgumentCaptor.capture(), any(), any(), any());
119         verify(mUwbManager).registerAdapterStateCallback(
120                 any(), mAdapterStateCallbackArgumentCaptor.capture());
121     }
122 
123     @Test
getAvailabilityStatus_uwbDisabled_shouldReturnDisabled()124     public void getAvailabilityStatus_uwbDisabled_shouldReturnDisabled() throws Exception {
125         when(mUwbUtils.isAirplaneModeOn(any())).thenReturn(true);
126         startControllerAndCaptureCallbacks();
127         assertThat(mController.getAvailabilityStatus())
128                 .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
129     }
130 
131     @Test
getAvailabilityStatus_uwbShown_shouldReturnAvailable()132     public void getAvailabilityStatus_uwbShown_shouldReturnAvailable() throws Exception {
133         when(mUwbUtils.isAirplaneModeOn(any())).thenReturn(false);
134         startControllerAndCaptureCallbacks();
135         assertThat(mController.getAvailabilityStatus())
136                 .isEqualTo(BasePreferenceController.AVAILABLE);
137     }
138 
139     @Test
getAvailabilityStatus_uwbNotShown_shouldReturnUnsupported()140     public void getAvailabilityStatus_uwbNotShown_shouldReturnUnsupported() {
141         doReturn(false).when(mPackageManager)
142                 .hasSystemFeature(PackageManager.FEATURE_UWB);
143 
144         mController.onStart();
145         verify(mContext, never()).registerReceiver(any(), any(), any(), any());
146         verify(mUwbManager, never()).registerAdapterStateCallback(any(), any());
147         assertThat(mController.getAvailabilityStatus())
148                 .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
149     }
150 
151     @Test
isChecked_uwbEnabled_shouldReturnTrue()152     public void isChecked_uwbEnabled_shouldReturnTrue() {
153         doReturn(STATE_ENABLED_ACTIVE).when(mUwbManager).getAdapterState();
154 
155         startControllerAndCaptureCallbacks();
156         assertThat(mController.isChecked()).isTrue();
157     }
158 
159     @Test
isChecked_uwbDisabled_shouldReturnFalse()160     public void isChecked_uwbDisabled_shouldReturnFalse() {
161         doReturn(STATE_DISABLED).when(mUwbManager).getAdapterState();
162 
163         startControllerAndCaptureCallbacks();
164         assertThat(mController.isChecked()).isFalse();
165     }
166 
167     @Test
setChecked_uwbDisabled_shouldEnableUwb()168     public void setChecked_uwbDisabled_shouldEnableUwb() {
169         clearInvocations(mUwbManager);
170 
171         startControllerAndCaptureCallbacks();
172         mController.setChecked(true);
173 
174         verify(mUwbManager).setUwbEnabled(true);
175         verify(mUwbManager, never()).setUwbEnabled(false);
176     }
177 
178     @Test
setChecked_uwbEnabled_shouldDisableUwb()179     public void setChecked_uwbEnabled_shouldDisableUwb() {
180         clearInvocations(mUwbManager);
181 
182         startControllerAndCaptureCallbacks();
183         mController.setChecked(false);
184 
185         verify(mUwbManager).setUwbEnabled(false);
186         verify(mUwbManager, never()).setUwbEnabled(true);
187     }
188 
189     @Test
updateStateAndSummary_uwbDisabledAndEnabled()190     public void updateStateAndSummary_uwbDisabledAndEnabled() {
191         startControllerAndCaptureCallbacks();
192         clearInvocations(mUwbManager, mPreference);
193 
194         mAdapterStateCallbackArgumentCaptor.getValue().onStateChanged(
195                 STATE_DISABLED, STATE_CHANGED_REASON_SYSTEM_POLICY);
196 
197         verify(mPreference).setEnabled(true);
198         assertThat(mController.isChecked()).isFalse();
199         verify(mPreference, times(2)).setSummary(TEST_SUMMARY);
200 
201         mAdapterStateCallbackArgumentCaptor.getValue().onStateChanged(
202                 STATE_ENABLED_INACTIVE, STATE_CHANGED_REASON_SYSTEM_POLICY);
203 
204         verify(mPreference, times(2)).setEnabled(true);
205         assertThat(mController.isChecked()).isTrue();
206         verify(mPreference, times(4)).setSummary(TEST_SUMMARY);
207     }
208 
209     @Test
updateStateAndSummary_apmEnabledAndDisabled()210     public void updateStateAndSummary_apmEnabledAndDisabled() {
211         startControllerAndCaptureCallbacks();
212         clearInvocations(mUwbManager, mPreference);
213 
214         when(mUwbUtils.isAirplaneModeOn(any())).thenReturn(true);
215         mBroadcastReceiverArgumentCaptor.getValue().onReceive(
216                 mock(Context.class), mock(Intent.class));
217 
218         verify(mPreference).setEnabled(false);
219         verify(mPreference, times(2)).setSummary(TEST_AIRPLANE_SUMMARY);
220 
221         when(mUwbUtils.isAirplaneModeOn(any())).thenReturn(false);
222         mBroadcastReceiverArgumentCaptor.getValue().onReceive(
223                 mock(Context.class), mock(Intent.class));
224 
225         verify(mPreference).setEnabled(true);
226         verify(mPreference, times(2)).setSummary(TEST_SUMMARY);
227     }
228 
229     @Test
updateStateAndSummary_uwbDisabledDueToRegulatory()230     public void updateStateAndSummary_uwbDisabledDueToRegulatory() {
231         startControllerAndCaptureCallbacks();
232         clearInvocations(mUwbManager, mPreference);
233 
234         mAdapterStateCallbackArgumentCaptor.getValue().onStateChanged(
235                 STATE_DISABLED, STATE_CHANGED_REASON_SYSTEM_REGULATION);
236 
237         assertThat(mController.getAvailabilityStatus())
238                 .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
239         verify(mPreference, times(2)).setSummary(TEST_NO_UWB_REGULATORY_SUMMARY);
240     }
241 }
242 
243