1 /* 2 * Copyright (C) 2024 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 package com.android.nfc; 17 18 import static com.android.nfc.NfcService.PREF_NFC_ON; 19 20 import static org.mockito.ArgumentMatchers.any; 21 import static org.mockito.ArgumentMatchers.anyBoolean; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.ArgumentMatchers.anyLong; 24 import static org.mockito.ArgumentMatchers.anyString; 25 import static org.mockito.ArgumentMatchers.argThat; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.Mockito.atLeastOnce; 28 import static org.mockito.Mockito.clearInvocations; 29 import static org.mockito.Mockito.doNothing; 30 import static org.mockito.Mockito.mock; 31 import static org.mockito.Mockito.times; 32 import static org.mockito.Mockito.verify; 33 import static org.mockito.Mockito.verifyNoMoreInteractions; 34 import static org.mockito.Mockito.when; 35 36 import android.app.ActivityManager; 37 import android.app.AlarmManager; 38 import android.app.Application; 39 import android.app.KeyguardManager; 40 import android.app.backup.BackupManager; 41 import android.content.BroadcastReceiver; 42 import android.content.ContentResolver; 43 import android.content.Intent; 44 import android.content.SharedPreferences; 45 import android.content.pm.PackageManager; 46 import android.content.res.Resources; 47 import android.nfc.NfcAdapter; 48 import android.nfc.NfcServiceManager; 49 import android.nfc.tech.Ndef; 50 import android.os.AsyncTask; 51 import android.os.Bundle; 52 import android.os.Handler; 53 import android.os.HandlerExecutor; 54 import android.os.PowerManager; 55 import android.os.UserManager; 56 import android.os.test.TestLooper; 57 58 import androidx.test.ext.junit.runners.AndroidJUnit4; 59 60 61 import com.android.dx.mockito.inline.extended.ExtendedMockito; 62 63 import org.junit.After; 64 import org.junit.Assert; 65 import org.junit.Before; 66 import org.junit.Test; 67 import org.junit.runner.RunWith; 68 import org.mockito.ArgumentCaptor; 69 import org.mockito.Captor; 70 import org.mockito.Mock; 71 import org.mockito.MockitoAnnotations; 72 import org.mockito.MockitoSession; 73 import org.mockito.quality.Strictness; 74 75 import java.util.Optional; 76 77 @RunWith(AndroidJUnit4.class) 78 public final class NfcServiceTest { 79 private static final String PKG_NAME = "com.test"; 80 @Mock Application mApplication; 81 @Mock NfcInjector mNfcInjector; 82 @Mock DeviceHost mDeviceHost; 83 @Mock NfcEventLog mNfcEventLog; 84 @Mock NfcDispatcher mNfcDispatcher; 85 @Mock NfcUnlockManager mNfcUnlockManager; 86 @Mock SharedPreferences mPreferences; 87 @Mock SharedPreferences.Editor mPreferencesEditor; 88 @Mock PowerManager mPowerManager; 89 @Mock PackageManager mPackageManager; 90 @Mock ScreenStateHelper mScreenStateHelper; 91 @Mock Resources mResources; 92 @Mock KeyguardManager mKeyguardManager; 93 @Mock UserManager mUserManager; 94 @Mock ActivityManager mActivityManager; 95 @Mock NfcServiceManager.ServiceRegisterer mNfcManagerRegisterer; 96 @Mock NfcDiagnostics mNfcDiagnostics; 97 @Mock DeviceConfigFacade mDeviceConfigFacade; 98 @Mock ContentResolver mContentResolver; 99 @Mock Bundle mUserRestrictions; 100 @Mock BackupManager mBackupManager; 101 @Mock AlarmManager mAlarmManager; 102 @Captor ArgumentCaptor<DeviceHost.DeviceHostListener> mDeviceHostListener; 103 @Captor ArgumentCaptor<BroadcastReceiver> mGlobalReceiver; 104 @Captor ArgumentCaptor<AlarmManager.OnAlarmListener> mAlarmListener; 105 TestLooper mLooper; 106 NfcService mNfcService; 107 private MockitoSession mStaticMockSession; 108 109 @Before setUp()110 public void setUp() { 111 mLooper = new TestLooper(); 112 MockitoAnnotations.initMocks(this); 113 AsyncTask.setDefaultExecutor(new HandlerExecutor(new Handler(mLooper.getLooper()))); 114 115 when(mNfcInjector.getMainLooper()).thenReturn(mLooper.getLooper()); 116 when(mNfcInjector.getNfcEventLog()).thenReturn(mNfcEventLog); 117 when(mNfcInjector.makeDeviceHost(any())).thenReturn(mDeviceHost); 118 when(mNfcInjector.getScreenStateHelper()).thenReturn(mScreenStateHelper); 119 when(mNfcInjector.getNfcDiagnostics()).thenReturn(mNfcDiagnostics); 120 when(mNfcInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade); 121 when(mNfcInjector.getNfcManagerRegisterer()).thenReturn(mNfcManagerRegisterer); 122 when(mNfcInjector.getBackupManager()).thenReturn(mBackupManager); 123 when(mNfcInjector.getNfcDispatcher()).thenReturn(mNfcDispatcher); 124 when(mNfcInjector.getNfcUnlockManager()).thenReturn(mNfcUnlockManager); 125 when(mApplication.getSharedPreferences(anyString(), anyInt())).thenReturn(mPreferences); 126 when(mApplication.getSystemService(PowerManager.class)).thenReturn(mPowerManager); 127 when(mApplication.getSystemService(UserManager.class)).thenReturn(mUserManager); 128 when(mApplication.getSystemService(ActivityManager.class)).thenReturn(mActivityManager); 129 when(mApplication.getSystemService(KeyguardManager.class)).thenReturn(mKeyguardManager); 130 when(mApplication.getSystemService(AlarmManager.class)).thenReturn(mAlarmManager); 131 when(mApplication.getPackageManager()).thenReturn(mPackageManager); 132 when(mApplication.getResources()).thenReturn(mResources); 133 when(mApplication.createContextAsUser(any(), anyInt())).thenReturn(mApplication); 134 when(mApplication.getContentResolver()).thenReturn(mContentResolver); 135 when(mUserManager.getUserRestrictions()).thenReturn(mUserRestrictions); 136 when(mResources.getStringArray(R.array.nfc_allow_list)).thenReturn(new String[0]); 137 when(mPreferences.edit()).thenReturn(mPreferencesEditor); 138 when(mPowerManager.newWakeLock(anyInt(), anyString())) 139 .thenReturn(mock(PowerManager.WakeLock.class)); 140 createNfcService(); 141 } 142 143 @After tearDown()144 public void tearDown() { 145 } 146 createNfcService()147 private void createNfcService() { 148 mNfcService = new NfcService(mApplication, mNfcInjector); 149 mLooper.dispatchAll(); 150 verify(mNfcInjector).makeDeviceHost(mDeviceHostListener.capture()); 151 verify(mApplication).registerReceiverForAllUsers( 152 mGlobalReceiver.capture(), 153 argThat(intent -> intent.hasAction(Intent.ACTION_SCREEN_ON)), any(), any()); 154 clearInvocations(mDeviceHost, mNfcInjector, mApplication); 155 } 156 enableAndVerify()157 private void enableAndVerify() throws Exception { 158 when(mDeviceHost.initialize()).thenReturn(true); 159 when(mPreferences.getBoolean(eq(PREF_NFC_ON), anyBoolean())).thenReturn(true); 160 mNfcService.mNfcAdapter.enable(PKG_NAME); 161 verify(mPreferencesEditor).putBoolean(PREF_NFC_ON, true); 162 mLooper.dispatchAll(); 163 verify(mDeviceHost).initialize(); 164 clearInvocations(mDeviceHost, mPreferencesEditor); 165 } 166 disableAndVerify()167 private void disableAndVerify() throws Exception { 168 when(mDeviceHost.deinitialize()).thenReturn(true); 169 when(mPreferences.getBoolean(eq(PREF_NFC_ON), anyBoolean())).thenReturn(false); 170 mNfcService.mNfcAdapter.disable(true, PKG_NAME); 171 verify(mPreferencesEditor).putBoolean(PREF_NFC_ON, false); 172 mLooper.dispatchAll(); 173 verify(mDeviceHost).deinitialize(); 174 verify(mNfcDispatcher).resetForegroundDispatch(); 175 clearInvocations(mDeviceHost, mPreferencesEditor, mNfcDispatcher); 176 } 177 178 179 @Test testEnable()180 public void testEnable() throws Exception { 181 enableAndVerify(); 182 } 183 184 @Test testDisable()185 public void testDisable() throws Exception { 186 enableAndVerify(); 187 disableAndVerify(); 188 } 189 190 @Test testBootupWithNfcOn()191 public void testBootupWithNfcOn() throws Exception { 192 when(mPreferences.getBoolean(eq(PREF_NFC_ON), anyBoolean())).thenReturn(true); 193 mNfcService = new NfcService(mApplication, mNfcInjector); 194 mLooper.dispatchAll(); 195 verify(mNfcInjector).makeDeviceHost(mDeviceHostListener.capture()); 196 verify(mApplication).registerReceiverForAllUsers( 197 mGlobalReceiver.capture(), 198 argThat(intent -> intent.hasAction(Intent.ACTION_SCREEN_ON)), any(), any()); 199 verify(mDeviceHost).initialize(); 200 } 201 202 @Test testBootupWithNfcOn_WhenOemExtensionEnabled()203 public void testBootupWithNfcOn_WhenOemExtensionEnabled() throws Exception { 204 when(mResources.getBoolean(R.bool.enable_oem_extension)).thenReturn(true); 205 createNfcService(); 206 207 verifyNoMoreInteractions(mDeviceHost); 208 } 209 210 @Test testBootupWithNfcOn_WhenOemExtensionEnabled_ThenAllowBoot()211 public void testBootupWithNfcOn_WhenOemExtensionEnabled_ThenAllowBoot() throws Exception { 212 when(mPreferences.getBoolean(eq(PREF_NFC_ON), anyBoolean())).thenReturn(true); 213 when(mResources.getBoolean(R.bool.enable_oem_extension)).thenReturn(true); 214 createNfcService(); 215 216 mNfcService.mNfcAdapter.allowBoot(); 217 mLooper.dispatchAll(); 218 verify(mDeviceHost).initialize(); 219 } 220 221 @Test testBootupWithNfcOn_WhenOemExtensionEnabled_ThenTimeout()222 public void testBootupWithNfcOn_WhenOemExtensionEnabled_ThenTimeout() throws Exception { 223 when(mPreferences.getBoolean(eq(PREF_NFC_ON), anyBoolean())).thenReturn(true); 224 when(mResources.getBoolean(R.bool.enable_oem_extension)).thenReturn(true); 225 createNfcService(); 226 verify(mAlarmManager).setExact( 227 anyInt(), anyLong(), anyString(), mAlarmListener.capture(), any()); 228 229 mAlarmListener.getValue().onAlarm(); 230 mLooper.dispatchAll(); 231 verify(mDeviceHost).initialize(); 232 } 233 234 @Test testSetObserveMode_nfcDisabled()235 public void testSetObserveMode_nfcDisabled() throws Exception { 236 mNfcService.mNfcAdapter.disable(true, PKG_NAME); 237 238 Assert.assertFalse(mNfcService.mNfcAdapter.setObserveMode(true, null)); 239 } 240 241 @Test testIsObserveModeEnabled_nfcDisabled()242 public void testIsObserveModeEnabled_nfcDisabled() throws Exception { 243 mNfcService.mNfcAdapter.disable(true, PKG_NAME); 244 245 Assert.assertFalse(mNfcService.mNfcAdapter.isObserveModeEnabled()); 246 } 247 248 @Test testIsObserveModeSupported_nfcDisabled()249 public void testIsObserveModeSupported_nfcDisabled() throws Exception { 250 mNfcService.mNfcAdapter.disable(true, PKG_NAME); 251 252 Assert.assertFalse(mNfcService.mNfcAdapter.isObserveModeSupported()); 253 } 254 255 @Test testEnableNfc_changeStateRestricted()256 public void testEnableNfc_changeStateRestricted() throws Exception { 257 when(mUserRestrictions.getBoolean( 258 UserManager.DISALLOW_CHANGE_NEAR_FIELD_COMMUNICATION_RADIO)).thenReturn(true); 259 mNfcService.mNfcAdapter.enable(PKG_NAME); 260 assert(mNfcService.mState == NfcAdapter.STATE_OFF); 261 } 262 263 @Test testDisableNfc_changeStateRestricted()264 public void testDisableNfc_changeStateRestricted() throws Exception { 265 enableAndVerify(); 266 when(mUserRestrictions.getBoolean( 267 UserManager.DISALLOW_CHANGE_NEAR_FIELD_COMMUNICATION_RADIO)).thenReturn(true); 268 mNfcService.mNfcAdapter.disable(true, PKG_NAME); 269 assert(mNfcService.mState == NfcAdapter.STATE_ON); 270 } 271 } 272