WifiAwareManagerTest.java revision b84ad8062dc7e7e0cbc87e6a6769741b66dd4568
1/*
2 * Copyright (C) 2016 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
17package android.net.wifi.aware;
18
19import static org.hamcrest.core.IsEqual.equalTo;
20import static org.junit.Assert.assertEquals;
21import static org.mockito.Matchers.any;
22import static org.mockito.Matchers.anyInt;
23import static org.mockito.Matchers.anyString;
24import static org.mockito.Matchers.eq;
25import static org.mockito.Matchers.isNull;
26import static org.mockito.Mockito.inOrder;
27import static org.mockito.Mockito.verify;
28import static org.mockito.Mockito.verifyNoMoreInteractions;
29import static org.mockito.Mockito.when;
30
31import android.content.Context;
32import android.net.wifi.RttManager;
33import android.os.Handler;
34import android.os.IBinder;
35import android.os.Parcel;
36import android.os.test.TestLooper;
37import android.test.suitebuilder.annotation.SmallTest;
38import android.util.Base64;
39
40import libcore.util.HexEncoding;
41
42import org.json.JSONObject;
43import org.junit.Before;
44import org.junit.Rule;
45import org.junit.Test;
46import org.junit.rules.ErrorCollector;
47import org.mockito.ArgumentCaptor;
48import org.mockito.InOrder;
49import org.mockito.Mock;
50import org.mockito.MockitoAnnotations;
51
52import java.util.List;
53
54/**
55 * Unit test harness for WifiAwareManager class.
56 */
57@SmallTest
58public class WifiAwareManagerTest {
59    private WifiAwareManager mDut;
60    private TestLooper mMockLooper;
61    private Handler mMockLooperHandler;
62
63    @Rule
64    public ErrorCollector collector = new ErrorCollector();
65
66    @Mock
67    public Context mockContext;
68
69    @Mock
70    public AttachCallback mockCallback;
71
72    @Mock
73    public DiscoverySessionCallback mockSessionCallback;
74
75    @Mock
76    public IWifiAwareManager mockAwareService;
77
78    @Mock
79    public PublishDiscoverySession mockPublishSession;
80
81    @Mock
82    public SubscribeDiscoverySession mockSubscribeSession;
83
84    @Mock
85    public RttManager.RttListener mockRttListener;
86
87    private static final int AWARE_STATUS_ERROR = -1;
88
89    @Before
90    public void setUp() throws Exception {
91        MockitoAnnotations.initMocks(this);
92
93        mDut = new WifiAwareManager(mockContext, mockAwareService);
94        mMockLooper = new TestLooper();
95        mMockLooperHandler = new Handler(mMockLooper.getLooper());
96    }
97
98    /*
99     * Straight pass-through tests
100     */
101
102    /**
103     * Validate pass-through of enableUsage() API.
104     */
105    @Test
106    public void testEnableUsage() throws Exception {
107        mDut.enableUsage();
108
109        verify(mockAwareService).enableUsage();
110    }
111
112    /**
113     * Validate pass-through of disableUsage() API.
114     */
115    @Test
116    public void testDisableUsage() throws Exception {
117        mDut.disableUsage();
118
119        verify(mockAwareService).disableUsage();
120    }
121
122    /**
123     * Validate pass-through of isUsageEnabled() API.
124     */
125    @Test
126    public void testIsUsageEnable() throws Exception {
127        mDut.isAvailable();
128
129        verify(mockAwareService).isUsageEnabled();
130    }
131
132    /**
133     * Validate pass-through of getCharacteristics() API.
134     */
135    @Test
136    public void testGetCharacteristics() throws Exception {
137        mDut.getCharacteristics();
138
139        verify(mockAwareService).getCharacteristics();
140    }
141
142    /*
143     * WifiAwareEventCallbackProxy Tests
144     */
145
146    /**
147     * Validate the successful connect flow: (1) connect + success (2) publish, (3) disconnect
148     * (4) try publishing on old session (5) connect again
149     */
150    @Test
151    public void testConnectFlow() throws Exception {
152        final int clientId = 4565;
153
154        InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService);
155        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
156                .forClass(IWifiAwareEventCallback.class);
157        ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
158                WifiAwareSession.class);
159        ArgumentCaptor<IBinder> binder = ArgumentCaptor.forClass(IBinder.class);
160
161        // (1) connect + success
162        mDut.attach(mockCallback, mMockLooperHandler);
163        inOrder.verify(mockAwareService).connect(binder.capture(), anyString(),
164                clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
165        clientProxyCallback.getValue().onConnectSuccess(clientId);
166        mMockLooper.dispatchAll();
167        inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
168        WifiAwareSession session = sessionCaptor.getValue();
169
170        // (2) publish - should succeed
171        PublishConfig publishConfig = new PublishConfig.Builder().build();
172        session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
173        inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
174                any(IWifiAwareDiscoverySessionCallback.class));
175
176        // (3) disconnect
177        session.destroy();
178        inOrder.verify(mockAwareService).disconnect(eq(clientId), eq(binder.getValue()));
179
180        // (4) try publishing again - fails silently
181        session.publish(new PublishConfig.Builder().build(), mockSessionCallback,
182                mMockLooperHandler);
183
184        // (5) connect
185        mDut.attach(mockCallback, mMockLooperHandler);
186        inOrder.verify(mockAwareService).connect(binder.capture(), anyString(),
187                any(IWifiAwareEventCallback.class), (ConfigRequest) isNull(), eq(false));
188
189        verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
190    }
191
192    /**
193     * Validate the failed connect flow: (1) connect + failure, (2) connect + success (3) subscribe
194     */
195    @Test
196    public void testConnectFailure() throws Exception {
197        final int clientId = 4565;
198        final int reason = AWARE_STATUS_ERROR;
199
200        InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService);
201        ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
202                WifiAwareSession.class);
203        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
204                .forClass(IWifiAwareEventCallback.class);
205
206        // (1) connect + failure
207        mDut.attach(mockCallback, mMockLooperHandler);
208        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
209                clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
210        clientProxyCallback.getValue().onConnectFail(reason);
211        mMockLooper.dispatchAll();
212        inOrder.verify(mockCallback).onAttachFailed();
213
214        // (2) connect + success
215        mDut.attach(mockCallback, mMockLooperHandler);
216        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
217                clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
218        clientProxyCallback.getValue().onConnectSuccess(clientId);
219        mMockLooper.dispatchAll();
220        inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
221        WifiAwareSession session = sessionCaptor.getValue();
222
223        // (4) subscribe: should succeed
224        SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
225        session.subscribe(subscribeConfig, mockSessionCallback, mMockLooperHandler);
226        inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig),
227                any(IWifiAwareDiscoverySessionCallback.class));
228
229        verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
230    }
231
232    /**
233     * Validate that can call connect to create multiple sessions: (1) connect
234     * + success, (2) try connect again
235     */
236    @Test
237    public void testInvalidConnectSequence() throws Exception {
238        final int clientId = 4565;
239
240        InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService);
241        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
242                .forClass(IWifiAwareEventCallback.class);
243
244        // (1) connect + success
245        mDut.attach(mockCallback, mMockLooperHandler);
246        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
247                clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
248        clientProxyCallback.getValue().onConnectSuccess(clientId);
249        mMockLooper.dispatchAll();
250        inOrder.verify(mockCallback).onAttached(any(WifiAwareSession.class));
251
252        // (2) connect + success
253        mDut.attach(mockCallback, mMockLooperHandler);
254        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
255                clientProxyCallback.capture(), (ConfigRequest) isNull(), eq(false));
256        clientProxyCallback.getValue().onConnectSuccess(clientId + 1);
257        mMockLooper.dispatchAll();
258        inOrder.verify(mockCallback).onAttached(any(WifiAwareSession.class));
259
260        verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService);
261    }
262
263    /*
264     * WifiAwareDiscoverySessionCallbackProxy Tests
265     */
266
267    /**
268     * Validate the publish flow: (0) connect + success, (1) publish, (2)
269     * success creates session, (3) pass through everything, (4) update publish
270     * through session, (5) terminate locally, (6) try another command -
271     * ignored.
272     */
273    @Test
274    public void testPublishFlow() throws Exception {
275        final int clientId = 4565;
276        final int sessionId = 123;
277        final ConfigRequest configRequest = new ConfigRequest.Builder().build();
278        final PublishConfig publishConfig = new PublishConfig.Builder().build();
279        final PeerHandle peerHandle = new PeerHandle(873);
280        final String string1 = "hey from here...";
281        final byte[] matchFilter = { 1, 12, 2, 31, 32 };
282        final int messageId = 2123;
283        final int reason = AWARE_STATUS_ERROR;
284
285        InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
286                mockPublishSession);
287        ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
288                WifiAwareSession.class);
289        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
290                .forClass(IWifiAwareEventCallback.class);
291        ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
292                .forClass(IWifiAwareDiscoverySessionCallback.class);
293        ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
294                .forClass(PublishDiscoverySession.class);
295        ArgumentCaptor<PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(PeerHandle.class);
296        ArgumentCaptor<List<byte[]>> matchFilterCaptor = ArgumentCaptor.forClass(
297                (Class) List.class);
298
299        // (0) connect + success
300        mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
301        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
302                clientProxyCallback.capture(), eq(configRequest), eq(false));
303        clientProxyCallback.getValue().onConnectSuccess(clientId);
304        mMockLooper.dispatchAll();
305        inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
306        WifiAwareSession session = sessionCaptor.getValue();
307
308        // (1) publish
309        session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
310        inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
311                sessionProxyCallback.capture());
312
313        // (2) publish session created
314        sessionProxyCallback.getValue().onSessionStarted(sessionId);
315        mMockLooper.dispatchAll();
316        inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
317
318        // (3) ...
319        publishSession.getValue().sendMessage(peerHandle, messageId, string1.getBytes());
320        sessionProxyCallback.getValue().onMatch(peerHandle.peerId, string1.getBytes(), matchFilter);
321        sessionProxyCallback.getValue().onMessageReceived(peerHandle.peerId, string1.getBytes());
322        sessionProxyCallback.getValue().onMessageSendFail(messageId, reason);
323        sessionProxyCallback.getValue().onMessageSendSuccess(messageId);
324        mMockLooper.dispatchAll();
325
326        inOrder.verify(mockAwareService).sendMessage(eq(clientId), eq(sessionId),
327                eq(peerHandle.peerId), eq(string1.getBytes()), eq(messageId), eq(0));
328        inOrder.verify(mockSessionCallback).onServiceDiscovered(peerIdCaptor.capture(),
329                eq(string1.getBytes()),
330                matchFilterCaptor.capture());
331
332        // note: need to capture/compare elements since the Mockito eq() is a shallow comparator
333        List<byte[]> parsedMatchFilter = new TlvBufferUtils.TlvIterable(0, 1, matchFilter).toList();
334        collector.checkThat("match-filter-size", parsedMatchFilter.size(),
335                equalTo(matchFilterCaptor.getValue().size()));
336        collector.checkThat("match-filter-entry0", parsedMatchFilter.get(0),
337                equalTo(matchFilterCaptor.getValue().get(0)));
338        collector.checkThat("match-filter-entry1", parsedMatchFilter.get(1),
339                equalTo(matchFilterCaptor.getValue().get(1)));
340
341        assertEquals(peerIdCaptor.getValue().peerId, peerHandle.peerId);
342        inOrder.verify(mockSessionCallback).onMessageReceived(peerIdCaptor.capture(),
343                eq(string1.getBytes()));
344        assertEquals(peerIdCaptor.getValue().peerId, peerHandle.peerId);
345        inOrder.verify(mockSessionCallback).onMessageSendFailed(eq(messageId));
346        inOrder.verify(mockSessionCallback).onMessageSendSucceeded(eq(messageId));
347
348        // (4) update publish
349        publishSession.getValue().updatePublish(publishConfig);
350        sessionProxyCallback.getValue().onSessionConfigFail(reason);
351        mMockLooper.dispatchAll();
352        inOrder.verify(mockAwareService).updatePublish(eq(clientId), eq(sessionId),
353                eq(publishConfig));
354        inOrder.verify(mockSessionCallback).onSessionConfigFailed();
355
356        // (5) terminate
357        publishSession.getValue().destroy();
358        mMockLooper.dispatchAll();
359        inOrder.verify(mockAwareService).terminateSession(clientId, sessionId);
360
361        // (6) try an update (nothing)
362        publishSession.getValue().updatePublish(publishConfig);
363        mMockLooper.dispatchAll();
364
365        verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
366                mockPublishSession);
367    }
368
369    /**
370     * Validate race condition of session terminate and session action: (1)
371     * connect, (2) publish success + terminate, (3) update.
372     */
373    @Test
374    public void testPublishRemoteTerminate() throws Exception {
375        final int clientId = 4565;
376        final int sessionId = 123;
377        final ConfigRequest configRequest = new ConfigRequest.Builder().build();
378        final PublishConfig publishConfig = new PublishConfig.Builder().build();
379
380        InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
381                mockPublishSession);
382        ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
383                WifiAwareSession.class);
384        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
385                .forClass(IWifiAwareEventCallback.class);
386        ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
387                .forClass(IWifiAwareDiscoverySessionCallback.class);
388        ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
389                .forClass(PublishDiscoverySession.class);
390
391        // (1) connect successfully
392        mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
393        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
394                clientProxyCallback.capture(), eq(configRequest), eq(false));
395        clientProxyCallback.getValue().onConnectSuccess(clientId);
396        mMockLooper.dispatchAll();
397        inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
398        WifiAwareSession session = sessionCaptor.getValue();
399
400        // (2) publish: successfully - then terminated
401        session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
402        inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
403                sessionProxyCallback.capture());
404        sessionProxyCallback.getValue().onSessionStarted(sessionId);
405        sessionProxyCallback.getValue().onSessionTerminated(0);
406        mMockLooper.dispatchAll();
407        inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
408        inOrder.verify(mockSessionCallback).onSessionTerminated();
409
410        // (3) failure when trying to update: NOP
411        publishSession.getValue().updatePublish(publishConfig);
412
413        verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
414                mockPublishSession);
415    }
416
417    /**
418     * Validate the subscribe flow: (0) connect + success, (1) subscribe, (2)
419     * success creates session, (3) pass through everything, (4) update
420     * subscribe through session, (5) terminate locally, (6) try another command
421     * - ignored.
422     */
423    @Test
424    public void testSubscribeFlow() throws Exception {
425        final int clientId = 4565;
426        final int sessionId = 123;
427        final ConfigRequest configRequest = new ConfigRequest.Builder().build();
428        final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
429        final PeerHandle peerHandle = new PeerHandle(873);
430        final String string1 = "hey from here...";
431        final byte[] matchFilter = { 1, 12, 3, 31, 32 }; // bad data!
432        final int messageId = 2123;
433        final int reason = AWARE_STATUS_ERROR;
434
435        InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
436                mockSubscribeSession);
437        ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
438                WifiAwareSession.class);
439        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
440                .forClass(IWifiAwareEventCallback.class);
441        ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
442                .forClass(IWifiAwareDiscoverySessionCallback.class);
443        ArgumentCaptor<SubscribeDiscoverySession> subscribeSession = ArgumentCaptor
444                .forClass(SubscribeDiscoverySession.class);
445        ArgumentCaptor<PeerHandle> peerIdCaptor = ArgumentCaptor.forClass(PeerHandle.class);
446
447        // (0) connect + success
448        mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
449        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
450                clientProxyCallback.capture(), eq(configRequest), eq(false));
451        clientProxyCallback.getValue().onConnectSuccess(clientId);
452        mMockLooper.dispatchAll();
453        inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
454        WifiAwareSession session = sessionCaptor.getValue();
455
456        // (1) subscribe
457        session.subscribe(subscribeConfig, mockSessionCallback, mMockLooperHandler);
458        inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig),
459                sessionProxyCallback.capture());
460
461        // (2) subscribe session created
462        sessionProxyCallback.getValue().onSessionStarted(sessionId);
463        mMockLooper.dispatchAll();
464        inOrder.verify(mockSessionCallback).onSubscribeStarted(subscribeSession.capture());
465
466        // (3) ...
467        subscribeSession.getValue().sendMessage(peerHandle, messageId, string1.getBytes());
468        sessionProxyCallback.getValue().onMatch(peerHandle.peerId, string1.getBytes(), matchFilter);
469        sessionProxyCallback.getValue().onMessageReceived(peerHandle.peerId, string1.getBytes());
470        sessionProxyCallback.getValue().onMessageSendFail(messageId, reason);
471        sessionProxyCallback.getValue().onMessageSendSuccess(messageId);
472        mMockLooper.dispatchAll();
473
474        inOrder.verify(mockAwareService).sendMessage(eq(clientId), eq(sessionId),
475                eq(peerHandle.peerId), eq(string1.getBytes()), eq(messageId), eq(0));
476        inOrder.verify(mockSessionCallback).onServiceDiscovered(peerIdCaptor.capture(),
477                eq(string1.getBytes()), (List<byte[]>) isNull());
478        assertEquals((peerIdCaptor.getValue()).peerId, peerHandle.peerId);
479        inOrder.verify(mockSessionCallback).onMessageReceived(peerIdCaptor.capture(),
480                eq(string1.getBytes()));
481        assertEquals((peerIdCaptor.getValue()).peerId, peerHandle.peerId);
482        inOrder.verify(mockSessionCallback).onMessageSendFailed(eq(messageId));
483        inOrder.verify(mockSessionCallback).onMessageSendSucceeded(eq(messageId));
484
485        // (4) update subscribe
486        subscribeSession.getValue().updateSubscribe(subscribeConfig);
487        sessionProxyCallback.getValue().onSessionConfigFail(reason);
488        mMockLooper.dispatchAll();
489        inOrder.verify(mockAwareService).updateSubscribe(eq(clientId), eq(sessionId),
490                eq(subscribeConfig));
491        inOrder.verify(mockSessionCallback).onSessionConfigFailed();
492
493        // (5) terminate
494        subscribeSession.getValue().destroy();
495        mMockLooper.dispatchAll();
496        inOrder.verify(mockAwareService).terminateSession(clientId, sessionId);
497
498        // (6) try an update (nothing)
499        subscribeSession.getValue().updateSubscribe(subscribeConfig);
500        mMockLooper.dispatchAll();
501
502        verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
503                mockSubscribeSession);
504    }
505
506    /**
507     * Validate race condition of session terminate and session action: (1)
508     * connect, (2) subscribe success + terminate, (3) update.
509     */
510    @Test
511    public void testSubscribeRemoteTerminate() throws Exception {
512        final int clientId = 4565;
513        final int sessionId = 123;
514        final ConfigRequest configRequest = new ConfigRequest.Builder().build();
515        final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
516
517        InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
518                mockSubscribeSession);
519        ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
520                WifiAwareSession.class);
521        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
522                .forClass(IWifiAwareEventCallback.class);
523        ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
524                .forClass(IWifiAwareDiscoverySessionCallback.class);
525        ArgumentCaptor<SubscribeDiscoverySession> subscribeSession = ArgumentCaptor
526                .forClass(SubscribeDiscoverySession.class);
527
528        // (1) connect successfully
529        mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
530        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
531                clientProxyCallback.capture(), eq(configRequest), eq(false));
532        clientProxyCallback.getValue().onConnectSuccess(clientId);
533        mMockLooper.dispatchAll();
534        inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
535        WifiAwareSession session = sessionCaptor.getValue();
536
537        // (2) subscribe: successfully - then terminated
538        session.subscribe(subscribeConfig, mockSessionCallback, mMockLooperHandler);
539        inOrder.verify(mockAwareService).subscribe(eq(clientId), eq(subscribeConfig),
540                sessionProxyCallback.capture());
541        sessionProxyCallback.getValue().onSessionStarted(sessionId);
542        sessionProxyCallback.getValue().onSessionTerminated(0);
543        mMockLooper.dispatchAll();
544        inOrder.verify(mockSessionCallback).onSubscribeStarted(subscribeSession.capture());
545        inOrder.verify(mockSessionCallback).onSessionTerminated();
546
547        // (3) failure when trying to update: NOP
548        subscribeSession.getValue().updateSubscribe(subscribeConfig);
549
550        verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
551                mockSubscribeSession);
552    }
553
554    /*
555     * ConfigRequest Tests
556     */
557
558    @Test
559    public void testConfigRequestBuilderDefaults() {
560        ConfigRequest configRequest = new ConfigRequest.Builder().build();
561
562        collector.checkThat("mClusterHigh", ConfigRequest.CLUSTER_ID_MAX,
563                equalTo(configRequest.mClusterHigh));
564        collector.checkThat("mClusterLow", ConfigRequest.CLUSTER_ID_MIN,
565                equalTo(configRequest.mClusterLow));
566        collector.checkThat("mMasterPreference", 0,
567                equalTo(configRequest.mMasterPreference));
568        collector.checkThat("mSupport5gBand", false, equalTo(configRequest.mSupport5gBand));
569    }
570
571    @Test
572    public void testConfigRequestBuilder() {
573        final int clusterHigh = 100;
574        final int clusterLow = 5;
575        final int masterPreference = 55;
576        final boolean supportBand5g = true;
577
578        ConfigRequest configRequest = new ConfigRequest.Builder().setClusterHigh(clusterHigh)
579                .setClusterLow(clusterLow).setMasterPreference(masterPreference)
580                .setSupport5gBand(supportBand5g)
581                .build();
582
583        collector.checkThat("mClusterHigh", clusterHigh, equalTo(configRequest.mClusterHigh));
584        collector.checkThat("mClusterLow", clusterLow, equalTo(configRequest.mClusterLow));
585        collector.checkThat("mMasterPreference", masterPreference,
586                equalTo(configRequest.mMasterPreference));
587        collector.checkThat("mSupport5gBand", supportBand5g, equalTo(configRequest.mSupport5gBand));
588    }
589
590    @Test(expected = IllegalArgumentException.class)
591    public void testConfigRequestBuilderMasterPrefNegative() {
592        ConfigRequest.Builder builder = new ConfigRequest.Builder();
593        builder.setMasterPreference(-1);
594    }
595
596    @Test(expected = IllegalArgumentException.class)
597    public void testConfigRequestBuilderMasterPrefReserved1() {
598        new ConfigRequest.Builder().setMasterPreference(1);
599    }
600
601    @Test(expected = IllegalArgumentException.class)
602    public void testConfigRequestBuilderMasterPrefReserved255() {
603        new ConfigRequest.Builder().setMasterPreference(255);
604    }
605
606    @Test(expected = IllegalArgumentException.class)
607    public void testConfigRequestBuilderMasterPrefTooLarge() {
608        new ConfigRequest.Builder().setMasterPreference(256);
609    }
610
611    @Test(expected = IllegalArgumentException.class)
612    public void testConfigRequestBuilderClusterLowNegative() {
613        new ConfigRequest.Builder().setClusterLow(-1);
614    }
615
616    @Test(expected = IllegalArgumentException.class)
617    public void testConfigRequestBuilderClusterHighNegative() {
618        new ConfigRequest.Builder().setClusterHigh(-1);
619    }
620
621    @Test(expected = IllegalArgumentException.class)
622    public void testConfigRequestBuilderClusterLowAboveMax() {
623        new ConfigRequest.Builder().setClusterLow(ConfigRequest.CLUSTER_ID_MAX + 1);
624    }
625
626    @Test(expected = IllegalArgumentException.class)
627    public void testConfigRequestBuilderClusterHighAboveMax() {
628        new ConfigRequest.Builder().setClusterHigh(ConfigRequest.CLUSTER_ID_MAX + 1);
629    }
630
631    @Test(expected = IllegalArgumentException.class)
632    public void testConfigRequestBuilderClusterLowLargerThanHigh() {
633        new ConfigRequest.Builder().setClusterLow(100).setClusterHigh(5).build();
634    }
635
636    @Test
637    public void testConfigRequestParcel() {
638        final int clusterHigh = 189;
639        final int clusterLow = 25;
640        final int masterPreference = 177;
641        final boolean supportBand5g = true;
642
643        ConfigRequest configRequest = new ConfigRequest.Builder().setClusterHigh(clusterHigh)
644                .setClusterLow(clusterLow).setMasterPreference(masterPreference)
645                .setSupport5gBand(supportBand5g)
646                .build();
647
648        Parcel parcelW = Parcel.obtain();
649        configRequest.writeToParcel(parcelW, 0);
650        byte[] bytes = parcelW.marshall();
651        parcelW.recycle();
652
653        Parcel parcelR = Parcel.obtain();
654        parcelR.unmarshall(bytes, 0, bytes.length);
655        parcelR.setDataPosition(0);
656        ConfigRequest rereadConfigRequest = ConfigRequest.CREATOR.createFromParcel(parcelR);
657
658        assertEquals(configRequest, rereadConfigRequest);
659    }
660
661    /*
662     * SubscribeConfig Tests
663     */
664
665    @Test
666    public void testSubscribeConfigBuilderDefaults() {
667        SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
668
669        collector.checkThat("mServiceName", subscribeConfig.mServiceName, equalTo(null));
670        collector.checkThat("mSubscribeType", subscribeConfig.mSubscribeType,
671                equalTo(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE));
672        collector.checkThat("mSubscribeCount", subscribeConfig.mSubscribeCount, equalTo(0));
673        collector.checkThat("mTtlSec", subscribeConfig.mTtlSec, equalTo(0));
674        collector.checkThat("mMatchStyle", subscribeConfig.mMatchStyle,
675                equalTo(SubscribeConfig.MATCH_STYLE_ALL));
676        collector.checkThat("mEnableTerminateNotification",
677                subscribeConfig.mEnableTerminateNotification, equalTo(true));
678    }
679
680    @Test
681    public void testSubscribeConfigBuilder() {
682        final String serviceName = "some_service_or_other";
683        final String serviceSpecificInfo = "long arbitrary string with some info";
684        final byte[] matchFilter = { 1, 16, 1, 22 };
685        final int subscribeType = SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE;
686        final int subscribeCount = 10;
687        final int subscribeTtl = 15;
688        final int matchStyle = SubscribeConfig.MATCH_STYLE_FIRST_ONLY;
689        final boolean enableTerminateNotification = false;
690
691        SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName)
692                .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(
693                        new TlvBufferUtils.TlvIterable(0, 1, matchFilter).toList())
694                .setSubscribeType(subscribeType)
695                .setSubscribeCount(subscribeCount).setTtlSec(subscribeTtl).setMatchStyle(matchStyle)
696                .setTerminateNotificationEnabled(enableTerminateNotification).build();
697
698        collector.checkThat("mServiceName", serviceName.getBytes(),
699                equalTo(subscribeConfig.mServiceName));
700        collector.checkThat("mServiceSpecificInfo",
701                serviceSpecificInfo.getBytes(), equalTo(subscribeConfig.mServiceSpecificInfo));
702        collector.checkThat("mMatchFilter", matchFilter, equalTo(subscribeConfig.mMatchFilter));
703        collector.checkThat("mSubscribeType", subscribeType,
704                equalTo(subscribeConfig.mSubscribeType));
705        collector.checkThat("mSubscribeCount", subscribeCount,
706                equalTo(subscribeConfig.mSubscribeCount));
707        collector.checkThat("mTtlSec", subscribeTtl, equalTo(subscribeConfig.mTtlSec));
708        collector.checkThat("mMatchStyle", matchStyle, equalTo(subscribeConfig.mMatchStyle));
709        collector.checkThat("mEnableTerminateNotification", enableTerminateNotification,
710                equalTo(subscribeConfig.mEnableTerminateNotification));
711    }
712
713    @Test
714    public void testSubscribeConfigParcel() {
715        final String serviceName = "some_service_or_other";
716        final String serviceSpecificInfo = "long arbitrary string with some info";
717        final byte[] matchFilter = { 1, 16, 1, 22 };
718        final int subscribeType = SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE;
719        final int subscribeCount = 10;
720        final int subscribeTtl = 15;
721        final int matchStyle = SubscribeConfig.MATCH_STYLE_FIRST_ONLY;
722        final boolean enableTerminateNotification = true;
723
724        SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName)
725                .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(
726                        new TlvBufferUtils.TlvIterable(0, 1, matchFilter).toList())
727                .setSubscribeType(subscribeType)
728                .setSubscribeCount(subscribeCount).setTtlSec(subscribeTtl).setMatchStyle(matchStyle)
729                .setTerminateNotificationEnabled(enableTerminateNotification).build();
730
731        Parcel parcelW = Parcel.obtain();
732        subscribeConfig.writeToParcel(parcelW, 0);
733        byte[] bytes = parcelW.marshall();
734        parcelW.recycle();
735
736        Parcel parcelR = Parcel.obtain();
737        parcelR.unmarshall(bytes, 0, bytes.length);
738        parcelR.setDataPosition(0);
739        SubscribeConfig rereadSubscribeConfig = SubscribeConfig.CREATOR.createFromParcel(parcelR);
740
741        assertEquals(subscribeConfig, rereadSubscribeConfig);
742    }
743
744    @Test(expected = IllegalArgumentException.class)
745    public void testSubscribeConfigBuilderBadSubscribeType() {
746        new SubscribeConfig.Builder().setSubscribeType(10);
747    }
748
749    @Test(expected = IllegalArgumentException.class)
750    public void testSubscribeConfigBuilderNegativeCount() {
751        new SubscribeConfig.Builder().setSubscribeCount(-1);
752    }
753
754    @Test(expected = IllegalArgumentException.class)
755    public void testSubscribeConfigBuilderNegativeTtl() {
756        new SubscribeConfig.Builder().setTtlSec(-100);
757    }
758
759    /**
760     * Validate that a bad match style configuration throws an exception.
761     */
762    @Test(expected = IllegalArgumentException.class)
763    public void testSubscribeConfigBuilderBadMatchStyle() {
764        new SubscribeConfig.Builder().setMatchStyle(10);
765    }
766
767    /*
768     * PublishConfig Tests
769     */
770
771    @Test
772    public void testPublishConfigBuilderDefaults() {
773        PublishConfig publishConfig = new PublishConfig.Builder().build();
774
775        collector.checkThat("mServiceName", publishConfig.mServiceName, equalTo(null));
776        collector.checkThat("mPublishType", publishConfig.mPublishType,
777                equalTo(PublishConfig.PUBLISH_TYPE_UNSOLICITED));
778        collector.checkThat("mPublishCount", publishConfig.mPublishCount, equalTo(0));
779        collector.checkThat("mTtlSec", publishConfig.mTtlSec, equalTo(0));
780        collector.checkThat("mEnableTerminateNotification",
781                publishConfig.mEnableTerminateNotification, equalTo(true));
782    }
783
784    @Test
785    public void testPublishConfigBuilder() {
786        final String serviceName = "some_service_or_other";
787        final String serviceSpecificInfo = "long arbitrary string with some info";
788        final byte[] matchFilter = { 1, 16, 1, 22 };
789        final int publishType = PublishConfig.PUBLISH_TYPE_SOLICITED;
790        final int publishCount = 10;
791        final int publishTtl = 15;
792        final boolean enableTerminateNotification = false;
793
794        PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName)
795                .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(
796                        new TlvBufferUtils.TlvIterable(0, 1, matchFilter).toList())
797                .setPublishType(publishType)
798                .setPublishCount(publishCount).setTtlSec(publishTtl)
799                .setTerminateNotificationEnabled(enableTerminateNotification).build();
800
801        collector.checkThat("mServiceName", serviceName.getBytes(),
802                equalTo(publishConfig.mServiceName));
803        collector.checkThat("mServiceSpecificInfo",
804                serviceSpecificInfo.getBytes(), equalTo(publishConfig.mServiceSpecificInfo));
805        collector.checkThat("mMatchFilter", matchFilter, equalTo(publishConfig.mMatchFilter));
806        collector.checkThat("mPublishType", publishType, equalTo(publishConfig.mPublishType));
807        collector.checkThat("mPublishCount", publishCount, equalTo(publishConfig.mPublishCount));
808        collector.checkThat("mTtlSec", publishTtl, equalTo(publishConfig.mTtlSec));
809        collector.checkThat("mEnableTerminateNotification", enableTerminateNotification,
810                equalTo(publishConfig.mEnableTerminateNotification));
811    }
812
813    @Test
814    public void testPublishConfigParcel() {
815        final String serviceName = "some_service_or_other";
816        final String serviceSpecificInfo = "long arbitrary string with some info";
817        final byte[] matchFilter = { 1, 16, 1, 22 };
818        final int publishType = PublishConfig.PUBLISH_TYPE_SOLICITED;
819        final int publishCount = 10;
820        final int publishTtl = 15;
821        final boolean enableTerminateNotification = false;
822
823        PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName)
824                .setServiceSpecificInfo(serviceSpecificInfo.getBytes()).setMatchFilter(
825                        new TlvBufferUtils.TlvIterable(0, 1, matchFilter).toList())
826                .setPublishType(publishType)
827                .setPublishCount(publishCount).setTtlSec(publishTtl)
828                .setTerminateNotificationEnabled(enableTerminateNotification).build();
829
830        Parcel parcelW = Parcel.obtain();
831        publishConfig.writeToParcel(parcelW, 0);
832        byte[] bytes = parcelW.marshall();
833        parcelW.recycle();
834
835        Parcel parcelR = Parcel.obtain();
836        parcelR.unmarshall(bytes, 0, bytes.length);
837        parcelR.setDataPosition(0);
838        PublishConfig rereadPublishConfig = PublishConfig.CREATOR.createFromParcel(parcelR);
839
840        assertEquals(publishConfig, rereadPublishConfig);
841    }
842
843    @Test(expected = IllegalArgumentException.class)
844    public void testPublishConfigBuilderBadPublishType() {
845        new PublishConfig.Builder().setPublishType(5);
846    }
847
848    @Test(expected = IllegalArgumentException.class)
849    public void testPublishConfigBuilderNegativeCount() {
850        new PublishConfig.Builder().setPublishCount(-4);
851    }
852
853    @Test(expected = IllegalArgumentException.class)
854    public void testPublishConfigBuilderNegativeTtl() {
855        new PublishConfig.Builder().setTtlSec(-10);
856    }
857
858    /*
859     * Ranging tests
860     */
861
862    /**
863     * Validate ranging + success flow: (1) connect, (2) create a (publish) session, (3) start
864     * ranging, (4) ranging success callback, (5) ranging aborted callback ignored (since
865     * listener removed).
866     */
867    @Test
868    public void testRangingCallbacks() throws Exception {
869        final int clientId = 4565;
870        final int sessionId = 123;
871        final int rangingId = 3482;
872        final ConfigRequest configRequest = new ConfigRequest.Builder().build();
873        final PublishConfig publishConfig = new PublishConfig.Builder().build();
874        final RttManager.RttParams rttParams = new RttManager.RttParams();
875        rttParams.deviceType = RttManager.RTT_PEER_NAN;
876        rttParams.bssid = Integer.toString(1234);
877        final RttManager.RttResult rttResults = new RttManager.RttResult();
878        rttResults.distance = 10;
879
880        when(mockAwareService.startRanging(anyInt(), anyInt(),
881                any(RttManager.ParcelableRttParams.class))).thenReturn(rangingId);
882
883        InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
884                mockPublishSession, mockRttListener);
885        ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
886                WifiAwareSession.class);
887        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
888                .forClass(IWifiAwareEventCallback.class);
889        ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
890                .forClass(IWifiAwareDiscoverySessionCallback.class);
891        ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
892                .forClass(PublishDiscoverySession.class);
893        ArgumentCaptor<RttManager.ParcelableRttParams> rttParamCaptor = ArgumentCaptor
894                .forClass(RttManager.ParcelableRttParams.class);
895        ArgumentCaptor<RttManager.RttResult[]> rttResultsCaptor = ArgumentCaptor
896                .forClass(RttManager.RttResult[].class);
897
898        // (1) connect successfully
899        mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
900        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
901                clientProxyCallback.capture(), eq(configRequest), eq(false));
902        clientProxyCallback.getValue().onConnectSuccess(clientId);
903        mMockLooper.dispatchAll();
904        inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
905        WifiAwareSession session = sessionCaptor.getValue();
906
907        // (2) publish successfully
908        session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
909        inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
910                sessionProxyCallback.capture());
911        sessionProxyCallback.getValue().onSessionStarted(sessionId);
912        mMockLooper.dispatchAll();
913        inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
914
915        // (3) start ranging
916        publishSession.getValue().startRanging(new RttManager.RttParams[]{rttParams},
917                mockRttListener);
918        inOrder.verify(mockAwareService).startRanging(eq(clientId), eq(sessionId),
919                rttParamCaptor.capture());
920        collector.checkThat("RttParams.deviceType", rttParams.deviceType,
921                equalTo(rttParamCaptor.getValue().mParams[0].deviceType));
922        collector.checkThat("RttParams.bssid", rttParams.bssid,
923                equalTo(rttParamCaptor.getValue().mParams[0].bssid));
924
925        // (4) ranging success callback
926        clientProxyCallback.getValue().onRangingSuccess(rangingId,
927                new RttManager.ParcelableRttResults(new RttManager.RttResult[] { rttResults }));
928        mMockLooper.dispatchAll();
929        inOrder.verify(mockRttListener).onSuccess(rttResultsCaptor.capture());
930        collector.checkThat("RttResult.distance", rttResults.distance,
931                equalTo(rttResultsCaptor.getValue()[0].distance));
932
933        // (5) ranging aborted callback (should be ignored since listener cleared on first callback)
934        clientProxyCallback.getValue().onRangingAborted(rangingId);
935        mMockLooper.dispatchAll();
936
937        verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
938                mockPublishSession, mockRttListener);
939    }
940
941    /*
942     * Data-path tests
943     */
944
945    /**
946     * Validate that correct network specifier is generated for client-based data-path.
947     */
948    @Test
949    public void testNetworkSpecifierWithClient() throws Exception {
950        final int clientId = 4565;
951        final int sessionId = 123;
952        final PeerHandle peerHandle = new PeerHandle(123412);
953        final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
954        final String token = "Some arbitrary token string - can really be anything";
955        final ConfigRequest configRequest = new ConfigRequest.Builder().build();
956        final PublishConfig publishConfig = new PublishConfig.Builder().build();
957
958        String tokenB64 = Base64.encodeToString(token.getBytes(), Base64.DEFAULT);
959
960        ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
961                WifiAwareSession.class);
962        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
963                .forClass(IWifiAwareEventCallback.class);
964        ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
965                .forClass(IWifiAwareDiscoverySessionCallback.class);
966        ArgumentCaptor<PublishDiscoverySession> publishSession = ArgumentCaptor
967                .forClass(PublishDiscoverySession.class);
968
969        InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
970                mockPublishSession, mockRttListener);
971
972        // (1) connect successfully
973        mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
974        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
975                clientProxyCallback.capture(), eq(configRequest), eq(false));
976        clientProxyCallback.getValue().onConnectSuccess(clientId);
977        mMockLooper.dispatchAll();
978        inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
979        WifiAwareSession session = sessionCaptor.getValue();
980
981        // (2) publish successfully
982        session.publish(publishConfig, mockSessionCallback, mMockLooperHandler);
983        inOrder.verify(mockAwareService).publish(eq(clientId), eq(publishConfig),
984                sessionProxyCallback.capture());
985        sessionProxyCallback.getValue().onSessionStarted(sessionId);
986        mMockLooper.dispatchAll();
987        inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
988
989        // (3) request a network specifier from the session
990        String networkSpecifier = publishSession.getValue().createNetworkSpecifier(peerHandle,
991                token.getBytes());
992
993        // validate format
994        JSONObject jsonObject = new JSONObject(networkSpecifier);
995        collector.checkThat("role", role,
996                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
997        collector.checkThat("client_id", clientId,
998                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
999        collector.checkThat("session_id", sessionId,
1000                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
1001        collector.checkThat("peer_id", peerHandle.peerId,
1002                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
1003        collector.checkThat("token", tokenB64,
1004                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_TOKEN)));
1005
1006        verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
1007                mockPublishSession, mockRttListener);
1008    }
1009
1010    /**
1011     * Validate that correct network specifier is generated for a direct data-path (i.e.
1012     * specifying MAC address as opposed to a client-based oqaque specification).
1013     */
1014    @Test
1015    public void testNetworkSpecifierDirect() throws Exception {
1016        final int clientId = 134;
1017        final ConfigRequest configRequest = new ConfigRequest.Builder().build();
1018        final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false);
1019        final int role = WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR;
1020        final String token = "Some arbitrary token string - can really be anything";
1021
1022        String tokenB64 = Base64.encodeToString(token.getBytes(), Base64.DEFAULT);
1023
1024        ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
1025                WifiAwareSession.class);
1026        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
1027                .forClass(IWifiAwareEventCallback.class);
1028
1029        InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockAwareService,
1030                mockPublishSession, mockRttListener);
1031
1032        // (1) connect successfully
1033        mDut.attach(mMockLooperHandler, configRequest, mockCallback, null);
1034        inOrder.verify(mockAwareService).connect(any(IBinder.class), anyString(),
1035                clientProxyCallback.capture(), eq(configRequest), eq(false));
1036        clientProxyCallback.getValue().onConnectSuccess(clientId);
1037        mMockLooper.dispatchAll();
1038        inOrder.verify(mockCallback).onAttached(sessionCaptor.capture());
1039        WifiAwareSession session = sessionCaptor.getValue();
1040
1041        /* (2) request a direct network specifier*/
1042        String networkSpecifier = session.createNetworkSpecifier(role, someMac, token.getBytes());
1043
1044        /* validate format*/
1045        JSONObject jsonObject = new JSONObject(networkSpecifier);
1046        collector.checkThat("role", role,
1047                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
1048        collector.checkThat("client_id", clientId,
1049                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
1050        collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
1051                jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
1052                false)));
1053        collector.checkThat("token", tokenB64,
1054                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_TOKEN)));
1055
1056        verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
1057                mockPublishSession, mockRttListener);
1058    }
1059}
1060