RttServiceTest.java revision f4267b6840dbc7f430638c35c5448187b6e83846
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;
18
19import static org.junit.Assert.assertEquals;
20import static org.mockito.Matchers.any;
21import static org.mockito.Matchers.anyInt;
22import static org.mockito.Mockito.atLeastOnce;
23import static org.mockito.Mockito.mock;
24import static org.mockito.Mockito.times;
25import static org.mockito.Mockito.validateMockitoUsage;
26import static org.mockito.Mockito.verify;
27import static org.mockito.Mockito.verifyNoMoreInteractions;
28import static org.mockito.Mockito.when;
29
30import android.content.BroadcastReceiver;
31import android.content.Context;
32import android.content.IntentFilter;
33import android.net.wifi.RttManager;
34import android.net.wifi.RttManager.ParcelableRttParams;
35import android.net.wifi.RttManager.ResponderConfig;
36import android.net.wifi.WifiManager;
37import android.os.Handler;
38import android.os.Message;
39import android.os.test.TestLooper;
40import android.test.suitebuilder.annotation.SmallTest;
41
42import com.android.internal.util.test.BidirectionalAsyncChannel;
43
44import org.junit.After;
45import org.junit.Before;
46import org.junit.Test;
47import org.mockito.ArgumentCaptor;
48import org.mockito.Mock;
49import org.mockito.MockitoAnnotations;
50
51/**
52 * Unit test for {@link com.android.server.wifi.RttService}
53 */
54@SmallTest
55public class RttServiceTest {
56
57    // Some constants for running Rtt tests.
58    private static final String MAC = "12:34:56:78:9A:BC";
59    private static final int CLIENT_KEY1 = 1;
60    private static final int CLIENT_KEY2 = 2;
61
62    @Mock
63    Context mContext;
64    @Mock
65    WifiNative mWifiNative;
66    TestLooper mLooper;
67
68    RttService.RttServiceImpl mRttServiceImpl;
69    ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor = ArgumentCaptor
70            .forClass(BroadcastReceiver.class);
71
72    @Before
73    public void setUp() throws Exception {
74        MockitoAnnotations.initMocks(this);
75        TestUtil.installWlanWifiNative(mWifiNative);
76        mLooper = new TestLooper();
77        mRttServiceImpl = new RttService.RttServiceImpl(mContext, mLooper.getLooper());
78        mRttServiceImpl.startService();
79    }
80
81    @After
82    public void cleanup() {
83        validateMockitoUsage();
84    }
85
86    private void startWifi() {
87        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
88                any(IntentFilter.class));
89        TestUtil.sendWifiScanAvailable(mBroadcastReceiverCaptor.getValue(),
90                mContext, WifiManager.WIFI_STATE_ENABLED);
91    }
92
93    // Create and connect a bi-directional async channel.
94    private BidirectionalAsyncChannel connectChannel(Handler handler) {
95        BidirectionalAsyncChannel channel = new BidirectionalAsyncChannel();
96        channel.connect(mLooper.getLooper(), mRttServiceImpl.getMessenger(),
97                handler);
98        mLooper.dispatchAll();
99        channel.assertConnected();
100        return channel;
101    }
102
103    private void sendRangingRequestFailed(BidirectionalAsyncChannel channel, Handler handler,
104            int clientKey, ParcelableRttParams params) {
105        Message message = sendRangingRequest(channel, handler, clientKey, params);
106        assertEquals("ranging request did not fail",
107                RttManager.CMD_OP_FAILED, message.what);
108        verifyNoMoreInteractions(mWifiNative);
109    }
110
111    // Send rtt ranging request message and verify failure.
112    private Message sendRangingRequest(BidirectionalAsyncChannel channel, Handler handler,
113            int clientKey, ParcelableRttParams params) {
114        Message message = new Message();
115        message.what = RttManager.CMD_OP_START_RANGING;
116        message.arg2 = clientKey;
117        message.obj = params;
118        channel.sendMessage(message);
119        mLooper.dispatchAll();
120        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
121        verify(handler, atLeastOnce()).handleMessage(messageCaptor.capture());
122        return messageCaptor.getValue();
123    }
124
125    // Send enable responder message and verify success.
126    private void sendEnableResponderSucceed(BidirectionalAsyncChannel channel,
127            Handler handler, int clientKey) {
128        Message message = sendEnableResponder(channel, handler, clientKey,
129                createResponderConfig());
130        verify(mWifiNative).enableRttResponder(anyInt());
131        assertEquals("reponse status is not success",
132                RttManager.CMD_OP_ENALBE_RESPONDER_SUCCEEDED, message.what);
133        String actualMac = ((ResponderConfig) message.obj).macAddress;
134        assertEquals("mac address mismatch", MAC, actualMac);
135    }
136
137    // Send enable responder message and verify failure.
138    private void sendEnableResponderFailed(BidirectionalAsyncChannel channel,
139            Handler handler, int clientKey, int reason) {
140        Message message = sendEnableResponder(channel, handler, clientKey, null);
141        assertEquals("reponse status is not failure",
142                RttManager.CMD_OP_ENALBE_RESPONDER_FAILED, message.what);
143        assertEquals("failure reason is not " + reason,
144                reason, message.arg1);
145    }
146
147    private Message sendEnableResponder(BidirectionalAsyncChannel channel, Handler handler,
148            int clientKey, ResponderConfig config) {
149        when(mWifiNative.enableRttResponder(anyInt())).thenReturn(config);
150        when(mWifiNative.getMacAddress()).thenReturn(MAC);
151        Message message = new Message();
152        message.what = RttManager.CMD_OP_ENABLE_RESPONDER;
153        message.arg2 = clientKey;
154        channel.sendMessage(message);
155        mLooper.dispatchAll();
156        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
157        verify(handler, atLeastOnce()).handleMessage(messageCaptor.capture());
158        return messageCaptor.getValue();
159    }
160
161    private void sendDisableResponder(BidirectionalAsyncChannel channel, int key, boolean success) {
162        when(mWifiNative.disableRttResponder()).thenReturn(success);
163        Message message = new Message();
164        message.what = RttManager.CMD_OP_DISABLE_RESPONDER;
165        message.arg2 = key;
166        channel.sendMessage(message);
167        mLooper.dispatchAll();
168    }
169
170    private ResponderConfig createResponderConfig() {
171        ResponderConfig config = new ResponderConfig();
172        config.macAddress = MAC;
173        return config;
174    }
175
176    @Test
177    public void testEnableResponderSuccess() throws Exception {
178        startWifi();
179        Handler handler = mock(Handler.class);
180        BidirectionalAsyncChannel channel = connectChannel(handler);
181        // Successfully enabled responder.
182        sendEnableResponderSucceed(channel, handler, CLIENT_KEY1);
183    }
184
185    @Test
186    public void testEnableResponderSecondTime() throws Exception {
187        startWifi();
188        Handler handler = mock(Handler.class);
189        BidirectionalAsyncChannel channel = connectChannel(handler);
190        sendEnableResponderSucceed(channel, handler, CLIENT_KEY1);
191        // Calling enabling responder with the same key should succeed.
192        sendEnableResponderSucceed(channel, handler, CLIENT_KEY1);
193    }
194
195    @Test
196    public void testEnableResponderMultiClient() throws Exception {
197        startWifi();
198        Handler handler = mock(Handler.class);
199        BidirectionalAsyncChannel channel = connectChannel(handler);
200        sendEnableResponderSucceed(channel, handler, CLIENT_KEY1);
201        sendEnableResponderSucceed(channel, handler, CLIENT_KEY2);
202        // Native method should be called only once when multiple clients enabled responder.
203        verify(mWifiNative, times(1)).enableRttResponder(anyInt());
204    }
205
206    @Test
207    public void testDisableResponderSuccess() throws Exception {
208        startWifi();
209        Handler handler = mock(Handler.class);
210        BidirectionalAsyncChannel channel = connectChannel(handler);
211        sendEnableResponderSucceed(channel, handler, CLIENT_KEY1);
212        // Disable after successfully enabling.
213        sendDisableResponder(channel, CLIENT_KEY1, false);
214        verify(mWifiNative).disableRttResponder();
215    }
216
217    /**
218     * Enable responder failed because of internal error.
219     */
220    @Test
221    public void testEnableResponderFailure() throws Exception {
222        startWifi();
223        Handler handler = mock(Handler.class);
224        when(mWifiNative.enableRttResponder(anyInt())).thenReturn(null);
225        BidirectionalAsyncChannel channel = connectChannel(handler);
226        // Disable failed.
227        sendEnableResponderFailed(channel, handler, CLIENT_KEY1, RttManager.REASON_UNSPECIFIED);
228    }
229
230    @Test
231    public void testDisableResponderNotStarted() throws Exception {
232        startWifi();
233        Handler handler = mock(Handler.class);
234        BidirectionalAsyncChannel channel = connectChannel(handler);
235        // Disable without enabling should fail.
236        sendDisableResponder(channel, CLIENT_KEY1, false);
237        // Native disable method shouldn't be called.
238        verifyNoMoreInteractions(mWifiNative);
239    }
240
241    @Test
242    public void testDisableResponderMultiClient() throws Exception {
243        startWifi();
244        Handler handler = mock(Handler.class);
245        BidirectionalAsyncChannel channel = connectChannel(handler);
246        sendEnableResponderSucceed(channel, handler, CLIENT_KEY1);
247        sendEnableResponderSucceed(channel, handler, CLIENT_KEY2);
248        // Two clients enabled, one client disabled.
249        sendDisableResponder(channel, CLIENT_KEY1, true);
250        verify(mWifiNative, times(1)).getMacAddress();
251        verifyNoMoreInteractions(mWifiNative);
252    }
253
254    /**
255     * Enable responder failed because wifi is not enabled.
256     */
257    @Test
258    public void testEnableResponderFailedWifiDisabled() throws Exception {
259        Handler handler = mock(Handler.class);
260        BidirectionalAsyncChannel channel = connectChannel(handler);
261        // Wifi is disabled as startWifi() is not invoked.
262        sendEnableResponderFailed(channel, handler, CLIENT_KEY1, RttManager.REASON_NOT_AVAILABLE);
263        verifyNoMoreInteractions(mWifiNative);
264    }
265
266    /**
267     * Test RTT ranging with empty RttParams.
268     */
269    @Test
270    public void testInitiatorEmptyParams() throws Exception {
271        startWifi();
272        Handler handler = mock(Handler.class);
273        BidirectionalAsyncChannel channel = connectChannel(handler);
274        sendRangingRequestFailed(channel, handler, CLIENT_KEY1, new ParcelableRttParams(null));
275    }
276}
277