[go: nahoru, domu]

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