Home | History | Annotate | Download | only in p2p
      1 /*
      2  * Copyright (C) 2017 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.server.wifi.p2p;
     17 
     18 import static org.junit.Assert.*;
     19 import static org.mockito.Matchers.*;
     20 import static org.mockito.Mockito.doAnswer;
     21 import static org.mockito.Mockito.mock;
     22 import static org.mockito.Mockito.never;
     23 import static org.mockito.Mockito.times;
     24 import static org.mockito.Mockito.verify;
     25 
     26 import android.app.test.MockAnswerUtil.AnswerWithArguments;
     27 import android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIfaceCallback;
     28 import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods;
     29 import android.net.wifi.WpsInfo;
     30 import android.net.wifi.p2p.WifiP2pConfig;
     31 import android.net.wifi.p2p.WifiP2pDevice;
     32 import android.net.wifi.p2p.WifiP2pGroup;
     33 import android.net.wifi.p2p.WifiP2pProvDiscEvent;
     34 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
     35 
     36 import com.android.server.wifi.util.NativeUtil;
     37 
     38 import org.junit.Assert.*;
     39 import org.junit.Before;
     40 import org.junit.Test;
     41 import org.mockito.ArgumentCaptor;
     42 import org.mockito.MockitoAnnotations;
     43 
     44 import java.util.ArrayList;
     45 import java.util.HashSet;
     46 import java.util.List;
     47 
     48 
     49 /**
     50  * Unit tests for SupplicantP2pIfaceCallback
     51  */
     52 public class SupplicantP2pIfaceCallbackTest {
     53     private static final String TAG = "SupplicantP2pIfaceCallbackTest";
     54 
     55     private String mIface = "test_p2p0";
     56     private WifiP2pMonitor mMonitor;
     57     private SupplicantP2pIfaceCallback mDut;
     58 
     59     private byte[] mDeviceAddressInvalid1 = { 0x00 };
     60     private byte[] mDeviceAddressInvalid2 = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
     61     private byte[] mDeviceAddress1Bytes = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
     62     private String mDeviceAddress1String = "00:11:22:33:44:55";
     63     private byte[] mDeviceAddress2Bytes = { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56 };
     64     private String mDeviceAddress2String = "01:12:23:34:45:56";
     65     private byte[] mDeviceInfoBytes = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
     66     private static final byte[] DEVICE_ADDRESS = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
     67 
     68     private class SupplicantP2pIfaceCallbackSpy extends SupplicantP2pIfaceCallback {
     69         SupplicantP2pIfaceCallbackSpy(String iface, WifiP2pMonitor monitor) {
     70             super(iface, monitor);
     71         }
     72     }
     73 
     74     @Before
     75     public void setUp() throws Exception {
     76         MockitoAnnotations.initMocks(this);
     77         mMonitor = mock(WifiP2pMonitor.class);
     78         mDut = new SupplicantP2pIfaceCallbackSpy(mIface, mMonitor);
     79     }
     80 
     81     /**
     82      * Sunny day scenario for onDeviceFound call.
     83      */
     84     @Test
     85     public void testOnDeviceFound_success() throws Exception {
     86         byte[] fakePrimaryDeviceTypeBytes = { 0x01, 0x02, 0x03 };
     87         String fakePrimaryDeviceTypeString = "010203";
     88         String fakeDeviceName = "test device name";
     89         short fakeConfigMethods = 0x1234;
     90         byte fakeCapabilities = 123;
     91         int fakeGroupCapabilities = 456;
     92 
     93         doAnswer(new AnswerWithArguments() {
     94             public void answer(String iface, WifiP2pDevice device) {
     95                 // NOTE: mDeviceAddress1Bytes seems to be ignored by
     96                 // legacy implementation of WifiP2pDevice.
     97                 assertEquals(iface, mIface);
     98                 assertEquals(device.deviceName, fakeDeviceName);
     99                 assertEquals(device.primaryDeviceType, fakePrimaryDeviceTypeString);
    100                 assertEquals(device.deviceCapability, fakeCapabilities);
    101                 assertEquals(device.groupCapability, fakeGroupCapabilities);
    102                 assertEquals(device.wpsConfigMethodsSupported, fakeConfigMethods);
    103                 assertEquals(device.deviceAddress, mDeviceAddress2String);
    104                 assertEquals(device.status, WifiP2pDevice.AVAILABLE);
    105             }
    106         })
    107         .when(mMonitor).broadcastP2pDeviceFound(
    108                 anyString(), any(WifiP2pDevice.class));
    109 
    110         mDut.onDeviceFound(
    111                 mDeviceAddress1Bytes, mDeviceAddress2Bytes,
    112                 fakePrimaryDeviceTypeBytes,
    113                 fakeDeviceName, fakeConfigMethods,
    114                 fakeCapabilities, fakeGroupCapabilities,
    115                 mDeviceInfoBytes);
    116 
    117         mDut.onDeviceFound(
    118                 mDeviceAddress1Bytes, mDeviceAddress2Bytes,
    119                 fakePrimaryDeviceTypeBytes,
    120                 fakeDeviceName, fakeConfigMethods,
    121                 fakeCapabilities, fakeGroupCapabilities,
    122                 null);
    123 
    124         // Make sure we issued a broadcast each time.
    125         verify(mMonitor, times(2)).broadcastP2pDeviceFound(
    126                 anyString(), any(WifiP2pDevice.class));
    127     }
    128 
    129     /**
    130      * Failing scenarios for onDeviceFound call.
    131      */
    132     @Test
    133     public void testOnDeviceFound_invalidArguments() throws Exception {
    134         byte[] fakePrimaryDeviceTypeBytes = { 0x01, 0x02, 0x03 };
    135         String fakePrimaryDeviceTypeString = "010203";
    136         String fakeDeviceName = "test device name";
    137         short fakeConfigMethods = 0x1234;
    138         byte fakeCapabilities = 123;
    139         int fakeGroupCapabilities = 456;
    140 
    141         mDut.onDeviceFound(
    142                 mDeviceAddress2Bytes, null,
    143                 fakePrimaryDeviceTypeBytes,
    144                 fakeDeviceName, fakeConfigMethods,
    145                 fakeCapabilities, fakeGroupCapabilities,
    146                 mDeviceInfoBytes);
    147         verify(mMonitor, never()).broadcastP2pDeviceFound(
    148                 anyString(), any(WifiP2pDevice.class));
    149 
    150 
    151         mDut.onDeviceFound(
    152                 mDeviceAddress1Bytes, mDeviceAddress2Bytes,
    153                 null,
    154                 fakeDeviceName, fakeConfigMethods,
    155                 fakeCapabilities, fakeGroupCapabilities,
    156                 mDeviceInfoBytes);
    157         verify(mMonitor, never()).broadcastP2pDeviceFound(
    158                 anyString(), any(WifiP2pDevice.class));
    159 
    160 
    161         mDut.onDeviceFound(
    162                 mDeviceAddress1Bytes, mDeviceAddress2Bytes,
    163                 fakePrimaryDeviceTypeBytes,
    164                 null, fakeConfigMethods,
    165                 fakeCapabilities, fakeGroupCapabilities,
    166                 mDeviceInfoBytes);
    167         verify(mMonitor, never()).broadcastP2pDeviceFound(
    168                 anyString(), any(WifiP2pDevice.class));
    169 
    170 
    171         mDut.onDeviceFound(
    172                 mDeviceAddress1Bytes, mDeviceAddressInvalid1,
    173                 fakePrimaryDeviceTypeBytes,
    174                 null, fakeConfigMethods,
    175                 fakeCapabilities, fakeGroupCapabilities,
    176                 mDeviceInfoBytes);
    177         verify(mMonitor, never()).broadcastP2pDeviceFound(
    178                 anyString(), any(WifiP2pDevice.class));
    179 
    180 
    181         mDut.onDeviceFound(
    182                 mDeviceAddress1Bytes, mDeviceAddressInvalid2,
    183                 fakePrimaryDeviceTypeBytes,
    184                 null, fakeConfigMethods,
    185                 fakeCapabilities, fakeGroupCapabilities,
    186                 mDeviceInfoBytes);
    187         verify(mMonitor, never()).broadcastP2pDeviceFound(
    188                 anyString(), any(WifiP2pDevice.class));
    189     }
    190 
    191     /**
    192      * Sunny day scenario for onDeviceLost call.
    193      */
    194     @Test
    195     public void testOnDeviceLost_success() throws Exception {
    196         doAnswer(new AnswerWithArguments() {
    197             public void answer(String iface, WifiP2pDevice device) {
    198                 assertEquals(iface, mIface);
    199                 assertEquals(device.deviceAddress, mDeviceAddress1String);
    200                 assertEquals(device.status, WifiP2pDevice.UNAVAILABLE);
    201             }
    202         })
    203         .when(mMonitor).broadcastP2pDeviceLost(
    204                 anyString(), any(WifiP2pDevice.class));
    205 
    206         mDut.onDeviceLost(mDeviceAddress1Bytes);
    207 
    208         // Make sure we issued a broadcast each time.
    209         verify(mMonitor, times(1)).broadcastP2pDeviceLost(
    210                 anyString(), any(WifiP2pDevice.class));
    211     }
    212 
    213     /**
    214      * Failing scenarios for onDeviceLost call.
    215      */
    216     @Test
    217     public void testOnDeviceLost_invalidArguments() throws Exception {
    218         mDut.onDeviceLost(null);
    219         verify(mMonitor, never()).broadcastP2pDeviceLost(
    220                 anyString(), any(WifiP2pDevice.class));
    221 
    222         mDut.onDeviceLost(mDeviceAddressInvalid1);
    223         verify(mMonitor, never()).broadcastP2pDeviceLost(
    224                 anyString(), any(WifiP2pDevice.class));
    225 
    226         mDut.onDeviceLost(mDeviceAddressInvalid2);
    227         verify(mMonitor, never()).broadcastP2pDeviceLost(
    228                 anyString(), any(WifiP2pDevice.class));
    229     }
    230 
    231     /**
    232      * Sunny day scenario for onGoNegotiationRequest call.
    233      */
    234     @Test
    235     public void testOnGoNegotiationRequest_success() throws Exception {
    236         HashSet<Integer> setups = new HashSet<Integer>();
    237 
    238         doAnswer(new AnswerWithArguments() {
    239             public void answer(String iface, WifiP2pConfig config) {
    240                 assertEquals(iface, mIface);
    241                 assertNotNull(config.wps);
    242                 setups.add(config.wps.setup);
    243                 assertEquals(config.deviceAddress, mDeviceAddress1String);
    244             }
    245         })
    246         .when(mMonitor).broadcastP2pGoNegotiationRequest(
    247                 anyString(), any(WifiP2pConfig.class));
    248 
    249         mDut.onGoNegotiationRequest(mDeviceAddress1Bytes,
    250                 (short)ISupplicantP2pIfaceCallback.WpsDevPasswordId.USER_SPECIFIED);
    251         assertTrue(setups.contains(WpsInfo.DISPLAY));
    252 
    253         mDut.onGoNegotiationRequest(mDeviceAddress1Bytes,
    254                 (short)ISupplicantP2pIfaceCallback.WpsDevPasswordId.PUSHBUTTON);
    255         assertTrue(setups.contains(WpsInfo.PBC));
    256 
    257         mDut.onGoNegotiationRequest(mDeviceAddress1Bytes,
    258                 (short)ISupplicantP2pIfaceCallback.WpsDevPasswordId.REGISTRAR_SPECIFIED);
    259         assertTrue(setups.contains(WpsInfo.KEYPAD));
    260 
    261         // Invalid should default to PBC
    262         setups.clear();
    263         mDut.onGoNegotiationRequest(mDeviceAddress1Bytes, (short)0xffff);
    264         assertTrue(setups.contains(WpsInfo.PBC));
    265     }
    266 
    267     /**
    268      * Failing scenarios for onGoNegotiationRequest call.
    269      */
    270     @Test
    271     public void testOnGoNegotiationRequest_invalidArguments() throws Exception {
    272         mDut.onGoNegotiationRequest(null, (short)0);
    273         verify(mMonitor, never()).broadcastP2pDeviceLost(
    274                 anyString(), any(WifiP2pDevice.class));
    275 
    276         mDut.onGoNegotiationRequest(mDeviceAddressInvalid1, (short)0);
    277         verify(mMonitor, never()).broadcastP2pDeviceLost(
    278                 anyString(), any(WifiP2pDevice.class));
    279 
    280         mDut.onGoNegotiationRequest(mDeviceAddressInvalid2, (short)0);
    281         verify(mMonitor, never()).broadcastP2pDeviceLost(
    282                 anyString(), any(WifiP2pDevice.class));
    283     }
    284 
    285     /**
    286      * Sunny day scenario for onGroupStarted call.
    287      */
    288     @Test
    289     public void testOnGroupStarted_success() throws Exception {
    290         String fakeName = "group name";
    291         String fakePassphrase = "secret";
    292         ArrayList<Byte> fakeSsidBytesList = new ArrayList<Byte>() {{
    293             add((byte)0x30);
    294             add((byte)0x31);
    295             add((byte)0x32);
    296             add((byte)0x33);
    297         }};
    298         String fakeSsidString = "0123";
    299         HashSet<String> passwords = new HashSet<String>();
    300 
    301         doAnswer(new AnswerWithArguments() {
    302             public void answer(String iface, WifiP2pGroup group) {
    303                 assertEquals(iface, mIface);
    304                 assertNotNull(group.getOwner());
    305                 assertEquals(group.getOwner().deviceAddress, mDeviceAddress1String);
    306                 assertEquals(group.getNetworkId(), WifiP2pGroup.PERSISTENT_NET_ID);
    307                 passwords.add(group.getPassphrase());
    308                 assertEquals(group.getInterface(), fakeName);
    309                 assertEquals(group.getNetworkName(), fakeSsidString);
    310             }
    311         })
    312         .when(mMonitor).broadcastP2pGroupStarted(
    313                 anyString(), any(WifiP2pGroup.class));
    314 
    315         mDut.onGroupStarted(
    316                 fakeName, true, fakeSsidBytesList, 1, null, fakePassphrase,
    317                 mDeviceAddress1Bytes, true);
    318         assertTrue(passwords.contains(fakePassphrase));
    319 
    320         mDut.onGroupStarted(
    321                 fakeName, true, fakeSsidBytesList, 1, null, null,
    322                 mDeviceAddress1Bytes, true);
    323         assertTrue(passwords.contains(null));
    324 
    325         verify(mMonitor, times(2)).broadcastP2pGroupStarted(
    326                 anyString(), any(WifiP2pGroup.class));
    327     }
    328 
    329     /**
    330      * Failing scenarios for onGroupStarted call.
    331      */
    332     @Test
    333     public void testOnGroupStarted_invalidArguments() throws Exception {
    334         String fakeName = "group name";
    335         String fakePassphrase = "secret";
    336         ArrayList<Byte> fakeSsidBytesList = new ArrayList<Byte>() {{
    337             add((byte)0x30);
    338             add((byte)0x31);
    339             add((byte)0x32);
    340             add((byte)0x33);
    341         }};
    342         String fakeSsidString = "0123";
    343 
    344         mDut.onGroupStarted(
    345                 null, true, fakeSsidBytesList, 1, null, fakePassphrase,
    346                 mDeviceAddress1Bytes, true);
    347         verify(mMonitor, never()).broadcastP2pGroupStarted(
    348                 anyString(), any(WifiP2pGroup.class));
    349 
    350         mDut.onGroupStarted(
    351                 fakeName, true, null, 1, null, fakePassphrase,
    352                 mDeviceAddress1Bytes, true);
    353         verify(mMonitor, never()).broadcastP2pGroupStarted(
    354                 anyString(), any(WifiP2pGroup.class));
    355 
    356         mDut.onGroupStarted(
    357                 fakeName, true, fakeSsidBytesList, 1, null, fakePassphrase,
    358                 null, true);
    359         verify(mMonitor, never()).broadcastP2pGroupStarted(
    360                 anyString(), any(WifiP2pGroup.class));
    361     }
    362 
    363     /**
    364      * Test provision discovery callback.
    365      */
    366     @Test
    367     public void testOnProvisionDiscoveryCompleted() throws Exception {
    368         byte[] p2pDeviceAddr = DEVICE_ADDRESS;
    369         boolean isRequest = false;
    370         byte status = ISupplicantP2pIfaceCallback.P2pProvDiscStatusCode.SUCCESS;
    371         short configMethods = WpsConfigMethods.DISPLAY;
    372         String generatedPin = "12345678";
    373 
    374         ArgumentCaptor<WifiP2pProvDiscEvent> discEventCaptor =
    375                 ArgumentCaptor.forClass(WifiP2pProvDiscEvent.class);
    376         mDut.onProvisionDiscoveryCompleted(
    377                 p2pDeviceAddr, isRequest, status, configMethods, generatedPin);
    378         verify(mMonitor).broadcastP2pProvisionDiscoveryEnterPin(
    379                 anyString(), discEventCaptor.capture());
    380         assertEquals(WifiP2pProvDiscEvent.ENTER_PIN, discEventCaptor.getValue().event);
    381 
    382         configMethods = WpsConfigMethods.KEYPAD;
    383         mDut.onProvisionDiscoveryCompleted(
    384                 p2pDeviceAddr, isRequest, status, configMethods, generatedPin);
    385         verify(mMonitor).broadcastP2pProvisionDiscoveryShowPin(
    386                 anyString(), discEventCaptor.capture());
    387         assertEquals(WifiP2pProvDiscEvent.SHOW_PIN, discEventCaptor.getValue().event);
    388         assertEquals(generatedPin, discEventCaptor.getValue().pin);
    389 
    390         isRequest = true;
    391         configMethods = WpsConfigMethods.KEYPAD;
    392         mDut.onProvisionDiscoveryCompleted(
    393                 p2pDeviceAddr, isRequest, status, configMethods, generatedPin);
    394         verify(mMonitor, times(2)).broadcastP2pProvisionDiscoveryEnterPin(
    395                 anyString(), discEventCaptor.capture());
    396         assertEquals(WifiP2pProvDiscEvent.ENTER_PIN, discEventCaptor.getValue().event);
    397 
    398         configMethods = WpsConfigMethods.DISPLAY;
    399         mDut.onProvisionDiscoveryCompleted(
    400                 p2pDeviceAddr, isRequest, status, configMethods, generatedPin);
    401         verify(mMonitor, times(2)).broadcastP2pProvisionDiscoveryShowPin(
    402                 anyString(), discEventCaptor.capture());
    403         assertEquals(WifiP2pProvDiscEvent.SHOW_PIN, discEventCaptor.getValue().event);
    404         assertEquals(generatedPin, discEventCaptor.getValue().pin);
    405 
    406         isRequest = false;
    407         configMethods = WpsConfigMethods.PUSHBUTTON;
    408         mDut.onProvisionDiscoveryCompleted(
    409                 p2pDeviceAddr, isRequest, status, configMethods, generatedPin);
    410         verify(mMonitor).broadcastP2pProvisionDiscoveryPbcResponse(
    411                 anyString(), discEventCaptor.capture());
    412         assertEquals(WifiP2pProvDiscEvent.PBC_RSP, discEventCaptor.getValue().event);
    413 
    414         isRequest = true;
    415         mDut.onProvisionDiscoveryCompleted(
    416                 p2pDeviceAddr, isRequest, status, configMethods, generatedPin);
    417         verify(mMonitor).broadcastP2pProvisionDiscoveryPbcRequest(
    418                 anyString(), discEventCaptor.capture());
    419         assertEquals(WifiP2pProvDiscEvent.PBC_REQ, discEventCaptor.getValue().event);
    420     }
    421 
    422     /**
    423      * Test staAuth with device address, should trigger ApStaConnected broadcast
    424      */
    425     @Test
    426     public void testStaAuth_success() {
    427         // Trigger onStaAuthorized callback, ensure wifimonitor broadcast is sent with WifiP2pDevice
    428         // using the p2pDeviceAddress
    429         ArgumentCaptor<WifiP2pDevice> p2pDeviceCaptor =
    430                 ArgumentCaptor.forClass(WifiP2pDevice.class);
    431         mDut.onStaAuthorized(mDeviceAddress1Bytes, mDeviceAddress2Bytes);
    432         verify(mMonitor).broadcastP2pApStaConnected(any(String.class), p2pDeviceCaptor.capture());
    433         assertEquals(mDeviceAddress2String, p2pDeviceCaptor.getValue().deviceAddress);
    434     }
    435 
    436     /**
    437      * Test staAuth without device address, should trigger ApStaConnected broadcast using srcAddress
    438      */
    439     @Test
    440     public void testStaAuth_noDeviceAddress_success() {
    441         // Trigger onStaAuthorized callback, using a zero'd p2pDeviceAddress, ensure wifimonitor
    442         // broadcast is sent with WifiP2pDevice using the srcAddress
    443         ArgumentCaptor<WifiP2pDevice> p2pDeviceCaptor =
    444                 ArgumentCaptor.forClass(WifiP2pDevice.class);
    445         mDut.onStaAuthorized(mDeviceAddress1Bytes, NativeUtil.ANY_MAC_BYTES);
    446         verify(mMonitor).broadcastP2pApStaConnected(any(String.class), p2pDeviceCaptor.capture());
    447         assertEquals(mDeviceAddress1String, p2pDeviceCaptor.getValue().deviceAddress);
    448     }
    449 
    450     // TLVS hex data encoded as a hex string.
    451     // Taken directly from an observed supplicant service response event
    452     private static final String SERV_DISC_RESP_TLVS = "1d00010100076578616d706c650b5f6166706f766572"
    453             + "746370c00c001001001e000101000b5f6166706f766572746370c00c000c01074578616d706c65c0273c"
    454             + "00010100096d797072696e746572045f697070c00c00100109747874766572733d311a70646c3d617070"
    455             + "6c69636174696f6e2f706f73747363726970741900010100045f697070c00c000c01094d795072696e74"
    456             + "6572c0275f000201000a757569643a36383539646564652d383537342d353961622d393333322d313233"
    457             + "3435363738393031313a3a75726e3a736368656d61732d75706e702d6f72673a736572766963653a436f"
    458             + "6e6e656374696f6e4d616e616765723a3159000201000a757569643a36383539646564652d383537342d"
    459             + "353961622d393333322d3132333435363738393031313a3a75726e3a736368656d61732d75706e702d6f"
    460             + "72673a736572766963653a41565472616e73706f72743a315a000201000a757569643a36383539646564"
    461             + "652d383537342d353961622d393333322d3132333435363738393031313a3a75726e3a736368656d6173"
    462             + "2d75706e702d6f72673a6465766963653a4d6564696152656e64657265723a313e000201000a75756964"
    463             + "3a36383539646564652d383537342d353961622d393333322d3132333435363738393031313a3a75706e"
    464             + "703a726f6f746465766963652d000201000a757569643a36383539646564652d383537342d353961622d"
    465             + "393333322d313233343536373839303131";
    466 
    467     /**
    468      * Pretty basic onServiceDiscoveryResponse callback test.
    469      * Mocks the callback event, passing some observed real data to it, and ensures that it returns
    470      * a non-null WifiP2pServiceResponse list.
    471      */
    472     @Test
    473     public void testOnServiceDiscoveryResponseCompleted_success() throws Exception {
    474         ArrayList<Byte> tlvs = NativeUtil.byteArrayToArrayList(hexStr2Bin(SERV_DISC_RESP_TLVS));
    475         ArgumentCaptor<List<WifiP2pServiceResponse>> respListCaptor =
    476                 ArgumentCaptor.forClass(List.class);
    477         mDut.onServiceDiscoveryResponse(
    478                 mDeviceAddress1Bytes,
    479                 (short) 10 /* unused updateIndicator value */,
    480                 tlvs);
    481         verify(mMonitor).broadcastP2pServiceDiscoveryResponse(anyString(),
    482                 respListCaptor.capture());
    483         assertNotNull(respListCaptor.getValue());
    484     }
    485 
    486     /**
    487      * Converts hex string to byte array.
    488      *
    489      * @param hex hex string. if invalid, return null.
    490      * @return binary data.
    491      */
    492     private static byte[] hexStr2Bin(String hex) {
    493         int sz = hex.length() / 2;
    494         byte[] b = new byte[hex.length() / 2];
    495         for (int i = 0; i < sz; i++) {
    496             try {
    497                 b[i] = (byte) Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16);
    498             } catch (Exception e) {
    499                 return null;
    500             }
    501         }
    502         return b;
    503     }
    504 }
    505