WifiScanningServiceTest.java revision a8367288377cbaed6371256ca837b7aa22280706
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.scanner;
18
19import static com.android.server.wifi.ScanTestUtil.*;
20
21import static org.junit.Assert.*;
22import static org.mockito.Mockito.*;
23
24import android.content.BroadcastReceiver;
25import android.content.Context;
26import android.content.IntentFilter;
27import android.net.wifi.ScanResult;
28import android.net.wifi.WifiManager;
29import android.net.wifi.WifiScanner;
30import android.os.Bundle;
31import android.os.Handler;
32import android.os.Looper;
33import android.os.Message;
34import android.os.WorkSource;
35import android.test.suitebuilder.annotation.SmallTest;
36import android.util.Pair;
37
38import com.android.internal.app.IBatteryStats;
39import com.android.internal.util.Protocol;
40import com.android.server.wifi.BidirectionalAsyncChannel;
41import com.android.server.wifi.MockAlarmManager;
42import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
43import com.android.server.wifi.MockLooper;
44import com.android.server.wifi.ScanResults;
45import com.android.server.wifi.TestUtil;
46import com.android.server.wifi.WifiInjector;
47import com.android.server.wifi.WifiMetrics;
48import com.android.server.wifi.WifiMetricsProto;
49import com.android.server.wifi.WifiNative;
50
51import org.junit.After;
52import org.junit.Before;
53import org.junit.Test;
54import org.mockito.ArgumentCaptor;
55import org.mockito.InOrder;
56import org.mockito.Mock;
57import org.mockito.MockitoAnnotations;
58import org.mockito.internal.matchers.CapturingMatcher;
59
60import java.util.ArrayList;
61import java.util.Arrays;
62import java.util.Collections;
63
64/**
65 * Unit tests for {@link com.android.server.wifi.scanner.WifiScanningServiceImpl}.
66 */
67@SmallTest
68public class WifiScanningServiceTest {
69    public static final String TAG = "WifiScanningServiceTest";
70
71    @Mock Context mContext;
72    MockAlarmManager mAlarmManager;
73    @Mock WifiScannerImpl mWifiScannerImpl;
74    @Mock WifiScannerImpl.WifiScannerImplFactory mWifiScannerImplFactory;
75    @Mock IBatteryStats mBatteryStats;
76    @Mock WifiInjector mWifiInjector;
77    WifiMetrics mWifiMetrics;
78    MockLooper mLooper;
79    WifiScanningServiceImpl mWifiScanningServiceImpl;
80
81
82    @Before
83    public void setUp() throws Exception {
84        MockitoAnnotations.initMocks(this);
85
86        mAlarmManager = new MockAlarmManager();
87        when(mContext.getSystemService(Context.ALARM_SERVICE))
88                .thenReturn(mAlarmManager.getAlarmManager());
89        mWifiMetrics = new WifiMetrics();
90
91        ChannelHelper channelHelper = new PresetKnownBandsChannelHelper(
92                new int[]{2400, 2450},
93                new int[]{5150, 5175},
94                new int[]{5600, 5650, 5660});
95
96        mLooper = new MockLooper();
97        when(mWifiScannerImplFactory.create(any(Context.class), any(Looper.class)))
98                .thenReturn(mWifiScannerImpl);
99        when(mWifiScannerImpl.getChannelHelper()).thenReturn(channelHelper);
100        when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
101        mWifiScanningServiceImpl = new WifiScanningServiceImpl(mContext, mLooper.getLooper(),
102                mWifiScannerImplFactory, mBatteryStats, mWifiInjector);
103    }
104
105    @After
106    public void cleanup() {
107        validateMockitoUsage();
108    }
109
110    /**
111     * Internal BroadcastReceiver that WifiScanningServiceImpl uses to listen for broadcasts
112     * this is initialized by calling startServiceAndLoadDriver
113     */
114    BroadcastReceiver mBroadcastReceiver;
115
116    private WifiScanner.ScanSettings generateValidScanSettings() {
117        return createRequest(WifiScanner.WIFI_BAND_BOTH, 30000, 0, 20,
118                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
119    }
120
121    private BidirectionalAsyncChannel connectChannel(Handler handler) {
122        BidirectionalAsyncChannel controlChannel = new BidirectionalAsyncChannel();
123        controlChannel.connect(mLooper.getLooper(), mWifiScanningServiceImpl.getMessenger(),
124                handler);
125        mLooper.dispatchAll();
126        controlChannel.assertConnected();
127        return controlChannel;
128    }
129
130    private Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler) {
131        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
132        order.verify(handler).handleMessage(messageCaptor.capture());
133        return messageCaptor.getValue();
134    }
135
136    private Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler,
137            final int what) {
138        CapturingMatcher<Message> messageMatcher = new CapturingMatcher<Message>() {
139            public boolean matches(Object argument) {
140                Message message = (Message) argument;
141                return message.what == what;
142            }
143        };
144        order.verify(handler).handleMessage(argThat(messageMatcher));
145        return messageMatcher.getLastValue();
146    }
147
148    private void verifyScanResultsRecieved(InOrder order, Handler handler, int listenerId,
149            WifiScanner.ScanData... expected) {
150        Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler,
151                WifiScanner.CMD_SCAN_RESULT);
152        assertScanResultsMessage(listenerId, expected, scanResultMessage);
153    }
154
155    private void assertScanResultsMessage(int listenerId, WifiScanner.ScanData[] expected,
156            Message scanResultMessage) {
157        assertEquals("what", WifiScanner.CMD_SCAN_RESULT, scanResultMessage.what);
158        assertEquals("listenerId", listenerId, scanResultMessage.arg2);
159        assertScanDatasEquals(expected,
160                ((WifiScanner.ParcelableScanData) scanResultMessage.obj).getResults());
161    }
162
163    private void verifySingleScanCompletedRecieved(InOrder order, Handler handler, int listenerId) {
164        Message completedMessage = verifyHandleMessageAndGetMessage(order, handler,
165                WifiScanner.CMD_SINGLE_SCAN_COMPLETED);
166        assertSingleScanCompletedMessage(listenerId, completedMessage);
167    }
168
169    private void assertSingleScanCompletedMessage(int listenerId, Message completedMessage) {
170        assertEquals("what", WifiScanner.CMD_SINGLE_SCAN_COMPLETED, completedMessage.what);
171        assertEquals("listenerId", listenerId, completedMessage.arg2);
172    }
173
174    private void sendBackgroundScanRequest(BidirectionalAsyncChannel controlChannel,
175            int scanRequestId, WifiScanner.ScanSettings settings, WorkSource workSource) {
176        Bundle scanParams = new Bundle();
177        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
178        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
179        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_BACKGROUND_SCAN, 0,
180                        scanRequestId, scanParams));
181    }
182
183    private void sendSingleScanRequest(BidirectionalAsyncChannel controlChannel,
184            int scanRequestId, WifiScanner.ScanSettings settings, WorkSource workSource) {
185        Bundle scanParams = new Bundle();
186        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
187        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
188        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_SINGLE_SCAN, 0,
189                        scanRequestId, scanParams));
190    }
191
192    private void verifySuccessfulResponse(InOrder order, Handler handler, int arg2) {
193        Message response = verifyHandleMessageAndGetMessage(order, handler);
194        assertSuccessfulResponse(arg2, response);
195    }
196
197    private void assertSuccessfulResponse(int arg2, Message response) {
198        if (response.what == WifiScanner.CMD_OP_FAILED) {
199            WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj;
200            fail("response indicates failure, reason=" + result.reason
201                    + ", description=" + result.description);
202        } else {
203            assertEquals("response.what", WifiScanner.CMD_OP_SUCCEEDED, response.what);
204            assertEquals("response.arg2", arg2, response.arg2);
205        }
206    }
207
208    private void verifyFailedResponse(InOrder order, Handler handler, int arg2,
209            int expectedErrorReason, String expectedErrorDescription) {
210        Message response = verifyHandleMessageAndGetMessage(order, handler);
211        assertFailedResponse(arg2, expectedErrorReason, expectedErrorDescription, response);
212    }
213
214    private void assertFailedResponse(int arg2, int expectedErrorReason,
215            String expectedErrorDescription, Message response) {
216        if (response.what == WifiScanner.CMD_OP_SUCCEEDED) {
217            fail("response indicates success");
218        } else {
219            assertEquals("response.what", WifiScanner.CMD_OP_FAILED, response.what);
220            assertEquals("response.arg2", arg2, response.arg2);
221            WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj;
222            assertEquals("response.obj.reason",
223                    expectedErrorReason, result.reason);
224            assertEquals("response.obj.description",
225                    expectedErrorDescription, result.description);
226        }
227    }
228
229    private WifiNative.ScanEventHandler verifyStartSingleScan(InOrder order,
230            WifiNative.ScanSettings expected) {
231        ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor =
232                ArgumentCaptor.forClass(WifiNative.ScanSettings.class);
233        ArgumentCaptor<WifiNative.ScanEventHandler> scanEventHandlerCaptor =
234                ArgumentCaptor.forClass(WifiNative.ScanEventHandler.class);
235        order.verify(mWifiScannerImpl).startSingleScan(scanSettingsCaptor.capture(),
236                scanEventHandlerCaptor.capture());
237        assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue());
238        return scanEventHandlerCaptor.getValue();
239    }
240
241    private WifiNative.ScanEventHandler verifyStartBackgroundScan(InOrder order,
242            WifiNative.ScanSettings expected) {
243        ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor =
244                ArgumentCaptor.forClass(WifiNative.ScanSettings.class);
245        ArgumentCaptor<WifiNative.ScanEventHandler> scanEventHandlerCaptor =
246                ArgumentCaptor.forClass(WifiNative.ScanEventHandler.class);
247        order.verify(mWifiScannerImpl).startBatchedScan(scanSettingsCaptor.capture(),
248                scanEventHandlerCaptor.capture());
249        assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue());
250        return scanEventHandlerCaptor.getValue();
251    }
252
253    private static final int MAX_AP_PER_SCAN = 16;
254    private void startServiceAndLoadDriver() {
255        mWifiScanningServiceImpl.startService();
256        when(mWifiScannerImpl.getScanCapabilities(any(WifiNative.ScanCapabilities.class)))
257                .thenAnswer(new AnswerWithArguments() {
258                        public boolean answer(WifiNative.ScanCapabilities capabilities) {
259                            capabilities.max_scan_cache_size = Integer.MAX_VALUE;
260                            capabilities.max_scan_buckets = 8;
261                            capabilities.max_ap_cache_per_scan = MAX_AP_PER_SCAN;
262                            capabilities.max_rssi_sample_size = 8;
263                            capabilities.max_scan_reporting_threshold = 10;
264                            capabilities.max_hotlist_bssids = 0;
265                            capabilities.max_significant_wifi_change_aps = 0;
266                            return true;
267                        }
268                    });
269        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
270                ArgumentCaptor.forClass(BroadcastReceiver.class);
271        verify(mContext)
272                .registerReceiver(broadcastReceiverCaptor.capture(), any(IntentFilter.class));
273        mBroadcastReceiver = broadcastReceiverCaptor.getValue();
274        TestUtil.sendWifiScanAvailable(broadcastReceiverCaptor.getValue(), mContext,
275                WifiManager.WIFI_STATE_ENABLED);
276        mLooper.dispatchAll();
277    }
278
279    @Test
280    public void construct() throws Exception {
281        verifyNoMoreInteractions(mWifiScannerImpl, mWifiScannerImpl,
282                mWifiScannerImplFactory, mBatteryStats);
283    }
284
285    @Test
286    public void startService() throws Exception {
287        mWifiScanningServiceImpl.startService();
288        verifyNoMoreInteractions(mWifiScannerImplFactory);
289
290        Handler handler = mock(Handler.class);
291        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
292        InOrder order = inOrder(handler);
293        sendBackgroundScanRequest(controlChannel, 122, generateValidScanSettings(), null);
294        mLooper.dispatchAll();
295        verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available");
296    }
297
298    @Test
299    public void loadDriver() throws Exception {
300        startServiceAndLoadDriver();
301        verify(mWifiScannerImplFactory, times(1)).create(any(Context.class), any(Looper.class));
302
303        Handler handler = mock(Handler.class);
304        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
305        InOrder order = inOrder(handler);
306        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
307                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
308        sendBackgroundScanRequest(controlChannel, 192, generateValidScanSettings(), null);
309        mLooper.dispatchAll();
310        verifySuccessfulResponse(order, handler, 192);
311    }
312
313    @Test
314    public void sendInvalidCommand() throws Exception {
315        startServiceAndLoadDriver();
316
317        Handler handler = mock(Handler.class);
318        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
319        InOrder order = inOrder(handler, mWifiScannerImpl);
320        controlChannel.sendMessage(Message.obtain(null, Protocol.BASE_WIFI_MANAGER));
321        mLooper.dispatchAll();
322        verifyFailedResponse(order, handler, 0, WifiScanner.REASON_INVALID_REQUEST,
323                "Invalid request");
324    }
325
326    private void doSuccessfulSingleScan(WifiScanner.ScanSettings requestSettings,
327            WifiNative.ScanSettings nativeSettings, ScanResults results) {
328        int requestId = 12;
329        startServiceAndLoadDriver();
330
331        Handler handler = mock(Handler.class);
332        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
333        InOrder order = inOrder(handler, mWifiScannerImpl);
334
335        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
336                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
337
338        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
339
340        mLooper.dispatchAll();
341        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings);
342        verifySuccessfulResponse(order, handler, requestId);
343
344        when(mWifiScannerImpl.getLatestSingleScanResults())
345                .thenReturn(results.getScanData());
346        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
347
348        mLooper.dispatchAll();
349        verifyScanResultsRecieved(order, handler, requestId, results.getScanData());
350        verifySingleScanCompletedRecieved(order, handler, requestId);
351        verifyNoMoreInteractions(handler);
352    }
353
354    /**
355     * Do a single scan for a band and verify that it is successful.
356     */
357    @Test
358    public void sendSingleScanBandRequest() throws Exception {
359        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
360                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
361        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
362                ScanResults.create(0, 2400, 5150, 5175));
363    }
364
365    /**
366     * Do a single scan for a list of channels and verify that it is successful.
367     */
368    @Test
369    public void sendSingleScanChannelsRequest() throws Exception {
370        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
371                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
372        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
373                ScanResults.create(0, 2400, 5150, 5175));
374    }
375
376    /**
377     * Do a single scan, which the hardware fails to start, and verify that a failure response is
378     * delivered.
379     */
380    @Test
381    public void sendSingleScanRequestWhichFailsToStart() throws Exception {
382        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
383                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
384        int requestId = 33;
385
386        startServiceAndLoadDriver();
387
388        Handler handler = mock(Handler.class);
389        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
390        InOrder order = inOrder(handler, mWifiScannerImpl);
391
392        // scan fails
393        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
394                        any(WifiNative.ScanEventHandler.class))).thenReturn(false);
395
396        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
397
398        mLooper.dispatchAll();
399        // Scan is successfully queue, but then fails to execute
400        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
401        order.verify(handler, times(2)).handleMessage(messageCaptor.capture());
402        assertSuccessfulResponse(requestId, messageCaptor.getAllValues().get(0));
403        assertFailedResponse(requestId, WifiScanner.REASON_UNSPECIFIED,
404                "Failed to start single scan", messageCaptor.getAllValues().get(1));
405
406        assertEquals(mWifiMetrics.getOneshotScanCount(), 1);
407        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1);
408    }
409
410    /**
411     * Do a single scan, which successfully starts, but fails partway through and verify that a
412     * failure response is delivered.
413     */
414    @Test
415    public void sendSingleScanRequestWhichFailsAfterStart() throws Exception {
416        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
417                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
418        int requestId = 33;
419
420        startServiceAndLoadDriver();
421
422        Handler handler = mock(Handler.class);
423        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
424        InOrder order = inOrder(handler, mWifiScannerImpl);
425
426        // successful start
427        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
428                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
429
430        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
431
432        // Scan is successfully queue
433        mLooper.dispatchAll();
434        WifiNative.ScanEventHandler eventHandler =
435                verifyStartSingleScan(order, computeSingleScanNativeSettings(requestSettings));
436        verifySuccessfulResponse(order, handler, requestId);
437
438        // but then fails to execute
439        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_FAILED);
440        mLooper.dispatchAll();
441        verifyFailedResponse(order, handler, requestId,
442                WifiScanner.REASON_UNSPECIFIED, "Scan failed");
443        assertEquals(mWifiMetrics.getOneshotScanCount(), 1);
444        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1);
445    }
446
447    // TODO Add more single scan tests
448    // * disable wifi while scanning
449    // * disable wifi while scanning with pending scan
450
451    /**
452     * Send a single scan request and then a second one after the first completes.
453     */
454    @Test
455    public void sendSingleScanRequestAfterPreviousCompletes() {
456        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
457                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
458        int requestId1 = 12;
459        ScanResults results1 = ScanResults.create(0, 2400);
460
461
462        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
463                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
464        int requestId2 = 13;
465        ScanResults results2 = ScanResults.create(0, 2450);
466
467
468        startServiceAndLoadDriver();
469
470        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
471                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
472
473        Handler handler = mock(Handler.class);
474        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
475        InOrder order = inOrder(handler, mWifiScannerImpl);
476
477        // Run scan 1
478        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
479
480        mLooper.dispatchAll();
481        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(order,
482                computeSingleScanNativeSettings(requestSettings1));
483        verifySuccessfulResponse(order, handler, requestId1);
484
485        // dispatch scan 1 results
486        when(mWifiScannerImpl.getLatestSingleScanResults())
487                .thenReturn(results1.getScanData());
488        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
489
490        mLooper.dispatchAll();
491        verifyScanResultsRecieved(order, handler, requestId1, results1.getScanData());
492        verifySingleScanCompletedRecieved(order, handler, requestId1);
493
494        // Run scan 2
495        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
496
497        mLooper.dispatchAll();
498        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(order,
499                computeSingleScanNativeSettings(requestSettings2));
500        verifySuccessfulResponse(order, handler, requestId2);
501
502        // dispatch scan 2 results
503        when(mWifiScannerImpl.getLatestSingleScanResults())
504                .thenReturn(results2.getScanData());
505        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
506
507        mLooper.dispatchAll();
508        verifyScanResultsRecieved(order, handler, requestId2, results2.getScanData());
509        verifySingleScanCompletedRecieved(order, handler, requestId2);
510    }
511
512    /**
513     * Send a single scan request and then a second one before the first completes.
514     * Verify that both are scheduled and succeed.
515     */
516    @Test
517    public void sendSingleScanRequestWhilePreviousScanRunning() {
518        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
519                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
520        int requestId1 = 12;
521        ScanResults results1 = ScanResults.create(0, 2400);
522
523        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
524                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
525        int requestId2 = 13;
526        ScanResults results2 = ScanResults.create(0, 2450);
527
528
529        startServiceAndLoadDriver();
530
531        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
532                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
533
534        Handler handler = mock(Handler.class);
535        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
536        InOrder handlerOrder = inOrder(handler);
537        InOrder nativeOrder = inOrder(mWifiScannerImpl);
538
539        // Run scan 1
540        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
541
542        mLooper.dispatchAll();
543        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
544                computeSingleScanNativeSettings(requestSettings1));
545        verifySuccessfulResponse(handlerOrder, handler, requestId1);
546
547        // Queue scan 2 (will not run because previous is in progress)
548        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
549        mLooper.dispatchAll();
550        verifySuccessfulResponse(handlerOrder, handler, requestId2);
551
552        // dispatch scan 1 results
553        when(mWifiScannerImpl.getLatestSingleScanResults())
554                .thenReturn(results1.getScanData());
555        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
556
557        mLooper.dispatchAll();
558        verifyScanResultsRecieved(handlerOrder, handler, requestId1, results1.getScanData());
559        verifySingleScanCompletedRecieved(handlerOrder, handler, requestId1);
560
561        // now that the first scan completed we expect the second one to start
562        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(nativeOrder,
563                computeSingleScanNativeSettings(requestSettings2));
564
565        // dispatch scan 2 results
566        when(mWifiScannerImpl.getLatestSingleScanResults())
567                .thenReturn(results2.getScanData());
568        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
569
570        mLooper.dispatchAll();
571        verifyScanResultsRecieved(handlerOrder, handler, requestId2, results2.getScanData());
572        verifySingleScanCompletedRecieved(handlerOrder, handler, requestId2);
573        assertEquals(mWifiMetrics.getOneshotScanCount(), 2);
574        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 2);
575    }
576
577
578    /**
579     * Send a single scan request and then two more before the first completes.
580     * Verify that the first completes and the second two are merged.
581     */
582    @Test
583    public void sendMultipleSingleScanRequestWhilePreviousScanRunning() {
584        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
585                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
586        int requestId1 = 12;
587        ScanResults results1 = ScanResults.create(0, 2400);
588
589        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
590                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
591        int requestId2 = 13;
592        ScanResults results2 = ScanResults.create(0, 2450, 5175, 2450);
593
594        WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(5150), 0,
595                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
596        int requestId3 = 15;
597        ScanResults results3 = ScanResults.create(0, 5150, 5150, 5150, 5150);
598
599        WifiNative.ScanSettings nativeSettings2and3 = createSingleScanNativeSettingsForChannels(
600                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, channelsToSpec(2450, 5175, 5150));
601        ScanResults results2and3 = ScanResults.merge(results2, results3);
602
603
604        startServiceAndLoadDriver();
605
606        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
607                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
608
609        Handler handler = mock(Handler.class);
610        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
611        InOrder handlerOrder = inOrder(handler);
612        InOrder nativeOrder = inOrder(mWifiScannerImpl);
613
614        // Run scan 1
615        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
616
617        mLooper.dispatchAll();
618        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
619                computeSingleScanNativeSettings(requestSettings1));
620        verifySuccessfulResponse(handlerOrder, handler, requestId1);
621
622        // Queue scan 2 (will not run because previous is in progress)
623        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
624        mLooper.dispatchAll();
625        verifySuccessfulResponse(handlerOrder, handler, requestId2);
626
627        // Queue scan 3 (will not run because previous is in progress)
628        sendSingleScanRequest(controlChannel, requestId3, requestSettings3, null);
629        mLooper.dispatchAll();
630        verifySuccessfulResponse(handlerOrder, handler, requestId3);
631
632        // dispatch scan 1 results
633        when(mWifiScannerImpl.getLatestSingleScanResults())
634                .thenReturn(results1.getScanData());
635        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
636
637        mLooper.dispatchAll();
638        verifyScanResultsRecieved(handlerOrder, handler, requestId1, results1.getScanData());
639        verifySingleScanCompletedRecieved(handlerOrder, handler, requestId1);
640
641        // now that the first scan completed we expect the second and third ones to start
642        WifiNative.ScanEventHandler eventHandler2and3 = verifyStartSingleScan(nativeOrder,
643                nativeSettings2and3);
644
645        // dispatch scan 2 and 3 results
646        when(mWifiScannerImpl.getLatestSingleScanResults())
647                .thenReturn(results2and3.getScanData());
648        eventHandler2and3.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
649
650        mLooper.dispatchAll();
651
652        // unfortunatally the order that these events are dispatched is dependant on the order which
653        // they are iterated through internally
654        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
655        handlerOrder.verify(handler, times(4)).handleMessage(messageCaptor.capture());
656        int firstListenerId = messageCaptor.getAllValues().get(0).arg2;
657        assertTrue(firstListenerId + " was neither " + requestId2 + " nor " + requestId3,
658                firstListenerId == requestId2 || firstListenerId == requestId3);
659        if (firstListenerId == requestId2) {
660            assertScanResultsMessage(requestId2,
661                    new WifiScanner.ScanData[] {results2.getScanData()},
662                    messageCaptor.getAllValues().get(0));
663            assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(1));
664            assertScanResultsMessage(requestId3,
665                    new WifiScanner.ScanData[] {results3.getScanData()},
666                    messageCaptor.getAllValues().get(2));
667            assertSingleScanCompletedMessage(requestId3, messageCaptor.getAllValues().get(3));
668        } else {
669            assertScanResultsMessage(requestId3,
670                    new WifiScanner.ScanData[] {results3.getScanData()},
671                    messageCaptor.getAllValues().get(0));
672            assertSingleScanCompletedMessage(requestId3, messageCaptor.getAllValues().get(1));
673            assertScanResultsMessage(requestId2,
674                    new WifiScanner.ScanData[] {results2.getScanData()},
675                    messageCaptor.getAllValues().get(2));
676            assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(3));
677        }
678        assertEquals(mWifiMetrics.getOneshotScanCount(), 3);
679        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 3);
680    }
681
682    private void doSuccessfulBackgroundScan(WifiScanner.ScanSettings requestSettings,
683            WifiNative.ScanSettings nativeSettings) {
684        startServiceAndLoadDriver();
685
686        Handler handler = mock(Handler.class);
687        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
688        InOrder order = inOrder(handler, mWifiScannerImpl);
689
690        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
691                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
692
693        sendBackgroundScanRequest(controlChannel, 12, requestSettings, null);
694        mLooper.dispatchAll();
695        verifyStartBackgroundScan(order, nativeSettings);
696        verifySuccessfulResponse(order, handler, 12);
697        verifyNoMoreInteractions(handler);
698    }
699
700    /**
701     * Do a background scan for a band and verify that it is successful.
702     */
703    @Test
704    public void sendBackgroundScanBandRequest() throws Exception {
705        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 20000,
706                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
707        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
708                .withBasePeriod(20000)
709                .withMaxApPerScan(MAX_AP_PER_SCAN)
710                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
711                .addBucketWithBand(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
712                        WifiScanner.WIFI_BAND_BOTH)
713                .build();
714        doSuccessfulBackgroundScan(requestSettings, nativeSettings);
715        assertEquals(mWifiMetrics.getBackgroundScanCount(), 1);
716    }
717
718    /**
719     * Do a background scan for a list of channels and verify that it is successful.
720     */
721    @Test
722    public void sendBackgroundScanChannelsRequest() throws Exception {
723        WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(5150), 20000,
724                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
725        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
726                .withBasePeriod(20000)
727                .withMaxApPerScan(MAX_AP_PER_SCAN)
728                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
729                .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5150)
730                .build();
731        doSuccessfulBackgroundScan(requestSettings, nativeSettings);
732    }
733
734    private Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> createScanSettingsForHwPno()
735            throws Exception {
736        WifiScanner.ScanSettings requestSettings = createRequest(
737                channelsToSpec(0, 2400, 5150, 5175), 20000, 0, 20,
738                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
739        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
740                .withBasePeriod(20000)
741                .withMaxApPerScan(MAX_AP_PER_SCAN)
742                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
743                .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
744                        0, 2400, 5150, 5175)
745                .build();
746        return Pair.create(requestSettings, nativeSettings);
747    }
748
749    private Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> createScanSettingsForSwPno()
750            throws Exception {
751        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> settingsPair =
752                createScanSettingsForHwPno();
753
754        WifiScanner.ScanSettings requestSettings = settingsPair.first;
755        WifiNative.ScanSettings nativeSettings = settingsPair.second;
756        // reportEvents field is overridden for SW PNO
757        for (int i = 0; i < nativeSettings.buckets.length; i++) {
758            nativeSettings.buckets[i].report_events = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
759                    | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
760        }
761        return Pair.create(requestSettings, nativeSettings);
762    }
763
764    private Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> createPnoSettings(
765            ScanResults results)
766            throws Exception {
767        WifiScanner.PnoSettings requestPnoSettings = new WifiScanner.PnoSettings();
768        requestPnoSettings.networkList =
769                new WifiScanner.PnoSettings.PnoNetwork[results.getRawScanResults().length];
770        int i = 0;
771        for (ScanResult scanResult : results.getRawScanResults()) {
772            requestPnoSettings.networkList[i++] =
773                    new WifiScanner.PnoSettings.PnoNetwork(scanResult.SSID);
774        }
775
776        WifiNative.PnoSettings nativePnoSettings = new WifiNative.PnoSettings();
777        nativePnoSettings.min5GHzRssi = requestPnoSettings.min5GHzRssi;
778        nativePnoSettings.min24GHzRssi = requestPnoSettings.min24GHzRssi;
779        nativePnoSettings.initialScoreMax = requestPnoSettings.initialScoreMax;
780        nativePnoSettings.currentConnectionBonus = requestPnoSettings.currentConnectionBonus;
781        nativePnoSettings.sameNetworkBonus = requestPnoSettings.sameNetworkBonus;
782        nativePnoSettings.secureBonus = requestPnoSettings.secureBonus;
783        nativePnoSettings.band5GHzBonus = requestPnoSettings.band5GHzBonus;
784        nativePnoSettings.isConnected = requestPnoSettings.isConnected;
785        nativePnoSettings.networkList =
786                new WifiNative.PnoNetwork[requestPnoSettings.networkList.length];
787        for (i = 0; i < requestPnoSettings.networkList.length; i++) {
788            nativePnoSettings.networkList[i] = new WifiNative.PnoNetwork();
789            nativePnoSettings.networkList[i].ssid = requestPnoSettings.networkList[i].ssid;
790            nativePnoSettings.networkList[i].networkId =
791                    requestPnoSettings.networkList[i].networkId;
792            nativePnoSettings.networkList[i].priority = requestPnoSettings.networkList[i].priority;
793            nativePnoSettings.networkList[i].flags = requestPnoSettings.networkList[i].flags;
794            nativePnoSettings.networkList[i].auth_bit_field =
795                    requestPnoSettings.networkList[i].authBitField;
796        }
797        return Pair.create(requestPnoSettings, nativePnoSettings);
798    }
799
800    private ScanResults createScanResultsForPno() {
801        return ScanResults.create(0, 2400, 5150, 5175);
802    }
803
804    private ScanResults createScanResultsForPnoWithNoIE() {
805        return ScanResults.createWithNoIE(0, 2400, 5150, 5175);
806    }
807
808    private WifiNative.PnoEventHandler verifyHwPno(InOrder order,
809            WifiNative.PnoSettings expected) {
810        ArgumentCaptor<WifiNative.PnoSettings> pnoSettingsCaptor =
811                ArgumentCaptor.forClass(WifiNative.PnoSettings.class);
812        ArgumentCaptor<WifiNative.PnoEventHandler> pnoEventHandlerCaptor =
813                ArgumentCaptor.forClass(WifiNative.PnoEventHandler.class);
814        order.verify(mWifiScannerImpl).setHwPnoList(pnoSettingsCaptor.capture(),
815                pnoEventHandlerCaptor.capture());
816        assertNativePnoSettingsEquals(expected, pnoSettingsCaptor.getValue());
817        return pnoEventHandlerCaptor.getValue();
818    }
819
820    private void sendPnoScanRequest(BidirectionalAsyncChannel controlChannel,
821            int scanRequestId, WifiScanner.ScanSettings scanSettings,
822            WifiScanner.PnoSettings pnoSettings) {
823        Bundle pnoParams = new Bundle();
824        scanSettings.isPnoScan = true;
825        pnoParams.putParcelable(WifiScanner.PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings);
826        pnoParams.putParcelable(WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings);
827        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_PNO_SCAN, 0,
828                scanRequestId, pnoParams));
829    }
830
831    private void assertPnoNetworkFoundMessage(int listenerId, ScanResult[] expected,
832            Message networkFoundMessage) {
833        assertEquals("what", WifiScanner.CMD_PNO_NETWORK_FOUND, networkFoundMessage.what);
834        assertEquals("listenerId", listenerId, networkFoundMessage.arg2);
835        assertScanResultsEquals(expected,
836                ((WifiScanner.ParcelableScanResults) networkFoundMessage.obj).getResults());
837    }
838
839    private void verifyPnoNetworkFoundRecieved(InOrder order, Handler handler, int listenerId,
840            ScanResult[] expected) {
841        Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler,
842                WifiScanner.CMD_PNO_NETWORK_FOUND);
843        assertPnoNetworkFoundMessage(listenerId, expected, scanResultMessage);
844    }
845
846    private void expectSuccessfulBackgroundScan(InOrder order,
847            WifiNative.ScanSettings nativeSettings, ScanResults results) {
848        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
849                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
850        mLooper.dispatchAll();
851        WifiNative.ScanEventHandler eventHandler = verifyStartBackgroundScan(order, nativeSettings);
852        WifiScanner.ScanData[] scanDatas = new WifiScanner.ScanData[1];
853        scanDatas[0] = results.getScanData();
854        for (ScanResult fullScanResult : results.getRawScanResults()) {
855            eventHandler.onFullScanResult(fullScanResult, 0);
856        }
857        when(mWifiScannerImpl.getLatestBatchedScanResults(anyBoolean())).thenReturn(scanDatas);
858        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
859        mLooper.dispatchAll();
860    }
861
862    private void expectHwPnoScanWithNoBackgroundScan(InOrder order, Handler handler, int requestId,
863            WifiNative.PnoSettings nativeSettings, ScanResults results) {
864        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(true);
865        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(false);
866
867        when(mWifiScannerImpl.setHwPnoList(any(WifiNative.PnoSettings.class),
868                any(WifiNative.PnoEventHandler.class))).thenReturn(true);
869        mLooper.dispatchAll();
870        WifiNative.PnoEventHandler eventHandler = verifyHwPno(order, nativeSettings);
871        verifySuccessfulResponse(order, handler, requestId);
872        eventHandler.onPnoNetworkFound(results.getRawScanResults());
873        mLooper.dispatchAll();
874    }
875
876    private void expectHwPnoScanWithBackgroundScan(InOrder order, Handler handler, int requestId,
877            WifiNative.ScanSettings nativeScanSettings,
878            WifiNative.PnoSettings nativePnoSettings, ScanResults results) {
879        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(true);
880        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(true);
881
882        when(mWifiScannerImpl.setHwPnoList(any(WifiNative.PnoSettings.class),
883                any(WifiNative.PnoEventHandler.class))).thenReturn(true);
884        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
885                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
886        mLooper.dispatchAll();
887        WifiNative.PnoEventHandler eventHandler = verifyHwPno(order, nativePnoSettings);
888        verifySuccessfulResponse(order, handler, requestId);
889        verifyStartBackgroundScan(order, nativeScanSettings);
890        eventHandler.onPnoNetworkFound(results.getRawScanResults());
891        mLooper.dispatchAll();
892    }
893
894    private void expectHwPnoScanWithBackgroundScanWithNoIE(InOrder order, Handler handler,
895            int requestId, WifiNative.ScanSettings nativeBackgroundScanSettings,
896            WifiNative.ScanSettings nativeSingleScanSettings,
897            WifiNative.PnoSettings nativePnoSettings, ScanResults results) {
898        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
899                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
900
901        expectHwPnoScanWithBackgroundScan(order, handler, requestId, nativeBackgroundScanSettings,
902                nativePnoSettings, results);
903        WifiNative.ScanEventHandler eventHandler =
904                verifyStartSingleScan(order, nativeSingleScanSettings);
905        when(mWifiScannerImpl.getLatestSingleScanResults()).thenReturn(results.getScanData());
906        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
907        mLooper.dispatchAll();
908    }
909    private void expectSwPnoScan(InOrder order, WifiNative.ScanSettings nativeScanSettings,
910            ScanResults results) {
911        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(false);
912        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(true);
913
914        expectSuccessfulBackgroundScan(order, nativeScanSettings, results);
915    }
916
917    /**
918     * Tests Supplicant PNO scan when the PNO scan results contain IE info. This ensures that the
919     * PNO scan results are plumbed back to the client as a PNO network found event.
920     */
921    @Test
922    public void testSuccessfulHwPnoScanWithNoBackgroundScan() throws Exception {
923        startServiceAndLoadDriver();
924        Handler handler = mock(Handler.class);
925        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
926        InOrder order = inOrder(handler, mWifiScannerImpl);
927        int requestId = 12;
928
929        ScanResults scanResults = createScanResultsForPno();
930        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
931                createScanSettingsForHwPno();
932        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
933                createPnoSettings(scanResults);
934
935        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
936        expectHwPnoScanWithNoBackgroundScan(order, handler, requestId, pnoSettings.second,
937                scanResults);
938        verifyPnoNetworkFoundRecieved(order, handler, requestId, scanResults.getRawScanResults());
939    }
940
941    /**
942     * Tests Hal ePNO scan when the PNO scan results contain IE info. This ensures that the
943     * PNO scan results are plumbed back to the client as a PNO network found event.
944     */
945    @Test
946    public void testSuccessfulHwPnoScanWithBackgroundScan() throws Exception {
947        startServiceAndLoadDriver();
948        Handler handler = mock(Handler.class);
949        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
950        InOrder order = inOrder(handler, mWifiScannerImpl);
951        int requestId = 12;
952
953        ScanResults scanResults = createScanResultsForPno();
954        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
955                createScanSettingsForHwPno();
956        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
957                createPnoSettings(scanResults);
958
959        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
960        expectHwPnoScanWithBackgroundScan(order, handler, requestId, scanSettings.second,
961                pnoSettings.second, scanResults);
962        verifyPnoNetworkFoundRecieved(order, handler, requestId, scanResults.getRawScanResults());
963    }
964
965    /**
966     * Tests Hal ePNO scan when the PNO scan results don't contain IE info. This ensures that the
967     * single scan results are plumbed back to the client as a PNO network found event.
968     */
969    @Test
970    public void testSuccessfulHwPnoScanWithBackgroundScanWithNoIE() throws Exception {
971        startServiceAndLoadDriver();
972        Handler handler = mock(Handler.class);
973        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
974        InOrder order = inOrder(handler, mWifiScannerImpl);
975        int requestId = 12;
976
977        ScanResults scanResults = createScanResultsForPnoWithNoIE();
978        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
979                createScanSettingsForHwPno();
980        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
981                createPnoSettings(scanResults);
982
983        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
984        expectHwPnoScanWithBackgroundScanWithNoIE(order, handler, requestId, scanSettings.second,
985                computeSingleScanNativeSettings(scanSettings.first), pnoSettings.second,
986                scanResults);
987
988        ArrayList<ScanResult> sortScanList =
989                new ArrayList<ScanResult>(Arrays.asList(scanResults.getRawScanResults()));
990        Collections.sort(sortScanList, WifiScannerImpl.SCAN_RESULT_SORT_COMPARATOR);
991        verifyPnoNetworkFoundRecieved(order, handler, requestId,
992                sortScanList.toArray(new ScanResult[sortScanList.size()]));
993    }
994
995    /**
996     * Tests SW PNO scan. This ensures that the background scan results are plumbed back to the
997     * client as a PNO network found event.
998     */
999    @Test
1000    public void testSuccessfulSwPnoScan() throws Exception {
1001        startServiceAndLoadDriver();
1002        Handler handler = mock(Handler.class);
1003        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1004        InOrder order = inOrder(handler, mWifiScannerImpl);
1005        int requestId = 12;
1006
1007        ScanResults scanResults = createScanResultsForPno();
1008        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1009                createScanSettingsForSwPno();
1010        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1011                createPnoSettings(scanResults);
1012
1013        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1014        expectSwPnoScan(order, scanSettings.second, scanResults);
1015        verifyPnoNetworkFoundRecieved(order, handler, requestId, scanResults.getRawScanResults());
1016    }
1017}
1018