1 /* 2 * Copyright (C) 2022 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 android.nfc.tech.Ndef.EXTRA_NDEF_MSG; 19 20 import static com.google.common.truth.Truth.assertThat; 21 22 import static org.mockito.ArgumentMatchers.any; 23 import static org.mockito.ArgumentMatchers.anyBoolean; 24 import static org.mockito.ArgumentMatchers.anyInt; 25 import static org.mockito.ArgumentMatchers.anyString; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.Mockito.mock; 28 import static org.mockito.Mockito.verify; 29 import static org.mockito.Mockito.when; 30 31 import android.app.ActivityManager; 32 import android.app.KeyguardManager; 33 import android.app.PendingIntent; 34 import android.bluetooth.BluetoothProtoEnums; 35 import android.content.BroadcastReceiver; 36 import android.content.Context; 37 import android.content.Intent; 38 import android.content.IntentFilter; 39 import android.content.pm.ActivityInfo; 40 import android.content.pm.ApplicationInfo; 41 import android.content.pm.PackageManager; 42 import android.content.pm.ResolveInfo; 43 import android.content.res.Resources; 44 import android.hardware.display.DisplayManager; 45 import android.nfc.INfcOemExtensionCallback; 46 import android.nfc.NdefMessage; 47 import android.nfc.NdefRecord; 48 import android.nfc.NfcAdapter; 49 import android.nfc.Tag; 50 import android.nfc.tech.Ndef; 51 import android.nfc.tech.NfcBarcode; 52 import android.nfc.tech.TagTechnology; 53 import android.os.Bundle; 54 import android.os.Handler; 55 import android.os.Message; 56 import android.os.PowerManager; 57 import android.os.RemoteException; 58 import android.os.UserHandle; 59 import android.os.UserManager; 60 import android.os.test.TestLooper; 61 62 import androidx.test.ext.junit.runners.AndroidJUnit4; 63 64 import com.android.dx.mockito.inline.extended.ExtendedMockito; 65 import com.android.nfc.flags.FeatureFlags; 66 import com.android.nfc.handover.HandoverDataParser; 67 import com.android.nfc.handover.PeripheralHandoverService; 68 69 import org.junit.After; 70 import org.junit.Assert; 71 import org.junit.Before; 72 import org.junit.Test; 73 import org.junit.runner.RunWith; 74 import org.mockito.ArgumentCaptor; 75 import org.mockito.Mock; 76 import org.mockito.MockitoAnnotations; 77 import org.mockito.MockitoSession; 78 import org.mockito.quality.Strictness; 79 80 import java.nio.charset.StandardCharsets; 81 import java.util.ArrayList; 82 import java.util.HashMap; 83 import java.util.List; 84 import java.util.Map; 85 import java.util.concurrent.atomic.AtomicBoolean; 86 87 88 @RunWith(AndroidJUnit4.class) 89 public final class NfcDispatcherTest { 90 91 private static final String TAG = NfcDispatcherTest.class.getSimpleName(); 92 @Mock private NfcInjector mNfcInjector; 93 private MockitoSession mStaticMockSession; 94 private NfcDispatcher mNfcDispatcher; 95 TestLooper mLooper; 96 97 @Mock 98 private Context mockContext; 99 @Mock 100 private Resources mResources; 101 @Mock 102 private PackageManager mPackageManager; 103 @Mock 104 private PowerManager mPowerManager; 105 @Mock 106 KeyguardManager mKeyguardManager; 107 @Mock 108 DisplayManager mDisplayManager; 109 @Mock 110 UserManager mUserManager; 111 @Mock 112 ActivityManager mActivityManager; 113 @Mock 114 NfcAdapter mNfcAdapter; 115 @Mock 116 ForegroundUtils mForegroundUtils; 117 @Mock 118 AtomicBoolean mAtomicBoolean; 119 @Mock 120 DeviceConfigFacade mDeviceConfigFacade; 121 122 @Before setUp()123 public void setUp() throws PackageManager.NameNotFoundException { 124 mLooper = new TestLooper(); 125 mStaticMockSession = ExtendedMockito.mockitoSession() 126 .mockStatic(NfcStatsLog.class) 127 .mockStatic(android.nfc.Flags.class) 128 .mockStatic(com.android.nfc.flags.Flags.class) 129 .mockStatic(NfcAdapter.class) 130 .mockStatic(Ndef.class) 131 .mockStatic(ForegroundUtils.class) 132 .mockStatic(NfcWifiProtectedSetup.class) 133 .strictness(Strictness.LENIENT) 134 .startMocking(); 135 136 MockitoAnnotations.initMocks(this); 137 138 when(mPowerManager.isInteractive()).thenReturn(false); 139 when(mockContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager); 140 when(mockContext.getSystemService(KeyguardManager.class)).thenReturn(mKeyguardManager); 141 when(mockContext.getSystemService(DisplayManager.class)).thenReturn(mDisplayManager); 142 when(mockContext.getSystemService(UserManager.class)).thenReturn(mUserManager); 143 when(mockContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager); 144 when(ForegroundUtils.getInstance(mActivityManager)).thenReturn(mForegroundUtils); 145 when(mockContext.createPackageContextAsUser(anyString(), anyInt(), any())) 146 .thenReturn(mockContext); 147 when(mockContext.createContextAsUser(any(), anyInt())).thenReturn(mockContext); 148 when(mockContext.getPackageManager()).thenReturn(mPackageManager); 149 when(mPackageManager.getApplicationLabel(any())).thenReturn(""); 150 when(mockContext.getApplicationContext()).thenReturn(mockContext); 151 when(mResources.getBoolean(R.bool.tag_intent_app_pref_supported)).thenReturn(true); 152 when(mockContext.getResources()).thenReturn(mResources); 153 when(NfcAdapter.getDefaultAdapter(mockContext)).thenReturn(mNfcAdapter); 154 when(mNfcInjector.createAtomicBoolean()).thenReturn(mAtomicBoolean); 155 156 mNfcDispatcher = new NfcDispatcher(mockContext, 157 new HandoverDataParser(), mNfcInjector, true, mDeviceConfigFacade); 158 mLooper.dispatchAll(); 159 } 160 161 @After tearDown()162 public void tearDown() { 163 mStaticMockSession.finishMocking(); 164 } 165 166 @Test testLogOthers()167 public void testLogOthers() { 168 Tag tag = Tag.createMockTag(null, new int[0], new Bundle[0], 0L); 169 mNfcDispatcher.dispatchTag(tag); 170 ExtendedMockito.verify(() -> NfcStatsLog.write( 171 NfcStatsLog.NFC_TAG_OCCURRED, 172 NfcStatsLog.NFC_TAG_OCCURRED__TYPE__PROVISION, 173 -1, 174 tag.getTechCodeList(), 175 BluetoothProtoEnums.MAJOR_CLASS_UNCATEGORIZED, 176 "")); 177 } 178 179 @Test testSetForegroundDispatchForWifiConnect()180 public void testSetForegroundDispatchForWifiConnect() { 181 PendingIntent pendingIntent = mock(PendingIntent.class); 182 mNfcDispatcher.setForegroundDispatch(pendingIntent, new IntentFilter[]{}, 183 new String[][]{}); 184 Bundle bundle = mock(Bundle.class); 185 when(bundle.getParcelable(EXTRA_NDEF_MSG, android.nfc.NdefMessage.class)).thenReturn( 186 mock( 187 NdefMessage.class)); 188 Tag tag = Tag.createMockTag(null, new int[]{1}, new Bundle[]{bundle}, 0L); 189 Ndef ndef = mock(Ndef.class); 190 when(Ndef.get(tag)).thenReturn(ndef); 191 NdefMessage ndefMessage = mock(NdefMessage.class); 192 when(ndef.getCachedNdefMessage()).thenReturn(ndefMessage); 193 NdefRecord ndefRecord = mock(NdefRecord.class); 194 NdefRecord[] records = {ndefRecord}; 195 when(ndefMessage.getRecords()).thenReturn(records); 196 when(NfcWifiProtectedSetup.tryNfcWifiSetup(ndef, mockContext)).thenReturn(true); 197 mNfcDispatcher.dispatchTag(tag); 198 ExtendedMockito.verify(() -> NfcStatsLog.write( 199 NfcStatsLog.NFC_TAG_OCCURRED, 200 NfcStatsLog.NFC_TAG_OCCURRED__TYPE__WIFI_CONNECT, 201 -1, 202 tag.getTechCodeList(), 203 BluetoothProtoEnums.MAJOR_CLASS_UNCATEGORIZED, 204 "")); 205 } 206 207 @Test testPeripheralHandoverBTParing()208 public void testPeripheralHandoverBTParing() { 209 String btOobPayload = "00060E4C00520100000000000000000000000000000000000000000001"; 210 Bundle bundle = mock(Bundle.class); 211 when(bundle.getParcelable(EXTRA_NDEF_MSG, android.nfc.NdefMessage.class)).thenReturn( 212 mock( 213 NdefMessage.class)); 214 Tag tag = Tag.createMockTag(null, new int[]{1}, new Bundle[]{bundle}, 0L); 215 NdefMessage ndefMessage = mock(NdefMessage.class); 216 NdefRecord ndefRecord = mock(NdefRecord.class); 217 when(ndefRecord.getType()).thenReturn("application/vnd.bluetooth.ep.oob" 218 .getBytes(StandardCharsets.US_ASCII)); 219 when(ndefRecord.getTnf()).thenReturn(NdefRecord.TNF_MIME_MEDIA); 220 when(ndefRecord.getPayload()).thenReturn(btOobPayload.getBytes(StandardCharsets.US_ASCII)); 221 NdefRecord[] records = {ndefRecord}; 222 when(ndefMessage.getRecords()).thenReturn(records); 223 mNfcDispatcher.tryPeripheralHandover(ndefMessage, tag); 224 ExtendedMockito.verify(() -> NfcStatsLog.write( 225 NfcStatsLog.NFC_TAG_OCCURRED, 226 NfcStatsLog.NFC_TAG_OCCURRED__TYPE__BT_PAIRING, 227 -1, 228 tag.getTechCodeList(), 229 BluetoothProtoEnums.MAJOR_CLASS_UNCATEGORIZED, 230 "")); 231 } 232 233 @Test testCheckForAar()234 public void testCheckForAar() { 235 NdefRecord ndefRecord = mock(NdefRecord.class); 236 when(ndefRecord.getTnf()).thenReturn(NdefRecord.TNF_EXTERNAL_TYPE); 237 when(ndefRecord.getType()).thenReturn(NdefRecord.RTD_ANDROID_APP); 238 when(ndefRecord.getPayload()).thenReturn("test".getBytes(StandardCharsets.US_ASCII)); 239 String result = NfcDispatcher.checkForAar(ndefRecord); 240 assertThat(result).isEqualTo("test"); 241 } 242 243 @Test testCreateNfcResolverIntent()244 public void testCreateNfcResolverIntent() { 245 when(mResources.getBoolean(eq(R.bool.tag_intent_app_pref_supported))).thenReturn(true); 246 Tag tag = mock(Tag.class); 247 NdefMessage ndefMessage = mock(NdefMessage.class); 248 NdefRecord ndefRecord = NdefRecord.createUri("https://www.example.com"); 249 when(ndefMessage.getRecords()).thenReturn(new NdefRecord[]{ndefRecord}); 250 NfcDispatcher.DispatchInfo dispatchInfo = new NfcDispatcher 251 .DispatchInfo(mockContext, tag, ndefMessage); 252 ResolveInfo activity = mock(ResolveInfo.class); 253 ActivityInfo activityInfo = mock(ActivityInfo.class); 254 activityInfo.packageName = "com.android.nfc"; 255 activityInfo.name = "test"; 256 ApplicationInfo applicationInfo = mock(ApplicationInfo.class); 257 applicationInfo.uid = 0; 258 activityInfo.applicationInfo = applicationInfo; 259 activity.activityInfo = activityInfo; 260 261 ResolveInfo activity2 = mock(ResolveInfo.class); 262 ActivityInfo activityInfo2 = mock(ActivityInfo.class); 263 activityInfo2.packageName = "com.android.nfc2"; 264 activityInfo2.name = "test2"; 265 ApplicationInfo applicationInfo2 = mock(ApplicationInfo.class); 266 applicationInfo2.uid = 1; 267 activityInfo2.applicationInfo = applicationInfo2; 268 activity2.activityInfo = activityInfo2; 269 270 List<ResolveInfo> activities = new ArrayList<>(); 271 activities.add(activity); 272 activities.add(activity2); 273 Map<String, Boolean> prefList = new HashMap<>(); 274 prefList.put("com.android.nfc", false); 275 when(mNfcAdapter.getTagIntentAppPreferenceForUser(0)).thenReturn(prefList); 276 Assert.assertNotNull(dispatchInfo.intent); 277 dispatchInfo.intent.setAction(NfcAdapter.ACTION_TECH_DISCOVERED); 278 when(android.nfc.Flags.enableNfcMainline()).thenReturn(true); 279 when(com.android.nfc.flags.Flags.nfcAlertTagAppLaunch()).thenReturn(false); 280 dispatchInfo.checkPrefList(activities, 0); 281 282 assertThat(dispatchInfo.rootIntent).isNotNull(); 283 assertThat(dispatchInfo.rootIntent.getAction()).isNotNull(); 284 assertThat(dispatchInfo.rootIntent.getAction()) 285 .isEqualTo(NfcAdapter.ACTION_SHOW_NFC_RESOLVER); 286 } 287 288 @Test testDecodeNfcBarcodeUri()289 public void testDecodeNfcBarcodeUri() { 290 PendingIntent pendingIntent = mock(PendingIntent.class); 291 IntentFilter[] intentFilters = {}; 292 String[][] techLists = {{"Ndef"}}; 293 mNfcDispatcher.setForegroundDispatch(pendingIntent, intentFilters, techLists); 294 ArgumentCaptor<Integer> callingUid = ArgumentCaptor.forClass(Integer.class); 295 verify(mForegroundUtils).registerUidToBackgroundCallback(any(), callingUid.capture()); 296 Tag tag = mock(Tag.class); 297 Bundle bundle = new Bundle(); 298 bundle.putInt(NfcBarcode.EXTRA_BARCODE_TYPE, NfcBarcode.TYPE_KOVIO); 299 when(tag.getTechExtras(TagTechnology.NFC_BARCODE)).thenReturn(bundle); 300 when(tag.hasTech(TagTechnology.NFC_BARCODE)).thenReturn(true); 301 when(tag.getId()).thenReturn(new byte[]{0x04, 0x01, 0x64, 0x0C}); 302 when(tag.getTechList()).thenReturn(new String[]{"Ndef"}); 303 mNfcDispatcher.dispatchTag(tag); 304 ExtendedMockito.verify(() -> NfcStatsLog.write( 305 NfcStatsLog.NFC_TAG_OCCURRED, 306 NfcStatsLog.NFC_TAG_OCCURRED__TYPE__FOREGROUND_DISPATCH, 307 callingUid.getValue(), 308 tag.getTechCodeList(), 309 BluetoothProtoEnums.MAJOR_CLASS_UNCATEGORIZED, 310 "")); 311 } 312 313 @Test testExtractAarPackages()314 public void testExtractAarPackages() { 315 NdefMessage ndefMessage = mock(NdefMessage.class); 316 NdefRecord ndefRecord = mock(NdefRecord.class); 317 when(ndefRecord.getTnf()).thenReturn(NdefRecord.TNF_EXTERNAL_TYPE); 318 when(ndefRecord.getType()).thenReturn(NdefRecord.RTD_ANDROID_APP); 319 when(ndefRecord.getPayload()) 320 .thenReturn("com.android.test".getBytes(StandardCharsets.US_ASCII)); 321 when(ndefMessage.getRecords()).thenReturn(new NdefRecord[]{ndefRecord}); 322 List<String> aarPackages = NfcDispatcher.extractAarPackages(ndefMessage); 323 assertThat(aarPackages).isNotNull(); 324 assertThat(aarPackages.size()).isGreaterThan(0); 325 assertThat(aarPackages.get(0)).isEqualTo("com.android.test"); 326 } 327 328 @Test testFinalize()329 public void testFinalize() throws Throwable { 330 mNfcDispatcher.finalize(); 331 ArgumentCaptor<BroadcastReceiver> receiverArgumentCaptor = ArgumentCaptor.forClass( 332 BroadcastReceiver.class); 333 verify(mockContext).unregisterReceiver(receiverArgumentCaptor.capture()); 334 BroadcastReceiver broadcastReceiver = receiverArgumentCaptor.getValue(); 335 assertThat(broadcastReceiver).isNotNull(); 336 } 337 338 @Test testGetAppSearchIntent()339 public void testGetAppSearchIntent() { 340 Intent intent = NfcDispatcher.getAppSearchIntent("com.android.test"); 341 assertThat(intent).isNotNull(); 342 assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW); 343 } 344 345 @Test testGetOemAppSearchIntent()346 public void testGetOemAppSearchIntent() throws RemoteException { 347 INfcOemExtensionCallback nfcOemExtensionCallback = mock(INfcOemExtensionCallback.class); 348 mNfcDispatcher.setOemExtension(nfcOemExtensionCallback); 349 Intent intent = mNfcDispatcher.getOemAppSearchIntent("com.android.test"); 350 ArgumentCaptor<NfcCallbackResultReceiver> argumentCaptor = ArgumentCaptor.forClass( 351 NfcCallbackResultReceiver.class); 352 verify(nfcOemExtensionCallback).onGetOemAppSearchIntent(any(), argumentCaptor.capture()); 353 NfcCallbackResultReceiver nfcCallbackResultReceiver = argumentCaptor.getValue(); 354 assertThat(nfcCallbackResultReceiver).isNotNull(); 355 } 356 357 @Test testIsComponentEnabled()358 public void testIsComponentEnabled() throws PackageManager.NameNotFoundException { 359 PackageManager packageManager = mock(PackageManager.class); 360 ResolveInfo resolveInfo = mock(ResolveInfo.class); 361 ActivityInfo activityInfo = mock(ActivityInfo.class); 362 activityInfo.packageName = "com.android.test"; 363 activityInfo.name = "test"; 364 resolveInfo.activityInfo = activityInfo; 365 when(packageManager.getActivityInfo(any(), anyInt())).thenReturn(activityInfo); 366 boolean result = NfcDispatcher.isComponentEnabled(packageManager, resolveInfo); 367 assertThat(result).isTrue(); 368 } 369 370 @Test testQueryNfcIntentActivitiesAsUser()371 public void testQueryNfcIntentActivitiesAsUser() { 372 when(mResources.getBoolean(eq(R.bool.tag_intent_app_pref_supported))) 373 .thenReturn(true); 374 Tag tag = mock(Tag.class); 375 NdefMessage ndefMessage = mock(NdefMessage.class); 376 NdefRecord ndefRecord = NdefRecord.createUri("https://www.example.com"); 377 when(ndefMessage.getRecords()).thenReturn(new NdefRecord[]{ndefRecord}); 378 NfcDispatcher.DispatchInfo dispatchInfo = new NfcDispatcher 379 .DispatchInfo(mockContext, tag, ndefMessage); 380 UserHandle userHandle = mock(UserHandle.class); 381 List<UserHandle> luh = new ArrayList<>(); 382 luh.add(userHandle); 383 when(mUserManager.getEnabledProfiles()).thenReturn(luh); 384 when(mUserManager.isQuietModeEnabled(userHandle)).thenReturn(true); 385 dispatchInfo.hasIntentReceiver(); 386 verify(mPackageManager).queryIntentActivitiesAsUser(any(), any(), any()); 387 } 388 389 @Test testReceiveOemCallbackResult()390 public void testReceiveOemCallbackResult() throws RemoteException { 391 Tag tag = mock(Tag.class); 392 NdefMessage ndefMessage = mock(NdefMessage.class); 393 NdefRecord ndefRecord = NdefRecord.createUri("https://www.example.com"); 394 when(ndefMessage.getRecords()).thenReturn(new NdefRecord[]{ndefRecord}); 395 INfcOemExtensionCallback nfcOemExtensionCallback = mock(INfcOemExtensionCallback.class); 396 mNfcDispatcher.setOemExtension(nfcOemExtensionCallback); 397 mNfcDispatcher.receiveOemCallbackResult(tag, ndefMessage); 398 verify(nfcOemExtensionCallback).onNdefMessage(any(), any(), any()); 399 } 400 401 @Test testTryNdef()402 public void testTryNdef() { 403 when(mResources.getBoolean(eq(R.bool.tag_intent_app_pref_supported))) 404 .thenReturn(true); 405 Tag tag = mock(Tag.class); 406 NdefMessage ndefMessage = mock(NdefMessage.class); 407 NdefRecord ndefRecord = NdefRecord.createUri("https://www.example.com"); 408 when(ndefMessage.getRecords()).thenReturn(new NdefRecord[]{ndefRecord}); 409 UserHandle userHandle = mock(UserHandle.class); 410 List<UserHandle> luh = new ArrayList<>(); 411 luh.add(userHandle); 412 when(mUserManager.getEnabledProfiles()).thenReturn(luh); 413 when(mUserManager.isQuietModeEnabled(userHandle)).thenReturn(false); 414 NfcDispatcher.DispatchInfo dispatchInfo = new NfcDispatcher 415 .DispatchInfo(mockContext, tag, ndefMessage); 416 FeatureFlags featureFlags = mock(FeatureFlags.class); 417 when(featureFlags.sendViewIntentForUrlTagDispatch()).thenReturn(false); 418 when(mNfcInjector.getFeatureFlags()).thenReturn(featureFlags); 419 ResolveInfo ri = mock(ResolveInfo.class); 420 when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(ri); 421 mNfcDispatcher.tryNdef(dispatchInfo, ndefMessage); 422 verify(mPackageManager).resolveActivity(any(), anyInt()); 423 } 424 425 @Test testGetUri()426 public void testGetUri() { 427 when(mResources.getBoolean(eq(R.bool.tag_intent_app_pref_supported))) 428 .thenReturn(true); 429 Tag tag = mock(Tag.class); 430 NdefMessage ndefMessage = mock(NdefMessage.class); 431 NdefRecord ndefRecord = NdefRecord.createUri("https://www.example.com"); 432 when(ndefMessage.getRecords()).thenReturn(new NdefRecord[]{ndefRecord}); 433 NfcDispatcher.DispatchInfo dispatchInfo = new NfcDispatcher 434 .DispatchInfo(mockContext, tag, ndefMessage); 435 String uri = dispatchInfo.getUri(); 436 assertThat(uri).isNotNull(); 437 assertThat(uri).isEqualTo("https://www.example.com"); 438 } 439 440 @Test testIsWebIntent()441 public void testIsWebIntent() { 442 when(mResources.getBoolean(eq(R.bool.tag_intent_app_pref_supported))) 443 .thenReturn(true); 444 Tag tag = mock(Tag.class); 445 NdefMessage ndefMessage = mock(NdefMessage.class); 446 NdefRecord ndefRecord = NdefRecord.createUri("https://www.example.com"); 447 when(ndefMessage.getRecords()).thenReturn(new NdefRecord[]{ndefRecord}); 448 NfcDispatcher.DispatchInfo dispatchInfo = new NfcDispatcher 449 .DispatchInfo(mockContext, tag, ndefMessage); 450 boolean webIntent = dispatchInfo.isWebIntent(); 451 assertThat(webIntent).isTrue(); 452 } 453 454 @Test testSetViewIntent()455 public void testSetViewIntent() { 456 when(mResources.getBoolean(eq(R.bool.tag_intent_app_pref_supported))) 457 .thenReturn(true); 458 Tag tag = mock(Tag.class); 459 NdefMessage ndefMessage = mock(NdefMessage.class); 460 NdefRecord ndefRecord = NdefRecord.createUri("https://www.example.com"); 461 when(ndefMessage.getRecords()).thenReturn(new NdefRecord[]{ndefRecord}); 462 NfcDispatcher.DispatchInfo dispatchInfo = new NfcDispatcher 463 .DispatchInfo(mockContext, tag, ndefMessage); 464 Intent intent = dispatchInfo.setViewIntent(); 465 assertThat(intent).isNotNull(); 466 assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW); 467 } 468 469 @Test testTryStartActivity()470 public void testTryStartActivity() { 471 when(mResources.getBoolean(eq(R.bool.tag_intent_app_pref_supported))) 472 .thenReturn(true); 473 Tag tag = mock(Tag.class); 474 NdefMessage ndefMessage = mock(NdefMessage.class); 475 NdefRecord ndefRecord = NdefRecord.createUri("https://www.example.com"); 476 when(ndefMessage.getRecords()).thenReturn(new NdefRecord[]{ndefRecord}); 477 NfcDispatcher.DispatchInfo dispatchInfo = new NfcDispatcher 478 .DispatchInfo(mockContext, tag, ndefMessage); 479 ResolveInfo ri = mock(ResolveInfo.class); 480 ActivityInfo ai = mock(ActivityInfo.class); 481 ApplicationInfo applicationInfo = mock(ApplicationInfo.class); 482 applicationInfo.uid = 0; 483 ai.applicationInfo = applicationInfo; 484 ai.packageName = "com.android.test"; 485 ai.name = "test"; 486 ai.exported = true; 487 ri.activityInfo = ai; 488 List<ResolveInfo> ris = new ArrayList<>(); 489 ris.add(ri); 490 when(mPackageManager.queryIntentActivitiesAsUser(any(), any(), any())).thenReturn(ris); 491 boolean result = dispatchInfo.tryStartActivity(); 492 assertThat(result).isTrue(); 493 ExtendedMockito.verify(() -> NfcStatsLog.write(NfcStatsLog.NFC_TAG_OCCURRED, 494 NfcStatsLog.NFC_TAG_OCCURRED__TYPE__APP_LAUNCH, 495 0, 496 tag.getTechCodeList(), 497 BluetoothProtoEnums.MAJOR_CLASS_UNCATEGORIZED, 498 "")); 499 500 } 501 502 @Test testMessageHandler()503 public void testMessageHandler() { 504 Handler handler = mNfcDispatcher.getHandler(); 505 Message msg = new Message(); 506 msg.arg1 = 1; 507 msg.what = PeripheralHandoverService.MSG_HEADSET_NOT_CONNECTED; 508 handler.handleMessage(msg); 509 verify(mAtomicBoolean).set(true); 510 } 511 } 512