[go: nahoru, domu]

WifiScanningServiceTest.java revision 1f9f7c109ca952884fb7bff7271669d879ce9b97
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        when(mWifiScannerImpl.getScanCapabilities(any(WifiNative.ScanCapabilities.class)))
266                .thenAnswer(new AnswerWithArguments() {
267                        public boolean answer(WifiNative.ScanCapabilities capabilities) {
268                            capabilities.max_scan_cache_size = Integer.MAX_VALUE;
269                            capabilities.max_scan_buckets = 8;
270                            capabilities.max_ap_cache_per_scan = MAX_AP_PER_SCAN;
271                            capabilities.max_rssi_sample_size = 8;
272                            capabilities.max_scan_reporting_threshold = 10;
273                            capabilities.max_hotlist_bssids = 0;
274                            capabilities.max_significant_wifi_change_aps = 0;
275                            return true;
276                        }
277                    });
278        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
279                ArgumentCaptor.forClass(BroadcastReceiver.class);
280        verify(mContext)
281                .registerReceiver(broadcastReceiverCaptor.capture(), any(IntentFilter.class));
282        mBroadcastReceiver = broadcastReceiverCaptor.getValue();
283        TestUtil.sendWifiScanAvailable(broadcastReceiverCaptor.getValue(), mContext,
284                WifiManager.WIFI_STATE_ENABLED);
285        mLooper.dispatchAll();
286    }
287
288    private String dumpService() {
289        StringWriter stringWriter = new StringWriter();
290        mWifiScanningServiceImpl.dump(new FileDescriptor(), new PrintWriter(stringWriter),
291                new String[0]);
292        return stringWriter.toString();
293    }
294
295    private void assertDumpContainsRequestLog(String type, int id) {
296        String serviceDump = dumpService();
297        Pattern logLineRegex = Pattern.compile("^.+" + type + ": ClientInfo\\[uid=\\d+\\],Id=" +
298                id + ".*$", Pattern.MULTILINE);
299        assertTrue("dump did not contain log with type=" + type + ", id=" + id +
300                ": " + serviceDump + "\n",
301                logLineRegex.matcher(serviceDump).find());
302   }
303
304    private void assertDumpContainsCallbackLog(String callback, int id, String extra) {
305        String serviceDump = dumpService();
306        String extraPattern = extra == null ? "" : "," + extra;
307        Pattern logLineRegex = Pattern.compile("^.+" + callback + ": ClientInfo\\[uid=\\d+\\],Id=" +
308                id + extraPattern + "$", Pattern.MULTILINE);
309        assertTrue("dump did not contain callback log with callback=" + callback + ", id=" + id +
310                ", extra=" + extra + ": " + serviceDump + "\n",
311                logLineRegex.matcher(serviceDump).find());
312   }
313
314    @Test
315    public void construct() throws Exception {
316        verifyNoMoreInteractions(mWifiScannerImpl, mWifiScannerImpl,
317                mWifiScannerImplFactory, mBatteryStats);
318        dumpService(); // make sure this succeeds
319    }
320
321    @Test
322    public void startService() throws Exception {
323        mWifiScanningServiceImpl.startService();
324        verifyNoMoreInteractions(mWifiScannerImplFactory);
325
326        Handler handler = mock(Handler.class);
327        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
328        InOrder order = inOrder(handler);
329        sendBackgroundScanRequest(controlChannel, 122, generateValidScanSettings(), null);
330        mLooper.dispatchAll();
331        verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available");
332    }
333
334    @Test
335    public void loadDriver() throws Exception {
336        startServiceAndLoadDriver();
337        verify(mWifiScannerImplFactory, times(1))
338                .create(any(Context.class), any(Looper.class), any(Clock.class));
339
340        Handler handler = mock(Handler.class);
341        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
342        InOrder order = inOrder(handler);
343        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
344                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
345        sendBackgroundScanRequest(controlChannel, 192, generateValidScanSettings(), null);
346        mLooper.dispatchAll();
347        verifySuccessfulResponse(order, handler, 192);
348        assertDumpContainsRequestLog("addBackgroundScanRequest", 192);
349    }
350
351    @Test
352    public void sendInvalidCommand() throws Exception {
353        startServiceAndLoadDriver();
354
355        Handler handler = mock(Handler.class);
356        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
357        InOrder order = inOrder(handler, mWifiScannerImpl);
358        controlChannel.sendMessage(Message.obtain(null, Protocol.BASE_WIFI_MANAGER));
359        mLooper.dispatchAll();
360        verifyFailedResponse(order, handler, 0, WifiScanner.REASON_INVALID_REQUEST,
361                "Invalid request");
362    }
363
364    private void doSuccessfulSingleScan(WifiScanner.ScanSettings requestSettings,
365            WifiNative.ScanSettings nativeSettings, ScanResults results) throws RemoteException {
366        int requestId = 12;
367        WorkSource workSource = new WorkSource(2292);
368        startServiceAndLoadDriver();
369
370        Handler handler = mock(Handler.class);
371        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
372        InOrder order = inOrder(handler, mWifiScannerImpl);
373
374        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
375                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
376
377        sendSingleScanRequest(controlChannel, requestId, requestSettings, workSource);
378
379        mLooper.dispatchAll();
380        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings);
381        verifySuccessfulResponse(order, handler, requestId);
382        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource));
383
384        when(mWifiScannerImpl.getLatestSingleScanResults())
385                .thenReturn(results.getRawScanData());
386        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
387
388        mLooper.dispatchAll();
389        verifyScanResultsRecieved(order, handler, requestId, results.getScanData());
390        verifySingleScanCompletedRecieved(order, handler, requestId);
391        verifyNoMoreInteractions(handler);
392        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource));
393        assertDumpContainsRequestLog("addSingleScanRequest", requestId);
394        assertDumpContainsCallbackLog("singleScanResults", requestId,
395                "results=" + results.getScanData().getResults().length);
396    }
397
398    /**
399     * Do a single scan for a band and verify that it is successful.
400     */
401    @Test
402    public void sendSingleScanBandRequest() throws Exception {
403        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
404                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
405        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
406                ScanResults.create(0, 2400, 5150, 5175));
407    }
408
409    /**
410     * Do a single scan for a list of channels and verify that it is successful.
411     */
412    @Test
413    public void sendSingleScanChannelsRequest() throws Exception {
414        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
415                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
416        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
417                ScanResults.create(0, 2400, 5150, 5175));
418    }
419
420    /**
421     * Do a single scan with no results and verify that it is successful.
422     */
423    @Test
424    public void sendSingleScanRequestWithNoResults() throws Exception {
425        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
426                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
427        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
428                ScanResults.create(0, new int[0]));
429    }
430
431    /**
432     * Do a single scan with results that do not match the requested scan and verify that it is
433     * still successful (and returns no results).
434     */
435    @Test
436    public void sendSingleScanRequestWithBadRawResults() throws Exception {
437        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_24_GHZ, 0,
438                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
439        // Create a set of scan results that has results not matching the request settings, but is
440        // limited to zero results for the expected results.
441        ScanResults results = ScanResults.createOverflowing(0, 0,
442                ScanResults.generateNativeResults(0, 5150, 5171));
443        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
444                results);
445    }
446
447    /**
448     * Do a single scan, which the hardware fails to start, and verify that a failure response is
449     * delivered.
450     */
451    @Test
452    public void sendSingleScanRequestWhichFailsToStart() throws Exception {
453        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
454                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
455        int requestId = 33;
456
457        startServiceAndLoadDriver();
458
459        Handler handler = mock(Handler.class);
460        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
461        InOrder order = inOrder(handler, mWifiScannerImpl);
462
463        // scan fails
464        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
465                        any(WifiNative.ScanEventHandler.class))).thenReturn(false);
466
467        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
468
469        mLooper.dispatchAll();
470        // Scan is successfully queue, but then fails to execute
471        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
472        order.verify(handler, times(2)).handleMessage(messageCaptor.capture());
473        assertSuccessfulResponse(requestId, messageCaptor.getAllValues().get(0));
474        assertFailedResponse(requestId, WifiScanner.REASON_UNSPECIFIED,
475                "Failed to start single scan", messageCaptor.getAllValues().get(1));
476        verifyNoMoreInteractions(mBatteryStats);
477
478        assertEquals(mWifiMetrics.getOneshotScanCount(), 1);
479        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1);
480        assertDumpContainsRequestLog("addSingleScanRequest", requestId);
481    }
482
483    /**
484     * Do a single scan, which successfully starts, but fails partway through and verify that a
485     * failure response is delivered.
486     */
487    @Test
488    public void sendSingleScanRequestWhichFailsAfterStart() throws Exception {
489        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
490                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
491        int requestId = 33;
492        WorkSource workSource = new WorkSource(Binder.getCallingUid()); // don't explicitly set
493
494        startServiceAndLoadDriver();
495
496        Handler handler = mock(Handler.class);
497        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
498        InOrder order = inOrder(handler, mWifiScannerImpl);
499
500        // successful start
501        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
502                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
503
504        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
505
506        // Scan is successfully queue
507        mLooper.dispatchAll();
508        WifiNative.ScanEventHandler eventHandler =
509                verifyStartSingleScan(order, computeSingleScanNativeSettings(requestSettings));
510        verifySuccessfulResponse(order, handler, requestId);
511        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource));
512
513        // but then fails to execute
514        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_FAILED);
515        mLooper.dispatchAll();
516        verifyFailedResponse(order, handler, requestId,
517                WifiScanner.REASON_UNSPECIFIED, "Scan failed");
518        assertDumpContainsCallbackLog("singleScanFailed", requestId,
519                "reason=" + WifiScanner.REASON_UNSPECIFIED + ", Scan failed");
520        assertEquals(mWifiMetrics.getOneshotScanCount(), 1);
521        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1);
522        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource));
523    }
524
525    // TODO Add more single scan tests
526    // * disable wifi while scanning
527    // * disable wifi while scanning with pending scan
528
529    /**
530     * Send a single scan request and then a second one after the first completes.
531     */
532    @Test
533    public void sendSingleScanRequestAfterPreviousCompletes() {
534        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
535                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
536        int requestId1 = 12;
537        ScanResults results1 = ScanResults.create(0, 2400);
538
539
540        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
541                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
542        int requestId2 = 13;
543        ScanResults results2 = ScanResults.create(0, 2450);
544
545
546        startServiceAndLoadDriver();
547
548        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
549                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
550
551        Handler handler = mock(Handler.class);
552        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
553        InOrder order = inOrder(handler, mWifiScannerImpl);
554
555        // Run scan 1
556        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
557
558        mLooper.dispatchAll();
559        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(order,
560                computeSingleScanNativeSettings(requestSettings1));
561        verifySuccessfulResponse(order, handler, requestId1);
562
563        // dispatch scan 1 results
564        when(mWifiScannerImpl.getLatestSingleScanResults())
565                .thenReturn(results1.getScanData());
566        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
567
568        mLooper.dispatchAll();
569        verifyScanResultsRecieved(order, handler, requestId1, results1.getScanData());
570        verifySingleScanCompletedRecieved(order, handler, requestId1);
571
572        // Run scan 2
573        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
574
575        mLooper.dispatchAll();
576        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(order,
577                computeSingleScanNativeSettings(requestSettings2));
578        verifySuccessfulResponse(order, handler, requestId2);
579
580        // dispatch scan 2 results
581        when(mWifiScannerImpl.getLatestSingleScanResults())
582                .thenReturn(results2.getScanData());
583        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
584
585        mLooper.dispatchAll();
586        verifyScanResultsRecieved(order, handler, requestId2, results2.getScanData());
587        verifySingleScanCompletedRecieved(order, handler, requestId2);
588    }
589
590    /**
591     * Send a single scan request and then a second one before the first completes.
592     * Verify that both are scheduled and succeed.
593     */
594    @Test
595    public void sendSingleScanRequestWhilePreviousScanRunning() {
596        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
597                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
598        int requestId1 = 12;
599        ScanResults results1 = ScanResults.create(0, 2400);
600
601        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
602                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
603        int requestId2 = 13;
604        ScanResults results2 = ScanResults.create(0, 2450);
605
606
607        startServiceAndLoadDriver();
608
609        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
610                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
611
612        Handler handler = mock(Handler.class);
613        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
614        InOrder handlerOrder = inOrder(handler);
615        InOrder nativeOrder = inOrder(mWifiScannerImpl);
616
617        // Run scan 1
618        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
619
620        mLooper.dispatchAll();
621        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
622                computeSingleScanNativeSettings(requestSettings1));
623        verifySuccessfulResponse(handlerOrder, handler, requestId1);
624
625        // Queue scan 2 (will not run because previous is in progress)
626        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
627        mLooper.dispatchAll();
628        verifySuccessfulResponse(handlerOrder, handler, requestId2);
629
630        // dispatch scan 1 results
631        when(mWifiScannerImpl.getLatestSingleScanResults())
632                .thenReturn(results1.getScanData());
633        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
634
635        mLooper.dispatchAll();
636        verifyScanResultsRecieved(handlerOrder, handler, requestId1, results1.getScanData());
637        verifySingleScanCompletedRecieved(handlerOrder, handler, requestId1);
638
639        // now that the first scan completed we expect the second one to start
640        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(nativeOrder,
641                computeSingleScanNativeSettings(requestSettings2));
642
643        // dispatch scan 2 results
644        when(mWifiScannerImpl.getLatestSingleScanResults())
645                .thenReturn(results2.getScanData());
646        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
647
648        mLooper.dispatchAll();
649        verifyScanResultsRecieved(handlerOrder, handler, requestId2, results2.getScanData());
650        verifySingleScanCompletedRecieved(handlerOrder, handler, requestId2);
651        assertEquals(mWifiMetrics.getOneshotScanCount(), 2);
652        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 2);
653    }
654
655
656    /**
657     * Send a single scan request and then two more before the first completes.
658     * Verify that the first completes and the second two are merged.
659     */
660    @Test
661    public void sendMultipleSingleScanRequestWhilePreviousScanRunning() throws RemoteException {
662        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
663                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
664        int requestId1 = 12;
665        WorkSource workSource1 = new WorkSource(1121);
666        ScanResults results1 = ScanResults.create(0, 2400);
667
668        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
669                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
670        int requestId2 = 13;
671        WorkSource workSource2 = new WorkSource(Binder.getCallingUid()); // don't explicitly set
672        ScanResults results2 = ScanResults.create(0, 2450, 5175, 2450);
673
674        WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(5150), 0,
675                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
676        int requestId3 = 15;
677        WorkSource workSource3 = new WorkSource(2292);
678        ScanResults results3 = ScanResults.create(0, 5150, 5150, 5150, 5150);
679
680        WifiNative.ScanSettings nativeSettings2and3 = createSingleScanNativeSettingsForChannels(
681                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, channelsToSpec(2450, 5175, 5150));
682        ScanResults results2and3 = ScanResults.merge(results2, results3);
683        WorkSource workSource2and3 = new WorkSource();
684        workSource2and3.add(workSource2);
685        workSource2and3.add(workSource3);
686
687
688        startServiceAndLoadDriver();
689
690        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
691                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
692
693        Handler handler = mock(Handler.class);
694        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
695        InOrder handlerOrder = inOrder(handler);
696        InOrder nativeOrder = inOrder(mWifiScannerImpl);
697
698        // Run scan 1
699        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, workSource1);
700
701        mLooper.dispatchAll();
702        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
703                computeSingleScanNativeSettings(requestSettings1));
704        verifySuccessfulResponse(handlerOrder, handler, requestId1);
705        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource1));
706
707
708        // Queue scan 2 (will not run because previous is in progress)
709        // uses uid of calling process
710        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
711        mLooper.dispatchAll();
712        verifySuccessfulResponse(handlerOrder, handler, requestId2);
713
714        // Queue scan 3 (will not run because previous is in progress)
715        sendSingleScanRequest(controlChannel, requestId3, requestSettings3, workSource3);
716        mLooper.dispatchAll();
717        verifySuccessfulResponse(handlerOrder, handler, requestId3);
718
719        // dispatch scan 1 results
720        when(mWifiScannerImpl.getLatestSingleScanResults())
721                .thenReturn(results1.getScanData());
722        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
723
724        mLooper.dispatchAll();
725        verifyScanResultsRecieved(handlerOrder, handler, requestId1, results1.getScanData());
726        verifySingleScanCompletedRecieved(handlerOrder, handler, requestId1);
727        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource1));
728        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource2and3));
729
730        // now that the first scan completed we expect the second and third ones to start
731        WifiNative.ScanEventHandler eventHandler2and3 = verifyStartSingleScan(nativeOrder,
732                nativeSettings2and3);
733
734        // dispatch scan 2 and 3 results
735        when(mWifiScannerImpl.getLatestSingleScanResults())
736                .thenReturn(results2and3.getScanData());
737        eventHandler2and3.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
738
739        mLooper.dispatchAll();
740
741        // unfortunatally the order that these events are dispatched is dependant on the order which
742        // they are iterated through internally
743        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
744        handlerOrder.verify(handler, times(4)).handleMessage(messageCaptor.capture());
745        int firstListenerId = messageCaptor.getAllValues().get(0).arg2;
746        assertTrue(firstListenerId + " was neither " + requestId2 + " nor " + requestId3,
747                firstListenerId == requestId2 || firstListenerId == requestId3);
748        if (firstListenerId == requestId2) {
749            assertScanResultsMessage(requestId2,
750                    new WifiScanner.ScanData[] {results2.getScanData()},
751                    messageCaptor.getAllValues().get(0));
752            assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(1));
753            assertScanResultsMessage(requestId3,
754                    new WifiScanner.ScanData[] {results3.getScanData()},
755                    messageCaptor.getAllValues().get(2));
756            assertSingleScanCompletedMessage(requestId3, messageCaptor.getAllValues().get(3));
757        } else {
758            assertScanResultsMessage(requestId3,
759                    new WifiScanner.ScanData[] {results3.getScanData()},
760                    messageCaptor.getAllValues().get(0));
761            assertSingleScanCompletedMessage(requestId3, messageCaptor.getAllValues().get(1));
762            assertScanResultsMessage(requestId2,
763                    new WifiScanner.ScanData[] {results2.getScanData()},
764                    messageCaptor.getAllValues().get(2));
765            assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(3));
766        }
767        assertEquals(mWifiMetrics.getOneshotScanCount(), 3);
768        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 3);
769
770        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource2and3));
771
772        assertDumpContainsRequestLog("addSingleScanRequest", requestId1);
773        assertDumpContainsRequestLog("addSingleScanRequest", requestId2);
774        assertDumpContainsRequestLog("addSingleScanRequest", requestId3);
775        assertDumpContainsCallbackLog("singleScanResults", requestId1,
776                "results=" + results1.getRawScanResults().length);
777        assertDumpContainsCallbackLog("singleScanResults", requestId2,
778                "results=" + results2.getRawScanResults().length);
779        assertDumpContainsCallbackLog("singleScanResults", requestId3,
780                "results=" + results3.getRawScanResults().length);
781    }
782
783    private void doSuccessfulBackgroundScan(WifiScanner.ScanSettings requestSettings,
784            WifiNative.ScanSettings nativeSettings) {
785        startServiceAndLoadDriver();
786
787        Handler handler = mock(Handler.class);
788        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
789        InOrder order = inOrder(handler, mWifiScannerImpl);
790
791        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
792                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
793
794        sendBackgroundScanRequest(controlChannel, 12, requestSettings, null);
795        mLooper.dispatchAll();
796        verifyStartBackgroundScan(order, nativeSettings);
797        verifySuccessfulResponse(order, handler, 12);
798        verifyNoMoreInteractions(handler);
799        assertDumpContainsRequestLog("addBackgroundScanRequest", 12);
800    }
801
802    /**
803     * Do a background scan for a band and verify that it is successful.
804     */
805    @Test
806    public void sendBackgroundScanBandRequest() throws Exception {
807        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 20000,
808                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
809        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
810                .withBasePeriod(20000)
811                .withMaxApPerScan(MAX_AP_PER_SCAN)
812                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
813                .addBucketWithBand(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
814                        WifiScanner.WIFI_BAND_BOTH)
815                .build();
816        doSuccessfulBackgroundScan(requestSettings, nativeSettings);
817        assertEquals(mWifiMetrics.getBackgroundScanCount(), 1);
818    }
819
820    /**
821     * Do a background scan for a list of channels and verify that it is successful.
822     */
823    @Test
824    public void sendBackgroundScanChannelsRequest() throws Exception {
825        WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(5150), 20000,
826                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
827        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
828                .withBasePeriod(20000)
829                .withMaxApPerScan(MAX_AP_PER_SCAN)
830                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
831                .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5150)
832                .build();
833        doSuccessfulBackgroundScan(requestSettings, nativeSettings);
834    }
835
836    private Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> createScanSettingsForHwPno()
837            throws Exception {
838        WifiScanner.ScanSettings requestSettings = createRequest(
839                channelsToSpec(0, 2400, 5150, 5175), 20000, 0, 20,
840                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
841        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
842                .withBasePeriod(20000)
843                .withMaxApPerScan(MAX_AP_PER_SCAN)
844                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
845                .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
846                        0, 2400, 5150, 5175)
847                .build();
848        return Pair.create(requestSettings, nativeSettings);
849    }
850
851    private Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> createScanSettingsForSwPno()
852            throws Exception {
853        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> settingsPair =
854                createScanSettingsForHwPno();
855
856        WifiScanner.ScanSettings requestSettings = settingsPair.first;
857        WifiNative.ScanSettings nativeSettings = settingsPair.second;
858        // reportEvents field is overridden for SW PNO
859        for (int i = 0; i < nativeSettings.buckets.length; i++) {
860            nativeSettings.buckets[i].report_events = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
861                    | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
862        }
863        return Pair.create(requestSettings, nativeSettings);
864    }
865
866    private Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> createPnoSettings(
867            ScanResults results)
868            throws Exception {
869        WifiScanner.PnoSettings requestPnoSettings = new WifiScanner.PnoSettings();
870        requestPnoSettings.networkList =
871                new WifiScanner.PnoSettings.PnoNetwork[results.getRawScanResults().length];
872        int i = 0;
873        for (ScanResult scanResult : results.getRawScanResults()) {
874            requestPnoSettings.networkList[i++] =
875                    new WifiScanner.PnoSettings.PnoNetwork(scanResult.SSID);
876        }
877
878        WifiNative.PnoSettings nativePnoSettings = new WifiNative.PnoSettings();
879        nativePnoSettings.min5GHzRssi = requestPnoSettings.min5GHzRssi;
880        nativePnoSettings.min24GHzRssi = requestPnoSettings.min24GHzRssi;
881        nativePnoSettings.initialScoreMax = requestPnoSettings.initialScoreMax;
882        nativePnoSettings.currentConnectionBonus = requestPnoSettings.currentConnectionBonus;
883        nativePnoSettings.sameNetworkBonus = requestPnoSettings.sameNetworkBonus;
884        nativePnoSettings.secureBonus = requestPnoSettings.secureBonus;
885        nativePnoSettings.band5GHzBonus = requestPnoSettings.band5GHzBonus;
886        nativePnoSettings.isConnected = requestPnoSettings.isConnected;
887        nativePnoSettings.networkList =
888                new WifiNative.PnoNetwork[requestPnoSettings.networkList.length];
889        for (i = 0; i < requestPnoSettings.networkList.length; i++) {
890            nativePnoSettings.networkList[i] = new WifiNative.PnoNetwork();
891            nativePnoSettings.networkList[i].ssid = requestPnoSettings.networkList[i].ssid;
892            nativePnoSettings.networkList[i].networkId =
893                    requestPnoSettings.networkList[i].networkId;
894            nativePnoSettings.networkList[i].priority = requestPnoSettings.networkList[i].priority;
895            nativePnoSettings.networkList[i].flags = requestPnoSettings.networkList[i].flags;
896            nativePnoSettings.networkList[i].auth_bit_field =
897                    requestPnoSettings.networkList[i].authBitField;
898        }
899        return Pair.create(requestPnoSettings, nativePnoSettings);
900    }
901
902    private ScanResults createScanResultsForPno() {
903        return ScanResults.create(0, 2400, 5150, 5175);
904    }
905
906    private ScanResults createScanResultsForPnoWithNoIE() {
907        return ScanResults.createWithNoIE(0, 2400, 5150, 5175);
908    }
909
910    private WifiNative.PnoEventHandler verifyHwPno(InOrder order,
911            WifiNative.PnoSettings expected) {
912        ArgumentCaptor<WifiNative.PnoSettings> pnoSettingsCaptor =
913                ArgumentCaptor.forClass(WifiNative.PnoSettings.class);
914        ArgumentCaptor<WifiNative.PnoEventHandler> pnoEventHandlerCaptor =
915                ArgumentCaptor.forClass(WifiNative.PnoEventHandler.class);
916        order.verify(mWifiScannerImpl).setHwPnoList(pnoSettingsCaptor.capture(),
917                pnoEventHandlerCaptor.capture());
918        assertNativePnoSettingsEquals(expected, pnoSettingsCaptor.getValue());
919        return pnoEventHandlerCaptor.getValue();
920    }
921
922    private void sendPnoScanRequest(BidirectionalAsyncChannel controlChannel,
923            int scanRequestId, WifiScanner.ScanSettings scanSettings,
924            WifiScanner.PnoSettings pnoSettings) {
925        Bundle pnoParams = new Bundle();
926        scanSettings.isPnoScan = true;
927        pnoParams.putParcelable(WifiScanner.PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings);
928        pnoParams.putParcelable(WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings);
929        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_PNO_SCAN, 0,
930                scanRequestId, pnoParams));
931    }
932
933    private void assertPnoNetworkFoundMessage(int listenerId, ScanResult[] expected,
934            Message networkFoundMessage) {
935        assertEquals("what", WifiScanner.CMD_PNO_NETWORK_FOUND, networkFoundMessage.what);
936        assertEquals("listenerId", listenerId, networkFoundMessage.arg2);
937        assertScanResultsEquals(expected,
938                ((WifiScanner.ParcelableScanResults) networkFoundMessage.obj).getResults());
939    }
940
941    private void verifyPnoNetworkFoundRecieved(InOrder order, Handler handler, int listenerId,
942            ScanResult[] expected) {
943        Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler,
944                WifiScanner.CMD_PNO_NETWORK_FOUND);
945        assertPnoNetworkFoundMessage(listenerId, expected, scanResultMessage);
946    }
947
948    private void expectSuccessfulBackgroundScan(InOrder order,
949            WifiNative.ScanSettings nativeSettings, ScanResults results) {
950        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
951                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
952        mLooper.dispatchAll();
953        WifiNative.ScanEventHandler eventHandler = verifyStartBackgroundScan(order, nativeSettings);
954        WifiScanner.ScanData[] scanDatas = new WifiScanner.ScanData[1];
955        scanDatas[0] = results.getScanData();
956        for (ScanResult fullScanResult : results.getRawScanResults()) {
957            eventHandler.onFullScanResult(fullScanResult, 0);
958        }
959        when(mWifiScannerImpl.getLatestBatchedScanResults(anyBoolean())).thenReturn(scanDatas);
960        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
961        mLooper.dispatchAll();
962    }
963
964    private void expectHwPnoScanWithNoBackgroundScan(InOrder order, Handler handler, int requestId,
965            WifiNative.PnoSettings nativeSettings, ScanResults results) {
966        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(true);
967        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(false);
968
969        when(mWifiScannerImpl.setHwPnoList(any(WifiNative.PnoSettings.class),
970                any(WifiNative.PnoEventHandler.class))).thenReturn(true);
971        mLooper.dispatchAll();
972        WifiNative.PnoEventHandler eventHandler = verifyHwPno(order, nativeSettings);
973        verifySuccessfulResponse(order, handler, requestId);
974        eventHandler.onPnoNetworkFound(results.getRawScanResults());
975        mLooper.dispatchAll();
976    }
977
978    private void expectHwPnoScanWithBackgroundScan(InOrder order, Handler handler, int requestId,
979            WifiNative.ScanSettings nativeScanSettings,
980            WifiNative.PnoSettings nativePnoSettings, ScanResults results) {
981        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(true);
982        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(true);
983
984        when(mWifiScannerImpl.setHwPnoList(any(WifiNative.PnoSettings.class),
985                any(WifiNative.PnoEventHandler.class))).thenReturn(true);
986        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
987                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
988        mLooper.dispatchAll();
989        WifiNative.PnoEventHandler eventHandler = verifyHwPno(order, nativePnoSettings);
990        verifySuccessfulResponse(order, handler, requestId);
991        verifyStartBackgroundScan(order, nativeScanSettings);
992        eventHandler.onPnoNetworkFound(results.getRawScanResults());
993        mLooper.dispatchAll();
994    }
995
996    private void expectHwPnoScanWithBackgroundScanWithNoIE(InOrder order, Handler handler,
997            int requestId, WifiNative.ScanSettings nativeBackgroundScanSettings,
998            WifiNative.ScanSettings nativeSingleScanSettings,
999            WifiNative.PnoSettings nativePnoSettings, ScanResults results) {
1000        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1001                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1002
1003        expectHwPnoScanWithBackgroundScan(order, handler, requestId, nativeBackgroundScanSettings,
1004                nativePnoSettings, results);
1005        WifiNative.ScanEventHandler eventHandler =
1006                verifyStartSingleScan(order, nativeSingleScanSettings);
1007        when(mWifiScannerImpl.getLatestSingleScanResults()).thenReturn(results.getScanData());
1008        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1009        mLooper.dispatchAll();
1010    }
1011    private void expectSwPnoScan(InOrder order, WifiNative.ScanSettings nativeScanSettings,
1012            ScanResults results) {
1013        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(false);
1014        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(true);
1015
1016        expectSuccessfulBackgroundScan(order, nativeScanSettings, results);
1017    }
1018
1019    /**
1020     * Tests Supplicant PNO scan when the PNO scan results contain IE info. This ensures that the
1021     * PNO scan results are plumbed back to the client as a PNO network found event.
1022     */
1023    @Test
1024    public void testSuccessfulHwPnoScanWithNoBackgroundScan() throws Exception {
1025        startServiceAndLoadDriver();
1026        Handler handler = mock(Handler.class);
1027        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1028        InOrder order = inOrder(handler, mWifiScannerImpl);
1029        int requestId = 12;
1030
1031        ScanResults scanResults = createScanResultsForPno();
1032        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1033                createScanSettingsForHwPno();
1034        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1035                createPnoSettings(scanResults);
1036
1037        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1038        expectHwPnoScanWithNoBackgroundScan(order, handler, requestId, pnoSettings.second,
1039                scanResults);
1040        verifyPnoNetworkFoundRecieved(order, handler, requestId, scanResults.getRawScanResults());
1041    }
1042
1043    /**
1044     * Tests Hal ePNO scan when the PNO scan results contain IE info. This ensures that the
1045     * PNO scan results are plumbed back to the client as a PNO network found event.
1046     */
1047    @Test
1048    public void testSuccessfulHwPnoScanWithBackgroundScan() throws Exception {
1049        startServiceAndLoadDriver();
1050        Handler handler = mock(Handler.class);
1051        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1052        InOrder order = inOrder(handler, mWifiScannerImpl);
1053        int requestId = 12;
1054
1055        ScanResults scanResults = createScanResultsForPno();
1056        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1057                createScanSettingsForHwPno();
1058        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1059                createPnoSettings(scanResults);
1060
1061        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1062        expectHwPnoScanWithBackgroundScan(order, handler, requestId, scanSettings.second,
1063                pnoSettings.second, scanResults);
1064        verifyPnoNetworkFoundRecieved(order, handler, requestId, scanResults.getRawScanResults());
1065    }
1066
1067    /**
1068     * Tests Hal ePNO scan when the PNO scan results don't contain IE info. This ensures that the
1069     * single scan results are plumbed back to the client as a PNO network found event.
1070     */
1071    @Test
1072    public void testSuccessfulHwPnoScanWithBackgroundScanWithNoIE() throws Exception {
1073        startServiceAndLoadDriver();
1074        Handler handler = mock(Handler.class);
1075        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1076        InOrder order = inOrder(handler, mWifiScannerImpl);
1077        int requestId = 12;
1078
1079        ScanResults scanResults = createScanResultsForPnoWithNoIE();
1080        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1081                createScanSettingsForHwPno();
1082        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1083                createPnoSettings(scanResults);
1084
1085        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1086        expectHwPnoScanWithBackgroundScanWithNoIE(order, handler, requestId, scanSettings.second,
1087                computeSingleScanNativeSettings(scanSettings.first), pnoSettings.second,
1088                scanResults);
1089
1090        ArrayList<ScanResult> sortScanList =
1091                new ArrayList<ScanResult>(Arrays.asList(scanResults.getRawScanResults()));
1092        Collections.sort(sortScanList, WifiScannerImpl.SCAN_RESULT_SORT_COMPARATOR);
1093        verifyPnoNetworkFoundRecieved(order, handler, requestId,
1094                sortScanList.toArray(new ScanResult[sortScanList.size()]));
1095    }
1096
1097    /**
1098     * Tests SW PNO scan. This ensures that the background scan results are plumbed back to the
1099     * client as a PNO network found event.
1100     */
1101    @Test
1102    public void testSuccessfulSwPnoScan() throws Exception {
1103        startServiceAndLoadDriver();
1104        Handler handler = mock(Handler.class);
1105        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1106        InOrder order = inOrder(handler, mWifiScannerImpl);
1107        int requestId = 12;
1108
1109        ScanResults scanResults = createScanResultsForPno();
1110        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1111                createScanSettingsForSwPno();
1112        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1113                createPnoSettings(scanResults);
1114
1115        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1116        expectSwPnoScan(order, scanSettings.second, scanResults);
1117        verifyPnoNetworkFoundRecieved(order, handler, requestId, scanResults.getRawScanResults());
1118    }
1119}
1120