WifiAwareDataPathStateManagerTest.java revision d45abba86c33bd93863fc9d8f7c84ca28deb17b2
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 com.android.server.wifi.aware;
18
19import static org.hamcrest.core.IsEqual.equalTo;
20import static org.junit.Assert.assertTrue;
21import static org.mockito.Matchers.any;
22import static org.mockito.Matchers.anyBoolean;
23import static org.mockito.Matchers.anyInt;
24import static org.mockito.Matchers.anyShort;
25import static org.mockito.Matchers.anyString;
26import static org.mockito.Matchers.eq;
27import static org.mockito.Mockito.inOrder;
28import static org.mockito.Mockito.mock;
29import static org.mockito.Mockito.verify;
30import static org.mockito.Mockito.verifyNoMoreInteractions;
31import static org.mockito.Mockito.when;
32
33import android.app.test.TestAlarmManager;
34import android.content.Context;
35import android.net.ConnectivityManager;
36import android.net.LinkProperties;
37import android.net.NetworkCapabilities;
38import android.net.NetworkFactory;
39import android.net.NetworkInfo;
40import android.net.NetworkMisc;
41import android.net.NetworkRequest;
42import android.net.wifi.RttManager;
43import android.net.wifi.aware.ConfigRequest;
44import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback;
45import android.net.wifi.aware.IWifiAwareEventCallback;
46import android.net.wifi.aware.IWifiAwareManager;
47import android.net.wifi.aware.PublishConfig;
48import android.net.wifi.aware.SubscribeConfig;
49import android.net.wifi.aware.WifiAwareAttachCallback;
50import android.net.wifi.aware.WifiAwareDiscoveryBaseSession;
51import android.net.wifi.aware.WifiAwareDiscoverySessionCallback;
52import android.net.wifi.aware.WifiAwareManager;
53import android.net.wifi.aware.WifiAwarePublishDiscoverySession;
54import android.net.wifi.aware.WifiAwareSession;
55import android.net.wifi.aware.WifiAwareSubscribeDiscoverySession;
56import android.os.Handler;
57import android.os.IBinder;
58import android.os.INetworkManagementService;
59import android.os.Message;
60import android.os.Messenger;
61import android.os.test.TestLooper;
62import android.test.suitebuilder.annotation.SmallTest;
63import android.util.Pair;
64
65import com.android.internal.util.AsyncChannel;
66
67import libcore.util.HexEncoding;
68
69import org.json.JSONObject;
70import org.junit.Before;
71import org.junit.Rule;
72import org.junit.Test;
73import org.junit.rules.ErrorCollector;
74import org.mockito.ArgumentCaptor;
75import org.mockito.InOrder;
76import org.mockito.Mock;
77import org.mockito.MockitoAnnotations;
78
79import java.lang.reflect.Field;
80import java.util.Arrays;
81
82/**
83 * Unit test harness for WifiAwareDataPathStateManager class.
84 */
85@SmallTest
86public class WifiAwareDataPathStateManagerTest {
87    private static final String sAwareInterfacePrefix = "aware";
88
89    private TestLooper mMockLooper;
90    private Handler mMockLooperHandler;
91    private WifiAwareStateManager mDut;
92    @Mock private WifiAwareNative mMockNative;
93    @Mock private Context mMockContext;
94    @Mock private IWifiAwareManager mMockAwareService;
95    @Mock private WifiAwarePublishDiscoverySession mMockPublishSession;
96    @Mock private WifiAwareSubscribeDiscoverySession mMockSubscribeSession;
97    @Mock private RttManager.RttListener mMockRttListener;
98    @Mock private ConnectivityManager mMockCm;
99    @Mock private INetworkManagementService mMockNwMgt;
100    @Mock private WifiAwareDataPathStateManager.NetworkInterfaceWrapper mMockNetworkInterface;
101    @Mock private IWifiAwareEventCallback mMockCallback;
102    @Mock IWifiAwareDiscoverySessionCallback mMockSessionCallback;
103    TestAlarmManager mAlarmManager;
104
105    @Rule
106    public ErrorCollector collector = new ErrorCollector();
107
108    /**
109     * Initialize mocks.
110     */
111    @Before
112    public void setUp() throws Exception {
113        MockitoAnnotations.initMocks(this);
114
115        mAlarmManager = new TestAlarmManager();
116        when(mMockContext.getSystemService(Context.ALARM_SERVICE))
117                .thenReturn(mAlarmManager.getAlarmManager());
118
119        when(mMockContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mMockCm);
120
121        mMockLooper = new TestLooper();
122        mMockLooperHandler = new Handler(mMockLooper.getLooper());
123
124        mDut = new WifiAwareStateManager();
125        mDut.setNative(mMockNative);
126        mDut.start(mMockContext, mMockLooper.getLooper());
127        mDut.startLate();
128
129        when(mMockNative.getCapabilities(anyShort())).thenReturn(true);
130        when(mMockNative.enableAndConfigure(anyShort(), any(ConfigRequest.class), anyBoolean()))
131                .thenReturn(true);
132        when(mMockNative.disable(anyShort())).thenReturn(true);
133        when(mMockNative.publish(anyShort(), anyInt(), any(PublishConfig.class))).thenReturn(true);
134        when(mMockNative.subscribe(anyShort(), anyInt(), any(SubscribeConfig.class)))
135                .thenReturn(true);
136        when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(byte[].class),
137                any(byte[].class), anyInt())).thenReturn(true);
138        when(mMockNative.stopPublish(anyShort(), anyInt())).thenReturn(true);
139        when(mMockNative.stopSubscribe(anyShort(), anyInt())).thenReturn(true);
140        when(mMockNative.createAwareNetworkInterface(anyShort(), anyString())).thenReturn(true);
141        when(mMockNative.deleteAwareNetworkInterface(anyShort(), anyString())).thenReturn(true);
142        when(mMockNative.initiateDataPath(anyShort(), anyInt(), anyInt(), anyInt(),
143                any(byte[].class), anyString(), any(byte[].class))).thenReturn(true);
144        when(mMockNative.respondToDataPathRequest(anyShort(), anyBoolean(), anyInt(), anyString(),
145                any(byte[].class))).thenReturn(true);
146        when(mMockNative.endDataPath(anyShort(), anyInt())).thenReturn(true);
147
148        when(mMockNetworkInterface.configureAgentProperties(
149                any(WifiAwareDataPathStateManager.AwareNetworkRequestInformation.class),
150                anyString(), anyInt(), any(NetworkInfo.class), any(NetworkCapabilities.class),
151                any(LinkProperties.class))).thenReturn(true);
152
153        installDataPathStateManagerMocks();
154    }
155
156    /**
157     * Validates that creating and deleting all interfaces works based on capabilities.
158     */
159    @Test
160    public void testCreateDeleteAllInterfaces() throws Exception {
161        final int numNdis = 3;
162        final int failCreateInterfaceIndex = 1;
163
164        WifiAwareNative.Capabilities capabilities = new WifiAwareNative.Capabilities();
165        capabilities.maxNdiInterfaces = numNdis;
166
167        ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class);
168        ArgumentCaptor<String> interfaceName = ArgumentCaptor.forClass(String.class);
169        InOrder inOrder = inOrder(mMockNative);
170
171        // (1) get capabilities
172        mDut.queryCapabilities();
173        mMockLooper.dispatchAll();
174        inOrder.verify(mMockNative).getCapabilities(transactionId.capture());
175        mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), capabilities);
176        mMockLooper.dispatchAll();
177
178        // (2) create all interfaces
179        mDut.createAllDataPathInterfaces();
180        mMockLooper.dispatchAll();
181        for (int i = 0; i < numNdis; ++i) {
182            inOrder.verify(mMockNative).createAwareNetworkInterface(transactionId.capture(),
183                    interfaceName.capture());
184            collector.checkThat("interface created -- " + i, sAwareInterfacePrefix + i,
185                    equalTo(interfaceName.getValue()));
186            mDut.onCreateDataPathInterfaceResponse(transactionId.getValue(), true, 0);
187            mMockLooper.dispatchAll();
188        }
189
190        // (3) delete all interfaces [one unsuccessfully] - note that will not necessarily be
191        // done sequentially
192        boolean[] done = new boolean[numNdis];
193        Arrays.fill(done, false);
194        mDut.deleteAllDataPathInterfaces();
195        mMockLooper.dispatchAll();
196        for (int i = 0; i < numNdis; ++i) {
197            inOrder.verify(mMockNative).deleteAwareNetworkInterface(transactionId.capture(),
198                    interfaceName.capture());
199            int interfaceIndex = Integer.valueOf(
200                    interfaceName.getValue().substring(sAwareInterfacePrefix.length()));
201            done[interfaceIndex] = true;
202            if (interfaceIndex == failCreateInterfaceIndex) {
203                mDut.onDeleteDataPathInterfaceResponse(transactionId.getValue(), false, 0);
204            } else {
205                mDut.onDeleteDataPathInterfaceResponse(transactionId.getValue(), true, 0);
206            }
207            mMockLooper.dispatchAll();
208        }
209        for (int i = 0; i < numNdis; ++i) {
210            collector.checkThat("interface deleted -- " + i, done[i], equalTo(true));
211        }
212
213        // (4) create all interfaces (should get a delete for the one which couldn't delete earlier)
214        mDut.createAllDataPathInterfaces();
215        mMockLooper.dispatchAll();
216        for (int i = 0; i < numNdis; ++i) {
217            if (i == failCreateInterfaceIndex) {
218                inOrder.verify(mMockNative).deleteAwareNetworkInterface(transactionId.capture(),
219                        interfaceName.capture());
220                collector.checkThat("interface delete pre-create -- " + i,
221                        sAwareInterfacePrefix + i, equalTo(interfaceName.getValue()));
222                mDut.onDeleteDataPathInterfaceResponse(transactionId.getValue(), true, 0);
223                mMockLooper.dispatchAll();
224            }
225            inOrder.verify(mMockNative).createAwareNetworkInterface(transactionId.capture(),
226                    interfaceName.capture());
227            collector.checkThat("interface created -- " + i, sAwareInterfacePrefix + i,
228                    equalTo(interfaceName.getValue()));
229            mDut.onCreateDataPathInterfaceResponse(transactionId.getValue(), true, 0);
230            mMockLooper.dispatchAll();
231        }
232
233        verifyNoMoreInteractions(mMockNative);
234    }
235
236    /*
237     * Initiator tests
238     */
239
240    /**
241     * Validate the success flow of the Initiator: using session network specifier with a non-null
242     * token.
243     */
244    @Test
245    public void testDataPathInitiatorMacTokenSuccess() throws Exception {
246        testDataPathInitiatorUtility(false, true, true, true);
247    }
248
249    /**
250     * Validate the fail flow of the Initiator: using session network specifier with a null
251     * token.
252     */
253    @Test(expected = IllegalArgumentException.class)
254    public void testDataPathInitiatorMacNoTokenFail() throws Exception {
255        testDataPathInitiatorUtility(false, true, false, true);
256    }
257
258    /**
259     * Validate the fail flow of the Initiator: using session network specifier with a 0
260     * peer ID.
261     */
262    @Test(expected = IllegalArgumentException.class)
263    public void testDataPathInitiatorNoMacFail() throws Exception {
264        testDataPathInitiatorUtility(false, false, true, true);
265    }
266
267    /**
268     * Validate the success flow of the Initiator: using a direct network specifier with a non-null
269     * peer mac and non-null token.
270     */
271    @Test
272    public void testDataPathInitiatorDirectMacTokenSuccess() throws Exception {
273        testDataPathInitiatorUtility(true, true, true, true);
274    }
275
276    /**
277     * Validate the fail flow of the Initiator: using a direct network specifier with a non-null
278     * peer mac and null token.
279     */
280    @Test(expected = IllegalArgumentException.class)
281    public void testDataPathInitiatorDirectMacNoTokenFail() throws Exception {
282        testDataPathInitiatorUtility(true, true, false, true);
283    }
284
285    /**
286     * Validate the fail flow of the Initiator: using a direct network specifier with a null peer
287     * mac and non-null token.
288     */
289    @Test(expected = IllegalArgumentException.class)
290    public void testDataPathInitiatorDirectNoMacTokenFail() throws Exception {
291        testDataPathInitiatorUtility(true, false, true, true);
292    }
293
294    /**
295     * Validate the fail flow of the Initiator: using a direct network specifier with a null peer
296     * mac and null token.
297     */
298    @Test(expected = IllegalArgumentException.class)
299    public void testDataPathInitiatorDirectNoMacNoTokenFail() throws Exception {
300        testDataPathInitiatorUtility(true, false, false, true);
301    }
302
303    /**
304     * Validate the fail flow of the Initiator: use a session network specifier with a non-null
305     * token, but don't get a confirmation.
306     */
307    @Test
308    public void testDataPathInitiatorNoConfirmationTimeoutFail() throws Exception {
309        testDataPathInitiatorUtility(false, true, true, false);
310    }
311
312    /**
313     * Validate the fail flow of a mis-configured request: Publisher as Initiator
314     */
315    @Test
316    public void testDataPathInitiatorOnPublisherError() throws Exception {
317        testDataPathInitiatorResponderMismatchUtility(true);
318    }
319
320    /*
321     * Responder tests
322     */
323
324    /**
325     * Validate the success flow of the Responder: using session network specifier with a non-null
326     * token.
327     */
328    @Test
329    public void testDataPathResonderMacTokenSuccess() throws Exception {
330        testDataPathResponderUtility(false, true, true, true);
331    }
332
333    /**
334     * Validate the success flow of the Responder: using session network specifier with a null
335     * token.
336     */
337    @Test
338    public void testDataPathResonderMacNoTokenSuccess() throws Exception {
339        testDataPathResponderUtility(false, true, false, true);
340    }
341
342    /**
343     * Validate the success flow of the Responder: using session network specifier with a
344     * token and no peer ID (i.e. 0).
345     */
346    @Test
347    public void testDataPathResonderMacTokenNoPeerIdSuccess() throws Exception {
348        testDataPathResponderUtility(false, false, true, true);
349    }
350
351    /**
352     * Validate the success flow of the Responder: using session network specifier with a null
353     * token and no peer ID (i.e. 0).
354     */
355    @Test
356    public void testDataPathResonderMacTokenNoPeerIdNoTokenSuccess() throws Exception {
357        testDataPathResponderUtility(false, false, false, true);
358    }
359
360    /**
361     * Validate the success flow of the Responder: using a direct network specifier with a non-null
362     * peer mac and non-null token.
363     */
364    @Test
365    public void testDataPathResonderDirectMacTokenSuccess() throws Exception {
366        testDataPathResponderUtility(true, true, true, true);
367    }
368
369    /**
370     * Validate the success flow of the Responder: using a direct network specifier with a non-null
371     * peer mac and null token.
372     */
373    @Test
374    public void testDataPathResonderDirectMacNoTokenSuccess() throws Exception {
375        testDataPathResponderUtility(true, true, false, true);
376    }
377
378    /**
379     * Validate the success flow of the Responder: using a direct network specifier with a null peer
380     * mac and non-null token.
381     */
382    @Test
383    public void testDataPathResonderDirectNoMacTokenSuccess() throws Exception {
384        testDataPathResponderUtility(true, false, true, true);
385    }
386
387    /**
388     * Validate the success flow of the Responder: using a direct network specifier with a null peer
389     * mac and null token.
390     */
391    @Test
392    public void testDataPathResonderDirectNoMacNoTokenSuccess() throws Exception {
393        testDataPathResponderUtility(true, false, false, true);
394    }
395
396    /**
397     * Validate the fail flow of the Responder: use a session network specifier with a non-null
398     * token, but don't get a confirmation.
399     */
400    @Test
401    public void testDataPathResponderNoConfirmationTimeoutFail() throws Exception {
402        testDataPathResponderUtility(false, true, true, false);
403    }
404
405    /**
406     * Validate the fail flow of a mis-configured request: Subscriber as Responder
407     */
408    @Test
409    public void testDataPathResponderOnSubscriberError() throws Exception {
410        testDataPathInitiatorResponderMismatchUtility(false);
411    }
412
413    /*
414     * Utilities
415     */
416
417    private void testDataPathInitiatorResponderMismatchUtility(boolean doPublish) throws Exception {
418        final int clientId = 123;
419        final int pubSubId = 11234;
420        final int ndpId = 2;
421        final String token = "some token";
422        final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(1341234);
423        final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false);
424
425        InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback);
426
427        // (0) initialize
428        Pair<Integer, Messenger> res = initDataPathEndPoint(clientId, pubSubId, peerHandle,
429                peerDiscoveryMac, inOrder, doPublish);
430
431        // (1) request network
432        NetworkRequest nr = getSessionNetworkRequest(clientId, res.first, peerHandle, token,
433                doPublish);
434
435        // corrupt the network specifier: reverse the role (so it's mis-matched)
436        JSONObject jsonObject = new JSONObject(nr.networkCapabilities.getNetworkSpecifier());
437        jsonObject.put(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE,
438                1 - jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE));
439        nr.networkCapabilities.setNetworkSpecifier(jsonObject.toString());
440
441        Message reqNetworkMsg = Message.obtain();
442        reqNetworkMsg.what = NetworkFactory.CMD_REQUEST_NETWORK;
443        reqNetworkMsg.obj = nr;
444        reqNetworkMsg.arg1 = 0;
445        res.second.send(reqNetworkMsg);
446        mMockLooper.dispatchAll();
447
448        // consequences of failure:
449        //   Responder (publisher): responds with a rejection to any data-path requests
450        //   Initiator (subscribe): doesn't initiate (i.e. no HAL requests)
451        if (doPublish) {
452            // (2) get request & respond
453            mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId, token.getBytes());
454            mMockLooper.dispatchAll();
455            inOrder.verify(mMockNative).respondToDataPathRequest(anyShort(), eq(false),
456                    eq(ndpId), eq(""), eq(new byte[0]));
457        }
458
459        verifyNoMoreInteractions(mMockNative, mMockCm);
460    }
461
462    private void testDataPathInitiatorUtility(boolean useDirect, boolean provideMac,
463            boolean provideToken, boolean getConfirmation) throws Exception {
464        final int clientId = 123;
465        final int pubSubId = 11234;
466        final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(1341234);
467        final int ndpId = 2;
468        final String token = "some token";
469        final String peerToken = "let's go!";
470        final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false);
471        final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
472
473        ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class);
474        ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class);
475        InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback);
476
477        // (0) initialize
478        Pair<Integer, Messenger> res = initDataPathEndPoint(clientId, pubSubId, peerHandle,
479                peerDiscoveryMac, inOrder, false);
480
481        // (1) request network
482        NetworkRequest nr;
483        if (useDirect) {
484            nr = getDirectNetworkRequest(clientId,
485                    WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR,
486                    provideMac ? peerDiscoveryMac : null, provideToken ? token : null);
487        } else {
488            nr = getSessionNetworkRequest(clientId, res.first, provideMac ? peerHandle : null,
489                    provideToken ? token : null, false);
490        }
491
492        Message reqNetworkMsg = Message.obtain();
493        reqNetworkMsg.what = NetworkFactory.CMD_REQUEST_NETWORK;
494        reqNetworkMsg.obj = nr;
495        reqNetworkMsg.arg1 = 0;
496        res.second.send(reqNetworkMsg);
497        mMockLooper.dispatchAll();
498        inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(),
499                eq(useDirect ? 0 : peerHandle.peerId),
500                eq(WifiAwareNative.CHANNEL_REQUEST_TYPE_REQUESTED), eq(2437), eq(peerDiscoveryMac),
501                eq("aware0"), eq(token.getBytes()));
502        mDut.onInitiateDataPathResponseSuccess(transactionId.getValue(), ndpId);
503        mMockLooper.dispatchAll();
504
505        // (2) get confirmation OR timeout
506        if (getConfirmation) {
507            mDut.onDataPathConfirmNotification(ndpId, peerDataPathMac, true, 0,
508                    peerToken.getBytes());
509            mMockLooper.dispatchAll();
510            inOrder.verify(mMockCm).registerNetworkAgent(messengerCaptor.capture(),
511                    any(NetworkInfo.class), any(LinkProperties.class),
512                    any(NetworkCapabilities.class),
513                    anyInt(), any(NetworkMisc.class));
514        } else {
515            assertTrue(mAlarmManager.dispatch(
516                    WifiAwareStateManager.HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG));
517            mMockLooper.dispatchAll();
518            inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId));
519            mDut.onEndDataPathResponse(transactionId.getValue(), true, 0);
520            mMockLooper.dispatchAll();
521        }
522
523        // (3) end data-path (unless didn't get confirmation)
524        if (getConfirmation) {
525            Message endNetworkReqMsg = Message.obtain();
526            endNetworkReqMsg.what = NetworkFactory.CMD_CANCEL_REQUEST;
527            endNetworkReqMsg.obj = nr;
528            res.second.send(endNetworkReqMsg);
529
530            Message endNetworkUsageMsg = Message.obtain();
531            endNetworkUsageMsg.what = AsyncChannel.CMD_CHANNEL_DISCONNECTED;
532            messengerCaptor.getValue().send(endNetworkUsageMsg);
533
534            mMockLooper.dispatchAll();
535            inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId));
536            mDut.onEndDataPathResponse(transactionId.getValue(), true, 0);
537            mMockLooper.dispatchAll();
538        }
539
540        verifyNoMoreInteractions(mMockNative, mMockCm);
541    }
542
543    private void testDataPathResponderUtility(boolean useDirect, boolean provideMac,
544            boolean provideToken, boolean getConfirmation) throws Exception {
545        final int clientId = 123;
546        final int pubSubId = 11234;
547        final WifiAwareManager.PeerHandle peerHandle = new WifiAwareManager.PeerHandle(1341234);
548        final int ndpId = 2;
549        final String token = "some token";
550        final String peerToken = "let's go!";
551        final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false);
552        final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false);
553
554        ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class);
555        ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class);
556        InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback);
557
558        // (0) initialize
559        Pair<Integer, Messenger> res = initDataPathEndPoint(clientId, pubSubId, peerHandle,
560                peerDiscoveryMac, inOrder, true);
561
562        // (1) request network
563        NetworkRequest nr;
564        if (useDirect) {
565            nr = getDirectNetworkRequest(clientId,
566                    WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER,
567                    provideMac ? peerDiscoveryMac : null, provideToken ? token : null);
568        } else {
569            nr = getSessionNetworkRequest(clientId, res.first, provideMac ? peerHandle : null,
570                    provideToken ? token : null, true);
571        }
572
573        Message reqNetworkMsg = Message.obtain();
574        reqNetworkMsg.what = NetworkFactory.CMD_REQUEST_NETWORK;
575        reqNetworkMsg.obj = nr;
576        reqNetworkMsg.arg1 = 0;
577        res.second.send(reqNetworkMsg);
578        mMockLooper.dispatchAll();
579
580        // (2) get request & respond
581        mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId, token.getBytes());
582        mMockLooper.dispatchAll();
583        inOrder.verify(mMockNative).respondToDataPathRequest(transactionId.capture(), eq(true),
584                eq(ndpId), eq("aware0"), eq(new byte[0]));
585        mDut.onRespondToDataPathSetupRequestResponse(transactionId.getValue(), true, 0);
586        mMockLooper.dispatchAll();
587
588        // (3) get confirmation OR timeout
589        if (getConfirmation) {
590            mDut.onDataPathConfirmNotification(ndpId, peerDataPathMac, true, 0,
591                    peerToken.getBytes());
592            mMockLooper.dispatchAll();
593            inOrder.verify(mMockCm).registerNetworkAgent(messengerCaptor.capture(),
594                    any(NetworkInfo.class), any(LinkProperties.class),
595                    any(NetworkCapabilities.class),
596                    anyInt(), any(NetworkMisc.class));
597        } else {
598            assertTrue(mAlarmManager.dispatch(
599                    WifiAwareStateManager.HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG));
600            mMockLooper.dispatchAll();
601            inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId));
602            mDut.onEndDataPathResponse(transactionId.getValue(), true, 0);
603            mMockLooper.dispatchAll();
604        }
605
606        // (4) end data-path (unless didn't get confirmation)
607        if (getConfirmation) {
608            Message endNetworkMsg = Message.obtain();
609            endNetworkMsg.what = NetworkFactory.CMD_CANCEL_REQUEST;
610            endNetworkMsg.obj = nr;
611            res.second.send(endNetworkMsg);
612
613            Message endNetworkUsageMsg = Message.obtain();
614            endNetworkUsageMsg.what = AsyncChannel.CMD_CHANNEL_DISCONNECTED;
615            messengerCaptor.getValue().send(endNetworkUsageMsg);
616
617            mMockLooper.dispatchAll();
618            inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId));
619            mDut.onEndDataPathResponse(transactionId.getValue(), true, 0);
620            mMockLooper.dispatchAll();
621        }
622
623        verifyNoMoreInteractions(mMockNative, mMockCm);
624    }
625
626    private void installDataPathStateManagerMocks() throws Exception {
627        Field field = WifiAwareStateManager.class.getDeclaredField("mDataPathMgr");
628        field.setAccessible(true);
629        Object mDataPathMgr = field.get(mDut);
630
631        field = WifiAwareDataPathStateManager.class.getDeclaredField("mNwService");
632        field.setAccessible(true);
633        field.set(mDataPathMgr, mMockNwMgt);
634
635        field = WifiAwareDataPathStateManager.class.getDeclaredField("mNiWrapper");
636        field.setAccessible(true);
637        field.set(mDataPathMgr, mMockNetworkInterface);
638    }
639
640    private NetworkRequest getSessionNetworkRequest(int clientId, int sessionId,
641            WifiAwareManager.PeerHandle peerHandle, String token, boolean doPublish)
642            throws Exception {
643        final WifiAwareManager mgr = new WifiAwareManager(mMockContext, mMockAwareService);
644        final ConfigRequest configRequest = new ConfigRequest.Builder().build();
645        final PublishConfig publishConfig = new PublishConfig.Builder().build();
646        final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
647
648        ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
649                WifiAwareSession.class);
650        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
651                .forClass(IWifiAwareEventCallback.class);
652        ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor
653                .forClass(IWifiAwareDiscoverySessionCallback.class);
654        ArgumentCaptor<WifiAwareDiscoveryBaseSession> discoverySession = ArgumentCaptor
655                .forClass(WifiAwareDiscoveryBaseSession.class);
656
657        WifiAwareAttachCallback mockCallback = mock(WifiAwareAttachCallback.class);
658        WifiAwareDiscoverySessionCallback mockSessionCallback = mock(
659                WifiAwareDiscoverySessionCallback.class);
660
661        mgr.attach(mMockLooperHandler, configRequest, mockCallback, null);
662        verify(mMockAwareService).connect(any(IBinder.class), anyString(),
663                clientProxyCallback.capture(), eq(configRequest), eq(false));
664        clientProxyCallback.getValue().onConnectSuccess(clientId);
665        mMockLooper.dispatchAll();
666        verify(mockCallback).onAttached(sessionCaptor.capture());
667        if (doPublish) {
668            sessionCaptor.getValue().publish(publishConfig, mockSessionCallback,
669                    mMockLooperHandler);
670            verify(mMockAwareService).publish(eq(clientId), eq(publishConfig),
671                    sessionProxyCallback.capture());
672        } else {
673            sessionCaptor.getValue().subscribe(subscribeConfig, mockSessionCallback,
674                    mMockLooperHandler);
675            verify(mMockAwareService).subscribe(eq(clientId), eq(subscribeConfig),
676                    sessionProxyCallback.capture());
677        }
678        sessionProxyCallback.getValue().onSessionStarted(sessionId);
679        mMockLooper.dispatchAll();
680        if (doPublish) {
681            verify(mockSessionCallback).onPublishStarted(
682                    (WifiAwarePublishDiscoverySession) discoverySession.capture());
683        } else {
684            verify(mockSessionCallback).onSubscribeStarted(
685                    (WifiAwareSubscribeDiscoverySession) discoverySession.capture());
686        }
687
688        String ns = discoverySession.getValue().createNetworkSpecifier(peerHandle,
689                (token == null) ? null : token.getBytes());
690
691        NetworkCapabilities nc = new NetworkCapabilities();
692        nc.clearAll();
693        nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE);
694        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN).addCapability(
695                NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
696        nc.setNetworkSpecifier(ns);
697        nc.setLinkUpstreamBandwidthKbps(1);
698        nc.setLinkDownstreamBandwidthKbps(1);
699        nc.setSignalStrength(1);
700
701        return new NetworkRequest(nc, 0, 0, NetworkRequest.Type.NONE);
702    }
703
704    private NetworkRequest getDirectNetworkRequest(int clientId, int role, byte[] peer,
705            String token) throws Exception {
706        final ConfigRequest configRequest = new ConfigRequest.Builder().build();
707        final WifiAwareManager mgr = new WifiAwareManager(mMockContext, mMockAwareService);
708
709        ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
710                WifiAwareSession.class);
711        ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
712                .forClass(IWifiAwareEventCallback.class);
713
714        WifiAwareAttachCallback mockCallback = mock(WifiAwareAttachCallback.class);
715
716        mgr.attach(mMockLooperHandler, configRequest, mockCallback, null);
717        verify(mMockAwareService).connect(any(IBinder.class), anyString(),
718                clientProxyCallback.capture(), eq(configRequest), eq(false));
719        clientProxyCallback.getValue().onConnectSuccess(clientId);
720        mMockLooper.dispatchAll();
721        verify(mockCallback).onAttached(sessionCaptor.capture());
722
723        String ns = sessionCaptor.getValue().createNetworkSpecifier(role, peer,
724                (token == null) ? null : token.getBytes());
725        NetworkCapabilities nc = new NetworkCapabilities();
726        nc.clearAll();
727        nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE);
728        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN).addCapability(
729                NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
730        nc.setNetworkSpecifier(ns);
731        nc.setLinkUpstreamBandwidthKbps(1);
732        nc.setLinkDownstreamBandwidthKbps(1);
733        nc.setSignalStrength(1);
734
735        return new NetworkRequest(nc, 0, 0, NetworkRequest.Type.REQUEST);
736    }
737
738    private Pair<Integer, Messenger> initDataPathEndPoint(int clientId, int pubSubId,
739            WifiAwareManager.PeerHandle peerHandle, byte[] peerDiscoveryMac, InOrder inOrder,
740            boolean doPublish)
741            throws Exception {
742        final int uid = 1000;
743        final int pid = 2000;
744        final String callingPackage = "com.android.somePackage";
745        final String someMsg = "some arbitrary message from peer";
746        final ConfigRequest configRequest = new ConfigRequest.Builder().build();
747        final PublishConfig publishConfig = new PublishConfig.Builder().build();
748        final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build();
749
750        WifiAwareNative.Capabilities capabilities = new WifiAwareNative.Capabilities();
751        capabilities.maxNdiInterfaces = 1;
752
753        ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class);
754        ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class);
755        ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class);
756        ArgumentCaptor<String> strCaptor = ArgumentCaptor.forClass(String.class);
757
758        // (0) start/registrations
759        inOrder.verify(mMockCm).registerNetworkFactory(messengerCaptor.capture(),
760                strCaptor.capture());
761        collector.checkThat("factory name", "WIFI_AWARE_FACTORY", equalTo(strCaptor.getValue()));
762
763        // (1) get capabilities
764        mDut.queryCapabilities();
765        mMockLooper.dispatchAll();
766        inOrder.verify(mMockNative).getCapabilities(transactionId.capture());
767        mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), capabilities);
768        mMockLooper.dispatchAll();
769
770        // (2) enable usage (creates interfaces)
771        mDut.enableUsage();
772        mMockLooper.dispatchAll();
773        inOrder.verify(mMockNative).deInitAware();
774        inOrder.verify(mMockNative).createAwareNetworkInterface(transactionId.capture(),
775                strCaptor.capture());
776        collector.checkThat("interface created -- 0", sAwareInterfacePrefix + 0,
777                equalTo(strCaptor.getValue()));
778        mDut.onCreateDataPathInterfaceResponse(transactionId.getValue(), true, 0);
779        mMockLooper.dispatchAll();
780
781        // (3) create client & session & rx message
782        mDut.connect(clientId, uid, pid, callingPackage, mMockCallback, configRequest, false);
783        mMockLooper.dispatchAll();
784        inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
785                eq(configRequest), eq(true));
786        mDut.onConfigSuccessResponse(transactionId.getValue());
787        mMockLooper.dispatchAll();
788        inOrder.verify(mMockCallback).onConnectSuccess(clientId);
789        if (doPublish) {
790            mDut.publish(clientId, publishConfig, mMockSessionCallback);
791        } else {
792            mDut.subscribe(clientId, subscribeConfig, mMockSessionCallback);
793        }
794        mMockLooper.dispatchAll();
795        if (doPublish) {
796            inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig));
797        } else {
798            inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0),
799                    eq(subscribeConfig));
800        }
801        mDut.onSessionConfigSuccessResponse(transactionId.getValue(), doPublish, pubSubId);
802        mMockLooper.dispatchAll();
803        inOrder.verify(mMockSessionCallback).onSessionStarted(sessionId.capture());
804        mDut.onMessageReceivedNotification(pubSubId, peerHandle.peerId, peerDiscoveryMac,
805                someMsg.getBytes());
806        mMockLooper.dispatchAll();
807        inOrder.verify(mMockSessionCallback).onMessageReceived(peerHandle.peerId,
808                someMsg.getBytes());
809
810        return new Pair<>(sessionId.getValue(), messengerCaptor.getValue());
811    }
812}
813