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 17 package com.android.nfc; 18 19 20 import static org.mockito.ArgumentMatchers.any; 21 import static org.mockito.Mockito.mock; 22 import static org.mockito.Mockito.times; 23 import static org.mockito.Mockito.when; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.annotation.RequiresPermission; 28 import android.app.ActivityManager; 29 import android.content.BroadcastReceiver; 30 import android.content.ComponentName; 31 import android.content.ContentResolver; 32 import android.content.Context; 33 import android.content.ContextWrapper; 34 import android.content.Intent; 35 import android.content.IntentFilter; 36 import android.content.ServiceConnection; 37 import android.content.pm.PackageManager; 38 import android.nfc.Constants; 39 import android.nfc.cardemulation.HostNfcFService; 40 import android.nfc.cardemulation.NfcFServiceInfo; 41 import android.os.Build; 42 import android.os.Handler; 43 import android.os.IBinder; 44 import android.os.Message; 45 import android.os.Messenger; 46 import android.os.UserHandle; 47 import android.provider.Settings; 48 import android.util.Log; 49 50 import androidx.test.ext.junit.runners.AndroidJUnit4; 51 import androidx.test.platform.app.InstrumentationRegistry; 52 53 import com.android.dx.mockito.inline.extended.ExtendedMockito; 54 import com.android.nfc.cardemulation.AidRoutingManager; 55 import com.android.nfc.cardemulation.CardEmulationManager; 56 import com.android.nfc.cardemulation.HostNfcFEmulationManager; 57 import com.android.nfc.cardemulation.RegisteredAidCache; 58 import com.android.nfc.cardemulation.RegisteredT3tIdentifiersCache; 59 import com.android.nfc.cardemulation.RoutingOptionManager; 60 61 import org.junit.After; 62 import org.junit.Assert; 63 import org.junit.Before; 64 import org.junit.Test; 65 import org.junit.runner.RunWith; 66 import org.mockito.MockitoSession; 67 import org.mockito.quality.Strictness; 68 69 import com.android.nfc.flags.Flags; 70 71 @RunWith(AndroidJUnit4.class) 72 public class HostNfcFEmulationManagerTest { 73 74 private static final String TAG = HostNfcFEmulationManagerTest.class.getSimpleName(); 75 private MockitoSession mStaticMockSession; 76 private HostNfcFEmulationManager mHostNfcFEmulationManager; 77 private ComponentName componentName; 78 79 @Before setUp()80 public void setUp() throws Exception { 81 mStaticMockSession = ExtendedMockito.mockitoSession() 82 .mockStatic(Flags.class) 83 .mockStatic(NfcStatsLog.class) 84 .mockStatic(Message.class) 85 .strictness(Strictness.LENIENT) 86 .startMocking(); 87 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 88 Context mockContext = new ContextWrapper(context) { 89 90 public Context createContextAsUser(@NonNull UserHandle user, 91 @CreatePackageOptions int flags) { 92 if (Build.IS_ENG) { 93 throw new IllegalStateException("createContextAsUser not overridden!"); 94 } 95 return this; 96 } 97 98 public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver, 99 @NonNull IntentFilter filter, @Nullable String broadcastPermission, 100 @Nullable Handler scheduler) { 101 return mock(Intent.class); 102 } 103 104 public ContentResolver getContentResolver() { 105 return mock(ContentResolver.class); 106 } 107 108 public boolean bindServiceAsUser( 109 @NonNull @RequiresPermission Intent service, @NonNull ServiceConnection conn, 110 int flags, 111 @NonNull UserHandle user) { 112 return true; 113 } 114 115 public void unbindService(@NonNull ServiceConnection conn) { 116 117 } 118 119 120 }; 121 122 when(Flags.statsdCeEventsFlag()).thenReturn(false); 123 RegisteredT3tIdentifiersCache t3tIdentifiersCache = mock( 124 RegisteredT3tIdentifiersCache.class); 125 NfcFServiceInfo nfcFServiceInfo = mock(NfcFServiceInfo.class); 126 componentName = mock(ComponentName.class); 127 when(nfcFServiceInfo.getComponent()).thenReturn(componentName); 128 when(t3tIdentifiersCache.resolveNfcid2("6D2E616E64726F69")).thenReturn(nfcFServiceInfo); 129 Message message = new Message(); 130 when(Message.obtain(null, HostNfcFService.MSG_COMMAND_PACKET)).thenReturn(message); 131 when(Message.obtain(null, HostNfcFService.MSG_DEACTIVATED)).thenReturn(message); 132 when(Message.obtain()).thenReturn(message); 133 134 InstrumentationRegistry.getInstrumentation().runOnMainSync( 135 () -> mHostNfcFEmulationManager = 136 new HostNfcFEmulationManager(mockContext, t3tIdentifiersCache)); 137 Assert.assertNotNull(mHostNfcFEmulationManager); 138 } 139 140 @After tearDown()141 public void tearDown() throws Exception { 142 mStaticMockSession.finishMocking(); 143 } 144 145 @Test testOnEnabledForegroundNfcFServiceChanged()146 public void testOnEnabledForegroundNfcFServiceChanged() { 147 String packageName = mHostNfcFEmulationManager.getEnabledFgServiceName(); 148 Assert.assertNull(packageName); 149 when(componentName.getPackageName()).thenReturn("com.android.nfc"); 150 mHostNfcFEmulationManager.onEnabledForegroundNfcFServiceChanged(0, componentName); 151 packageName = mHostNfcFEmulationManager.getEnabledFgServiceName(); 152 Assert.assertNotNull(packageName); 153 Assert.assertEquals("com.android.nfc", packageName); 154 155 } 156 157 @Test testOnHostEmulationData()158 public void testOnHostEmulationData() { 159 testOnEnabledForegroundNfcFServiceChanged(); 160 mHostNfcFEmulationManager.onHostEmulationData("com.android.nfc".getBytes()); 161 ExtendedMockito.verify(() -> NfcStatsLog.write(NfcStatsLog.NFC_CARDEMULATION_OCCURRED, 162 NfcStatsLog.NFC_CARDEMULATION_OCCURRED__CATEGORY__HCE_PAYMENT, 163 "HCEF", 164 0)); 165 } 166 167 @Test testOnNfcDisabled()168 public void testOnNfcDisabled() { 169 testOnHostEmulationData(); 170 ServiceConnection serviceConnection = mHostNfcFEmulationManager.getServiceConnection(); 171 Message message = mock(Message.class); 172 when(Message.obtain(null, HostNfcFService.MSG_COMMAND_PACKET)).thenReturn(message); 173 serviceConnection.onServiceConnected(mock(ComponentName.class), mock(IBinder.class)); 174 int userId = mHostNfcFEmulationManager.getServiceUserId(); 175 Assert.assertEquals(0, userId); 176 mHostNfcFEmulationManager.onNfcDisabled(); 177 userId = mHostNfcFEmulationManager.getServiceUserId(); 178 Assert.assertEquals(-1, userId); 179 ExtendedMockito.verify(() -> Message.obtain(null, HostNfcFService.MSG_COMMAND_PACKET)); 180 } 181 182 183 @Test testOnUserSwitched()184 public void testOnUserSwitched() { 185 testOnHostEmulationData(); 186 ServiceConnection serviceConnection = mHostNfcFEmulationManager.getServiceConnection(); 187 Message message = mock(Message.class); 188 when(Message.obtain(null, HostNfcFService.MSG_COMMAND_PACKET)).thenReturn(message); 189 serviceConnection.onServiceConnected(mock(ComponentName.class), mock(IBinder.class)); 190 int userId = mHostNfcFEmulationManager.getServiceUserId(); 191 Assert.assertEquals(0, userId); 192 mHostNfcFEmulationManager.onUserSwitched(); 193 boolean isUserSwitched = mHostNfcFEmulationManager.isUserSwitched(); 194 Assert.assertTrue(isUserSwitched); 195 userId = mHostNfcFEmulationManager.getServiceUserId(); 196 Assert.assertEquals(-1, userId); 197 ExtendedMockito.verify(() -> Message.obtain(null, HostNfcFService.MSG_COMMAND_PACKET)); 198 } 199 200 @Test testOnHostEmulationDeactivated()201 public void testOnHostEmulationDeactivated() { 202 testOnHostEmulationData(); 203 ServiceConnection serviceConnection = mHostNfcFEmulationManager.getServiceConnection(); 204 Message message = mock(Message.class); 205 when(Message.obtain(null, HostNfcFService.MSG_COMMAND_PACKET)).thenReturn(message); 206 serviceConnection.onServiceConnected(mock(ComponentName.class), mock(IBinder.class)); 207 ComponentName serviceName = mHostNfcFEmulationManager.getServiceName(); 208 Assert.assertNotNull(serviceName); 209 mHostNfcFEmulationManager.onHostEmulationDeactivated(); 210 serviceName = mHostNfcFEmulationManager.getServiceName(); 211 Assert.assertNull(serviceName); 212 } 213 } 214