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