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 com.android.nfc.NfcDispatcher.DISPATCH_SUCCESS; 19 20 import static org.mockito.ArgumentMatchers.any; 21 import static org.mockito.ArgumentMatchers.anyInt; 22 import static org.mockito.ArgumentMatchers.eq; 23 import static org.mockito.Mockito.mock; 24 import static org.mockito.Mockito.mockingDetails; 25 import static org.mockito.Mockito.when; 26 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.content.BroadcastReceiver; 30 import android.content.Context; 31 import android.content.ContextWrapper; 32 import android.content.Intent; 33 import android.content.IntentFilter; 34 import android.content.pm.ActivityInfo; 35 import android.content.pm.PackageManager; 36 import android.content.pm.PackageManager.ResolveInfoFlags; 37 import android.content.pm.ResolveInfo; 38 import android.content.res.Resources; 39 import android.nfc.Tag; 40 import android.os.Bundle; 41 import android.os.Handler; 42 import android.os.PowerManager; 43 import android.os.UserHandle; 44 import android.util.Log; 45 import androidx.test.core.content.pm.ApplicationInfoBuilder; 46 import androidx.test.ext.junit.runners.AndroidJUnit4; 47 import androidx.test.platform.app.InstrumentationRegistry; 48 49 import com.android.dx.mockito.inline.extended.ExtendedMockito; 50 import com.android.nfc.handover.HandoverDataParser; 51 52 import java.util.ArrayList; 53 import java.util.List; 54 import java.util.concurrent.atomic.AtomicBoolean; 55 import java.util.concurrent.atomic.AtomicReference; 56 57 import org.junit.After; 58 import org.junit.Assert; 59 import org.junit.Before; 60 import org.junit.Test; 61 import org.junit.runner.RunWith; 62 import org.mockito.Mock; 63 import org.mockito.Mockito; 64 import org.mockito.MockitoAnnotations; 65 import org.mockito.MockitoSession; 66 import org.mockito.quality.Strictness; 67 68 @RunWith(AndroidJUnit4.class) 69 public final class NfcReaderConflictOccurredTest { 70 71 private static final String TAG = NfcReaderConflictOccurredTest.class.getSimpleName(); 72 private NfcInjector mNfcInjector; 73 AtomicBoolean mAtomicBoolean; 74 @Mock 75 DeviceConfigFacade mDeviceConfigFacade; 76 77 private MockitoSession mStaticMockSession; 78 private NfcDispatcher mNfcDispatcher; 79 80 @Before setUp()81 public void setUp() { 82 mStaticMockSession = ExtendedMockito.mockitoSession() 83 .mockStatic(NfcStatsLog.class) 84 .strictness(Strictness.LENIENT) 85 .startMocking(); 86 MockitoAnnotations.initMocks(this); 87 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 88 PackageManager mockPackageManager = Mockito.mock(PackageManager.class); 89 // multiple resolveInfos for Tag 90 when(mockPackageManager.queryIntentActivitiesAsUser( 91 any(Intent.class), 92 any(ResolveInfoFlags.class), 93 any(UserHandle.class))).thenReturn(constructConflictingResolveInfos()); 94 PowerManager mockPowerManager = Mockito.mock(PowerManager.class); 95 when(mockPowerManager.isInteractive()).thenReturn(false); 96 Resources mockResources = Mockito.mock(Resources.class); 97 when(mockResources.getBoolean(eq(R.bool.tag_intent_app_pref_supported))) 98 .thenReturn(false); 99 100 Context mockContext = new ContextWrapper(context) { 101 @Override 102 public PackageManager getPackageManager() { 103 Log.i(TAG, "[Mock] getPackageManager"); 104 return mockPackageManager; 105 } 106 107 @Override 108 public Object getSystemService(String name) { 109 if (Context.POWER_SERVICE.equals(name)) { 110 Log.i(TAG, "[Mock] mockPowerManager"); 111 return mockPowerManager; 112 } 113 return super.getSystemService(name); 114 } 115 116 @Override 117 public Resources getResources() { 118 Log.i(TAG, "[Mock] getResources"); 119 return mockResources; 120 } 121 @Override 122 public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver, 123 @NonNull IntentFilter filter, @Nullable String broadcastPermission, 124 @Nullable Handler scheduler) { 125 Log.i(TAG, "[Mock] getIntent"); 126 return Mockito.mock(Intent.class); 127 } 128 }; 129 mNfcInjector = mock(NfcInjector.class); 130 NfcInjector.setNfcInjector(mNfcInjector); 131 mAtomicBoolean = mock(AtomicBoolean.class); 132 when(mNfcInjector.createAtomicBoolean()).thenReturn(mAtomicBoolean); 133 InstrumentationRegistry.getInstrumentation().runOnMainSync( 134 () -> mNfcDispatcher = new NfcDispatcher( 135 mockContext, new HandoverDataParser(), mNfcInjector, false, 136 mDeviceConfigFacade)); 137 Assert.assertNotNull(mNfcDispatcher); 138 } 139 140 @After tearDown()141 public void tearDown() { 142 mStaticMockSession.finishMocking(); 143 } 144 145 @Test testLogReaderConflict()146 public void testLogReaderConflict() { 147 Tag tag = Tag.createMockTag(null, new int[0], new Bundle[0], 0L); 148 int result = mNfcDispatcher.dispatchTag(tag); 149 ExtendedMockito.verify(() -> NfcStatsLog.write( 150 NfcStatsLog.NFC_READER_CONFLICT_OCCURRED)); 151 } 152 153 154 @Test testLogReaderSuccess()155 public void testLogReaderSuccess() { 156 Tag tag = Tag.createMockTag(null, new int[0], new Bundle[0], 0L); 157 int result = mNfcDispatcher.dispatchTag(tag); 158 Assert.assertEquals(result,DISPATCH_SUCCESS); 159 } 160 constructConflictingResolveInfos()161 public List<ResolveInfo> constructConflictingResolveInfos() { 162 List<ResolveInfo> mockResolves = new ArrayList<>(); 163 mockResolves.add(constructResolveInfo("appName1", "packageName1", 111)); 164 mockResolves.add(constructResolveInfo("appName2", "packageName2", 112)); 165 return mockResolves; 166 } 167 constructResolveInfo(String appName, String packageName, int uid)168 public ResolveInfo constructResolveInfo(String appName, String packageName, int uid) { 169 ResolveInfo resolveInfo = new ResolveInfo(); 170 resolveInfo.activityInfo = new ActivityInfo(); 171 resolveInfo.activityInfo.applicationInfo = 172 ApplicationInfoBuilder.newBuilder() 173 .setName(appName) 174 .setPackageName(packageName) 175 .build(); 176 resolveInfo.activityInfo.applicationInfo.uid = uid; 177 resolveInfo.activityInfo.exported = true; 178 return resolveInfo; 179 } 180 } 181