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 import static com.android.nfc.NfcWifiProtectedSetup.NFC_TOKEN_MIME_TYPE; 20 21 import static com.google.common.primitives.Bytes.concat; 22 23 import static org.mockito.ArgumentMatchers.eq; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.spy; 26 import static org.mockito.Mockito.when; 27 28 import android.annotation.NonNull; 29 import android.annotation.Nullable; 30 import android.content.BroadcastReceiver; 31 import android.content.Context; 32 import android.content.ContextWrapper; 33 import android.content.Intent; 34 import android.content.IntentFilter; 35 import android.content.pm.PackageManager; 36 import android.content.res.Resources; 37 import android.net.wifi.WifiConfiguration; 38 import android.nfc.FormatException; 39 import android.nfc.NdefMessage; 40 import android.nfc.NdefRecord; 41 import android.nfc.tech.Ndef; 42 import android.os.Handler; 43 import android.os.PowerManager; 44 import android.util.Log; 45 46 import com.android.dx.mockito.inline.extended.ExtendedMockito; 47 48 import junit.framework.TestCase; 49 50 import org.junit.After; 51 import org.junit.Assert; 52 import org.junit.Before; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.mockito.Mockito; 56 import org.mockito.MockitoSession; 57 import org.mockito.quality.Strictness; 58 59 import androidx.test.ext.junit.runners.AndroidJUnit4; 60 import androidx.test.platform.app.InstrumentationRegistry; 61 62 import java.nio.ByteBuffer; 63 64 65 @RunWith(AndroidJUnit4.class) 66 public class NfcWifiProtectedSetupTest extends TestCase { 67 68 private static final String TAG = NfcWifiProtectedSetupTest.class.getSimpleName(); 69 private MockitoSession mStaticMockSession; 70 private Context mockContext; 71 public static final byte[] CREDENTIAL = {0x10, 0x0e}; 72 public static final byte[] NETWORK_IDX = {0x10, 0x26}; 73 public static final byte[] NETWORK_NAME = {0x10, 0x45}; 74 public static final byte[] AUTH_TYPE = {0x10, 0x03}; 75 public static final byte[] CRYPT_TYPE = {0x10, 0x0F}; 76 public static final byte[] AUTH_WPA_PERSONAL = {0x00, 0x02}; 77 public static final byte[] CRYPT_WEP = {0x00, 0x02}; 78 public static final byte[] CRYPT_AES_TKIP = {0x00, 0x0C}; 79 public static final byte[] NETWORK_KEY = {0x10, 0x27}; 80 public static final byte[] WPS_AUTH_WPA_PERSONAL = {0x00, 0x02}; 81 public static final byte[] MAC_ADDRESS = {0x10, 0x20}; 82 83 84 @Before setUp()85 public void setUp() throws Exception { 86 mStaticMockSession = ExtendedMockito.mockitoSession() 87 .mockStatic(Ndef.class) 88 .strictness(Strictness.LENIENT) 89 .startMocking(); 90 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 91 PowerManager mockPowerManager = Mockito.mock(PowerManager.class); 92 when(mockPowerManager.isInteractive()).thenReturn(false); 93 Resources mockResources = Mockito.mock(Resources.class); 94 when(mockResources.getBoolean(eq(R.bool.tag_intent_app_pref_supported))) 95 .thenReturn(false); 96 97 mockContext = new ContextWrapper(context) { 98 @Override 99 public Object getSystemService(String name) { 100 if (Context.POWER_SERVICE.equals(name)) { 101 Log.i(TAG, "[Mock] mockPowerManager"); 102 return mockPowerManager; 103 } 104 return super.getSystemService(name); 105 } 106 107 @Override 108 public Resources getResources() { 109 Log.i(TAG, "[Mock] getResources"); 110 return mockResources; 111 } 112 113 @Override 114 public Intent registerReceiverForAllUsers(@Nullable BroadcastReceiver receiver, 115 @NonNull IntentFilter filter, @Nullable String broadcastPermission, 116 @Nullable Handler scheduler) { 117 Log.i(TAG, "[Mock] getIntent"); 118 return Mockito.mock(Intent.class); 119 } 120 }; 121 } 122 123 @After tearDown()124 public void tearDown() throws Exception { 125 mStaticMockSession.finishMocking(); 126 } 127 128 @Test testTryNfcWifiSetupFailed()129 public void testTryNfcWifiSetupFailed() { 130 Ndef ndef = mock(Ndef.class); 131 NdefMessage ndefMessage = mock(NdefMessage.class); 132 133 NdefRecord[] ndefRecords = new NdefRecord[2]; 134 byte[] version = new byte[]{(0x1 << 4) | (0x2)}; 135 ndefRecords[0] = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, 136 NdefRecord.RTD_HANDOVER_REQUEST, new byte[0], version); 137 ndefRecords[1] = createWifiRecord(new String[]{"Nfctest", "", "Open", "wet"}); 138 when(ndefMessage.getRecords()).thenReturn(ndefRecords); 139 when(ndef.getCachedNdefMessage()).thenReturn(ndefMessage); 140 boolean isSucceeded = NfcWifiProtectedSetup.tryNfcWifiSetup(ndef, mockContext); 141 Log.d(TAG, "testTryNfcWifiSetupFailed - " + isSucceeded); 142 Assert.assertFalse(isSucceeded); 143 } 144 createWifiRecord(String[] data)145 private NdefRecord createWifiRecord(String[] data) { 146 String ssid = data[0]; 147 String password = data[1]; 148 byte[] ssidByte = ssid.getBytes(); 149 byte[] passwordByte = password.getBytes(); 150 byte[] ssidLength = {(byte) ((int) Math.floor(ssid.length() / 256)), 151 (byte) (ssid.length() % 256)}; 152 byte[] passwordLength = {(byte) ((int) Math.floor(password.length() / 256)), 153 (byte) (password.length() % 256)}; 154 byte[] cred = {0x00, 0x36}; 155 byte[] idx = {0x00, 0x01, 0x01}; 156 byte[] mac = {}; 157 158 byte[] payload = concat(CREDENTIAL, cred, 159 NETWORK_IDX, idx, 160 NETWORK_NAME, ssidLength, ssidByte, 161 AUTH_TYPE, AUTH_WPA_PERSONAL, WPS_AUTH_WPA_PERSONAL, 162 CRYPT_TYPE, CRYPT_WEP, CRYPT_AES_TKIP, 163 NETWORK_KEY, passwordLength, passwordByte, 164 MAC_ADDRESS, mac); 165 return NdefRecord.createMime(NFC_TOKEN_MIME_TYPE, payload); 166 } 167 } 168