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