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