1 /* 2 * Copyright (C) 2018 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.nfc; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.spy; 22 import static org.mockito.Mockito.times; 23 import static org.mockito.Mockito.verify; 24 import static org.mockito.Mockito.when; 25 26 import android.content.Context; 27 import android.content.Intent; 28 import android.nfc.NfcAdapter; 29 import android.nfc.NfcManager; 30 import android.os.UserManager; 31 import android.provider.Settings; 32 33 import androidx.preference.PreferenceScreen; 34 35 import com.android.settings.nfc.NfcPreferenceController.NfcSliceWorker; 36 import com.android.settings.nfc.NfcPreferenceController.NfcSliceWorker.NfcUpdateReceiver; 37 import com.android.settings.testutils.shadow.ShadowNfcAdapter; 38 import com.android.settingslib.widget.MainSwitchPreference; 39 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.mockito.Mock; 44 import org.mockito.MockitoAnnotations; 45 import org.robolectric.RobolectricTestRunner; 46 import org.robolectric.RuntimeEnvironment; 47 import org.robolectric.annotation.Config; 48 import org.robolectric.shadow.api.Shadow; 49 import org.robolectric.util.ReflectionHelpers; 50 51 import java.util.ArrayList; 52 import java.util.List; 53 54 @RunWith(RobolectricTestRunner.class) 55 @Config(shadows = ShadowNfcAdapter.class) 56 public class NfcPreferenceControllerTest { 57 58 @Mock 59 NfcManager mManager; 60 @Mock 61 private UserManager mUserManager; 62 @Mock 63 private PreferenceScreen mScreen; 64 65 private Context mContext; 66 private MainSwitchPreference mNfcPreference; 67 private NfcPreferenceController mNfcController; 68 private ShadowNfcAdapter mShadowNfcAdapter; 69 private NfcAdapter mNfcAdapter; 70 71 @Before setUp()72 public void setUp() { 73 MockitoAnnotations.initMocks(this); 74 mContext = spy(RuntimeEnvironment.application); 75 mShadowNfcAdapter = Shadow.extract(NfcAdapter.getDefaultAdapter(mContext)); 76 mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext); 77 78 when(mContext.getApplicationContext()).thenReturn(mContext); 79 when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); 80 when(mContext.getSystemService(Context.NFC_SERVICE)).thenReturn(mManager); 81 82 mNfcController = new NfcPreferenceController(mContext, 83 NfcPreferenceController.KEY_TOGGLE_NFC); 84 mNfcPreference = new MainSwitchPreference(RuntimeEnvironment.application); 85 86 when(mScreen.findPreference(mNfcController.getPreferenceKey())).thenReturn(mNfcPreference); 87 } 88 89 @Test getAvailabilityStatus_hasNfc_shouldReturnAvailable()90 public void getAvailabilityStatus_hasNfc_shouldReturnAvailable() { 91 mShadowNfcAdapter.setEnabled(true); 92 assertThat(mNfcController.getAvailabilityStatus()) 93 .isEqualTo(NfcPreferenceController.AVAILABLE); 94 } 95 96 @Test getAvailabilityStatus_noNfcAdapter_shouldReturnDisabledUnsupported()97 public void getAvailabilityStatus_noNfcAdapter_shouldReturnDisabledUnsupported() { 98 ReflectionHelpers.setField(mNfcController, "mNfcAdapter", null); 99 assertThat(mNfcController.getAvailabilityStatus()) 100 .isEqualTo(NfcPreferenceController.UNSUPPORTED_ON_DEVICE); 101 } 102 103 @Test isNfcEnable_nfcStateNotTurning_shouldReturnTrue()104 public void isNfcEnable_nfcStateNotTurning_shouldReturnTrue() { 105 mNfcController.displayPreference(mScreen); 106 mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_ON); 107 mNfcController.onResume(); 108 assertThat(mNfcPreference.isEnabled()).isTrue(); 109 110 mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_OFF); 111 mNfcController.onResume(); 112 assertThat(mNfcPreference.isEnabled()).isTrue(); 113 } 114 115 @Test isNfcEnable_nfcStateTurning_shouldReturnFalse()116 public void isNfcEnable_nfcStateTurning_shouldReturnFalse() { 117 mNfcController.displayPreference(mScreen); 118 mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_TURNING_ON); 119 mNfcController.onResume(); 120 assertThat(mNfcPreference.isEnabled()).isFalse(); 121 122 mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_TURNING_OFF); 123 mNfcController.onResume(); 124 assertThat(mNfcPreference.isEnabled()).isFalse(); 125 } 126 127 @Test isNfcChecked_nfcStateOn_shouldReturnTrue()128 public void isNfcChecked_nfcStateOn_shouldReturnTrue() { 129 mNfcController.displayPreference(mScreen); 130 mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_ON); 131 mNfcController.onResume(); 132 assertThat(mNfcPreference.isChecked()).isTrue(); 133 134 mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_TURNING_ON); 135 mNfcController.onResume(); 136 assertThat(mNfcPreference.isChecked()).isTrue(); 137 } 138 139 @Test isNfcChecked_nfcStateOff_shouldReturnFalse()140 public void isNfcChecked_nfcStateOff_shouldReturnFalse() { 141 mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_OFF); 142 mNfcController.onResume(); 143 assertThat(mNfcPreference.isChecked()).isFalse(); 144 145 mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_TURNING_OFF); 146 mNfcController.onResume(); 147 assertThat(mNfcPreference.isChecked()).isFalse(); 148 } 149 150 @Test updateNonIndexableKeys_available_shouldNotUpdate()151 public void updateNonIndexableKeys_available_shouldNotUpdate() { 152 mShadowNfcAdapter.setEnabled(true); 153 final List<String> keys = new ArrayList<>(); 154 155 mNfcController.updateNonIndexableKeys(keys); 156 157 assertThat(keys).isEmpty(); 158 } 159 160 @Test updateNonIndexableKeys_notAvailable_shouldUpdate()161 public void updateNonIndexableKeys_notAvailable_shouldUpdate() { 162 ReflectionHelpers.setField(mNfcController, "mNfcAdapter", null); 163 final List<String> keys = new ArrayList<>(); 164 165 mNfcController.updateNonIndexableKeys(keys); 166 167 assertThat(keys).hasSize(1); 168 } 169 170 @Test setChecked_True_nfcShouldEnable()171 public void setChecked_True_nfcShouldEnable() { 172 mNfcController.setChecked(true); 173 mNfcController.onResume(); 174 175 assertThat(mNfcAdapter.isEnabled()).isTrue(); 176 } 177 178 @Test setChecked_False_nfcShouldDisable()179 public void setChecked_False_nfcShouldDisable() { 180 mNfcController.setChecked(false); 181 mNfcController.onResume(); 182 183 assertThat(mNfcAdapter.isEnabled()).isFalse(); 184 } 185 186 @Test hasAsyncUpdate_shouldReturnTrue()187 public void hasAsyncUpdate_shouldReturnTrue() { 188 assertThat(mNfcController.hasAsyncUpdate()).isTrue(); 189 } 190 191 @Test isToggleableInAirplaneMode_containNfc_shouldReturnTrue()192 public void isToggleableInAirplaneMode_containNfc_shouldReturnTrue() { 193 Settings.Global.putString(mContext.getContentResolver(), 194 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, 195 Settings.Global.RADIO_NFC); 196 Settings.Global.putInt(mContext.getContentResolver(), 197 Settings.Global.AIRPLANE_MODE_ON, 1); 198 199 assertThat(NfcPreferenceController.isToggleableInAirplaneMode(mContext)).isTrue(); 200 } 201 202 @Test isToggleableInAirplaneMode_withoutNfc_shouldReturnFalse()203 public void isToggleableInAirplaneMode_withoutNfc_shouldReturnFalse() { 204 Settings.Global.putString(mContext.getContentResolver(), 205 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, 206 "null"); 207 Settings.Global.putInt(mContext.getContentResolver(), 208 Settings.Global.AIRPLANE_MODE_ON, 1); 209 210 assertThat(NfcPreferenceController.isToggleableInAirplaneMode(mContext)).isFalse(); 211 } 212 213 @Test shouldTurnOffNFCInAirplaneMode_airplaneModeRadiosContainsNfc_shouldReturnTrue()214 public void shouldTurnOffNFCInAirplaneMode_airplaneModeRadiosContainsNfc_shouldReturnTrue() { 215 Settings.Global.putString(mContext.getContentResolver(), 216 Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC); 217 218 assertThat(NfcPreferenceController.shouldTurnOffNFCInAirplaneMode(mContext)).isTrue(); 219 } 220 221 @Test shouldTurnOffNFCInAirplaneMode_airplaneModeRadiosWithoutNfc_shouldReturnFalse()222 public void shouldTurnOffNFCInAirplaneMode_airplaneModeRadiosWithoutNfc_shouldReturnFalse() { 223 Settings.Global.putString(mContext.getContentResolver(), 224 Settings.Global.AIRPLANE_MODE_RADIOS, ""); 225 226 assertThat(NfcPreferenceController.shouldTurnOffNFCInAirplaneMode(mContext)).isFalse(); 227 } 228 229 @Test ncfSliceWorker_nfcBroadcast_noExtra_sliceDoesntUpdate()230 public void ncfSliceWorker_nfcBroadcast_noExtra_sliceDoesntUpdate() { 231 final NfcSliceWorker worker = spy( 232 new NfcSliceWorker(mContext, mNfcController.getSliceUri())); 233 final NfcUpdateReceiver receiver = worker.new NfcUpdateReceiver(worker); 234 final Intent triggerIntent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 235 236 receiver.onReceive(mContext, triggerIntent); 237 238 verify(worker, times(0)).updateSlice(); 239 } 240 241 @Test ncfSliceWorker_nfcBroadcast_turningOn_sliceDoesntUpdate()242 public void ncfSliceWorker_nfcBroadcast_turningOn_sliceDoesntUpdate() { 243 final NfcSliceWorker worker = spy( 244 new NfcSliceWorker(mContext, mNfcController.getSliceUri())); 245 final NfcUpdateReceiver receiver = worker.new NfcUpdateReceiver(worker); 246 final Intent triggerIntent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 247 triggerIntent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_TURNING_ON); 248 249 receiver.onReceive(mContext, triggerIntent); 250 251 verify(worker, times(0)).updateSlice(); 252 } 253 254 @Test ncfSliceWorker_nfcBroadcast_turningOff_sliceDoesntUpdate()255 public void ncfSliceWorker_nfcBroadcast_turningOff_sliceDoesntUpdate() { 256 final NfcSliceWorker worker = spy( 257 new NfcSliceWorker(mContext, mNfcController.getSliceUri())); 258 final NfcUpdateReceiver receiver = worker.new NfcUpdateReceiver(worker); 259 final Intent triggerIntent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 260 triggerIntent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_TURNING_OFF); 261 262 receiver.onReceive(mContext, triggerIntent); 263 264 verify(worker, times(0)).updateSlice(); 265 } 266 267 @Test ncfSliceWorker_nfcBroadcast_nfcOn_sliceUpdates()268 public void ncfSliceWorker_nfcBroadcast_nfcOn_sliceUpdates() { 269 final NfcSliceWorker worker = spy( 270 new NfcSliceWorker(mContext, mNfcController.getSliceUri())); 271 final NfcUpdateReceiver receiver = worker.new NfcUpdateReceiver(worker); 272 final Intent triggerIntent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 273 triggerIntent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_ON); 274 275 receiver.onReceive(mContext, triggerIntent); 276 277 verify(worker).updateSlice(); 278 } 279 280 @Test ncfSliceWorker_nfcBroadcast_nfcOff_sliceUpdates()281 public void ncfSliceWorker_nfcBroadcast_nfcOff_sliceUpdates() { 282 final NfcSliceWorker worker = spy( 283 new NfcSliceWorker(mContext, mNfcController.getSliceUri())); 284 final NfcUpdateReceiver receiver = worker.new NfcUpdateReceiver(worker); 285 final Intent triggerIntent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 286 triggerIntent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_OFF); 287 288 receiver.onReceive(mContext, triggerIntent); 289 290 verify(worker).updateSlice(); 291 } 292 293 @Test isPublicSlice_returnsTrue()294 public void isPublicSlice_returnsTrue() { 295 assertThat(mNfcController.isPublicSlice()).isTrue(); 296 } 297 } 298