WifiScanningServiceTest.java revision c9c91fd93350151a33d87fca768921520c256256
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.app.test.MockAnswerUtil.AnswerWithArguments;
26import android.app.test.TestAlarmManager;
27import android.content.BroadcastReceiver;
28import android.content.Context;
29import android.content.Intent;
30import android.content.IntentFilter;
31import android.net.wifi.ScanResult;
32import android.net.wifi.WifiManager;
33import android.net.wifi.WifiScanner;
34import android.os.Binder;
35import android.os.Bundle;
36import android.os.Handler;
37import android.os.Looper;
38import android.os.Message;
39import android.os.RemoteException;
40import android.os.UserHandle;
41import android.os.WorkSource;
42import android.os.test.TestLooper;
43import android.test.suitebuilder.annotation.SmallTest;
44import android.util.Pair;
45
46import com.android.internal.app.IBatteryStats;
47import com.android.internal.util.AsyncChannel;
48import com.android.internal.util.Protocol;
49import com.android.internal.util.test.BidirectionalAsyncChannel;
50import com.android.server.wifi.Clock;
51import com.android.server.wifi.ScanResults;
52import com.android.server.wifi.TestUtil;
53import com.android.server.wifi.WifiInjector;
54import com.android.server.wifi.WifiMetrics;
55import com.android.server.wifi.WifiMetricsProto;
56import com.android.server.wifi.WifiNative;
57
58import org.junit.After;
59import org.junit.Before;
60import org.junit.Test;
61import org.mockito.ArgumentCaptor;
62import org.mockito.InOrder;
63import org.mockito.Mock;
64import org.mockito.MockitoAnnotations;
65import org.mockito.internal.matchers.CapturingMatcher;
66
67import java.io.FileDescriptor;
68import java.io.PrintWriter;
69import java.io.StringWriter;
70import java.util.ArrayList;
71import java.util.Arrays;
72import java.util.Collections;
73import java.util.List;
74import java.util.regex.Pattern;
75
76/**
77 * Unit tests for {@link com.android.server.wifi.scanner.WifiScanningServiceImpl}.
78 */
79@SmallTest
80public class WifiScanningServiceTest {
81    public static final String TAG = "WifiScanningServiceTest";
82
83    @Mock Context mContext;
84    TestAlarmManager mAlarmManager;
85    @Mock WifiScannerImpl mWifiScannerImpl;
86    @Mock WifiScannerImpl.WifiScannerImplFactory mWifiScannerImplFactory;
87    @Mock IBatteryStats mBatteryStats;
88    @Mock WifiInjector mWifiInjector;
89    @Mock Clock mClock;
90    WifiMetrics mWifiMetrics;
91    TestLooper mLooper;
92    WifiScanningServiceImpl mWifiScanningServiceImpl;
93
94
95    @Before
96    public void setUp() throws Exception {
97        MockitoAnnotations.initMocks(this);
98
99        mAlarmManager = new TestAlarmManager();
100        when(mContext.getSystemService(Context.ALARM_SERVICE))
101                .thenReturn(mAlarmManager.getAlarmManager());
102        mWifiMetrics = new WifiMetrics(mClock);
103
104        ChannelHelper channelHelper = new PresetKnownBandsChannelHelper(
105                new int[]{2400, 2450},
106                new int[]{5150, 5175},
107                new int[]{5600, 5650, 5660});
108
109        mLooper = new TestLooper();
110        when(mWifiScannerImplFactory
111                .create(any(Context.class), any(Looper.class), any(Clock.class)))
112                .thenReturn(mWifiScannerImpl);
113        when(mWifiScannerImpl.getChannelHelper()).thenReturn(channelHelper);
114        when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
115        mWifiScanningServiceImpl = new WifiScanningServiceImpl(mContext, mLooper.getLooper(),
116                mWifiScannerImplFactory, mBatteryStats, mWifiInjector);
117    }
118
119    @After
120    public void cleanup() {
121        validateMockitoUsage();
122    }
123
124    /**
125     * Internal BroadcastReceiver that WifiScanningServiceImpl uses to listen for broadcasts
126     * this is initialized by calling startServiceAndLoadDriver
127     */
128    BroadcastReceiver mBroadcastReceiver;
129
130    private WifiScanner.ScanSettings generateValidScanSettings() {
131        return createRequest(WifiScanner.WIFI_BAND_BOTH, 30000, 0, 20,
132                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
133    }
134
135    private BidirectionalAsyncChannel connectChannel(Handler handler) {
136        BidirectionalAsyncChannel controlChannel = new BidirectionalAsyncChannel();
137        controlChannel.connect(mLooper.getLooper(), mWifiScanningServiceImpl.getMessenger(),
138                handler);
139        mLooper.dispatchAll();
140        controlChannel.assertConnected();
141        return controlChannel;
142    }
143
144    private static Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler) {
145        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
146        order.verify(handler).handleMessage(messageCaptor.capture());
147        return messageCaptor.getValue();
148    }
149
150    private static Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler,
151            final int what) {
152        CapturingMatcher<Message> messageMatcher = new CapturingMatcher<Message>() {
153            public boolean matches(Object argument) {
154                Message message = (Message) argument;
155                return message.what == what;
156            }
157        };
158        order.verify(handler).handleMessage(argThat(messageMatcher));
159        return messageMatcher.getLastValue();
160    }
161
162    private static void verifyScanResultsReceived(InOrder order, Handler handler, int listenerId,
163            WifiScanner.ScanData... expected) {
164        Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler,
165                WifiScanner.CMD_SCAN_RESULT);
166        assertScanResultsMessage(listenerId, expected, scanResultMessage);
167    }
168
169    private static void assertScanResultsMessage(int listenerId, WifiScanner.ScanData[] expected,
170            Message scanResultMessage) {
171        assertEquals("what", WifiScanner.CMD_SCAN_RESULT, scanResultMessage.what);
172        assertEquals("listenerId", listenerId, scanResultMessage.arg2);
173        assertScanDatasEquals(expected,
174                ((WifiScanner.ParcelableScanData) scanResultMessage.obj).getResults());
175    }
176
177    private static void verifySingleScanCompletedReceived(InOrder order, Handler handler,
178            int listenerId) {
179        Message completedMessage = verifyHandleMessageAndGetMessage(order, handler,
180                WifiScanner.CMD_SINGLE_SCAN_COMPLETED);
181        assertSingleScanCompletedMessage(listenerId, completedMessage);
182    }
183
184    private static void assertSingleScanCompletedMessage(int listenerId, Message completedMessage) {
185        assertEquals("what", WifiScanner.CMD_SINGLE_SCAN_COMPLETED, completedMessage.what);
186        assertEquals("listenerId", listenerId, completedMessage.arg2);
187    }
188
189    private static void sendBackgroundScanRequest(BidirectionalAsyncChannel controlChannel,
190            int scanRequestId, WifiScanner.ScanSettings settings, WorkSource workSource) {
191        Bundle scanParams = new Bundle();
192        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
193        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
194        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_BACKGROUND_SCAN, 0,
195                        scanRequestId, scanParams));
196    }
197
198    private static void sendSingleScanRequest(BidirectionalAsyncChannel controlChannel,
199            int scanRequestId, WifiScanner.ScanSettings settings, WorkSource workSource) {
200        Bundle scanParams = new Bundle();
201        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
202        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
203        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_SINGLE_SCAN, 0,
204                        scanRequestId, scanParams));
205    }
206
207    private static void registerScanListener(BidirectionalAsyncChannel controlChannel,
208            int listenerRequestId) {
209        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_REGISTER_SCAN_LISTENER, 0,
210                        listenerRequestId, null));
211    }
212
213    private static void deregisterScanListener(BidirectionalAsyncChannel controlChannel,
214            int listenerRequestId) {
215        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_DEREGISTER_SCAN_LISTENER, 0,
216                        listenerRequestId, null));
217    }
218
219    private static void verifySuccessfulResponse(InOrder order, Handler handler, int arg2) {
220        Message response = verifyHandleMessageAndGetMessage(order, handler);
221        assertSuccessfulResponse(arg2, response);
222    }
223
224    private static void assertSuccessfulResponse(int arg2, Message response) {
225        if (response.what == WifiScanner.CMD_OP_FAILED) {
226            WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj;
227            fail("response indicates failure, reason=" + result.reason
228                    + ", description=" + result.description);
229        } else {
230            assertEquals("response.what", WifiScanner.CMD_OP_SUCCEEDED, response.what);
231            assertEquals("response.arg2", arg2, response.arg2);
232        }
233    }
234
235    /**
236     * If multiple results are expected for a single hardware scan then the order that they are
237     * dispatched is dependant on the order which they are iterated through internally. This
238     * function validates that the order is either one way or the other. A scan listener can
239     * optionally be provided as well and will be checked after the after the single scan requests.
240     */
241    private static void verifyMultipleSingleScanResults(InOrder handlerOrder, Handler handler,
242            int requestId1, ScanResults results1, int requestId2, ScanResults results2,
243            int listenerRequestId, ScanResults listenerResults) {
244        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
245        handlerOrder.verify(handler, times(listenerResults == null ? 4 : 5))
246                .handleMessage(messageCaptor.capture());
247        int firstListenerId = messageCaptor.getAllValues().get(0).arg2;
248        assertTrue(firstListenerId + " was neither " + requestId2 + " nor " + requestId1,
249                firstListenerId == requestId2 || firstListenerId == requestId1);
250        if (firstListenerId == requestId2) {
251            assertScanResultsMessage(requestId2,
252                    new WifiScanner.ScanData[] {results2.getScanData()},
253                    messageCaptor.getAllValues().get(0));
254            assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(1));
255            assertScanResultsMessage(requestId1,
256                    new WifiScanner.ScanData[] {results1.getScanData()},
257                    messageCaptor.getAllValues().get(2));
258            assertSingleScanCompletedMessage(requestId1, messageCaptor.getAllValues().get(3));
259            if (listenerResults != null) {
260                assertScanResultsMessage(listenerRequestId,
261                        new WifiScanner.ScanData[] {listenerResults.getScanData()},
262                        messageCaptor.getAllValues().get(4));
263            }
264        } else {
265            assertScanResultsMessage(requestId1,
266                    new WifiScanner.ScanData[] {results1.getScanData()},
267                    messageCaptor.getAllValues().get(0));
268            assertSingleScanCompletedMessage(requestId1, messageCaptor.getAllValues().get(1));
269            assertScanResultsMessage(requestId2,
270                    new WifiScanner.ScanData[] {results2.getScanData()},
271                    messageCaptor.getAllValues().get(2));
272            assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(3));
273            if (listenerResults != null) {
274                assertScanResultsMessage(listenerRequestId,
275                        new WifiScanner.ScanData[] {listenerResults.getScanData()},
276                        messageCaptor.getAllValues().get(4));
277            }
278        }
279    }
280
281    private static void verifyMultipleSingleScanResults(InOrder handlerOrder, Handler handler,
282            int requestId1, ScanResults results1, int requestId2, ScanResults results2) {
283        verifyMultipleSingleScanResults(handlerOrder, handler, requestId1, results1, requestId2,
284                results2, -1, null);
285    }
286
287    private static void verifyFailedResponse(InOrder order, Handler handler, int arg2,
288            int expectedErrorReason, String expectedErrorDescription) {
289        Message response = verifyHandleMessageAndGetMessage(order, handler);
290        assertFailedResponse(arg2, expectedErrorReason, expectedErrorDescription, response);
291    }
292
293    private static void assertFailedResponse(int arg2, int expectedErrorReason,
294            String expectedErrorDescription, Message response) {
295        if (response.what == WifiScanner.CMD_OP_SUCCEEDED) {
296            fail("response indicates success");
297        } else {
298            assertEquals("response.what", WifiScanner.CMD_OP_FAILED, response.what);
299            assertEquals("response.arg2", arg2, response.arg2);
300            WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj;
301            assertEquals("response.obj.reason",
302                    expectedErrorReason, result.reason);
303            assertEquals("response.obj.description",
304                    expectedErrorDescription, result.description);
305        }
306    }
307
308    private WifiNative.ScanEventHandler verifyStartSingleScan(InOrder order,
309            WifiNative.ScanSettings expected) {
310        ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor =
311                ArgumentCaptor.forClass(WifiNative.ScanSettings.class);
312        ArgumentCaptor<WifiNative.ScanEventHandler> scanEventHandlerCaptor =
313                ArgumentCaptor.forClass(WifiNative.ScanEventHandler.class);
314        order.verify(mWifiScannerImpl).startSingleScan(scanSettingsCaptor.capture(),
315                scanEventHandlerCaptor.capture());
316        assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue());
317        return scanEventHandlerCaptor.getValue();
318    }
319
320    private WifiNative.ScanEventHandler verifyStartBackgroundScan(InOrder order,
321            WifiNative.ScanSettings expected) {
322        ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor =
323                ArgumentCaptor.forClass(WifiNative.ScanSettings.class);
324        ArgumentCaptor<WifiNative.ScanEventHandler> scanEventHandlerCaptor =
325                ArgumentCaptor.forClass(WifiNative.ScanEventHandler.class);
326        order.verify(mWifiScannerImpl).startBatchedScan(scanSettingsCaptor.capture(),
327                scanEventHandlerCaptor.capture());
328        assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue());
329        return scanEventHandlerCaptor.getValue();
330    }
331
332    private static final int MAX_AP_PER_SCAN = 16;
333    private void startServiceAndLoadDriver() {
334        mWifiScanningServiceImpl.startService();
335        setupAndLoadDriver();
336    }
337
338    private void setupAndLoadDriver() {
339        when(mWifiScannerImpl.getScanCapabilities(any(WifiNative.ScanCapabilities.class)))
340                .thenAnswer(new AnswerWithArguments() {
341                        public boolean answer(WifiNative.ScanCapabilities capabilities) {
342                            capabilities.max_scan_cache_size = Integer.MAX_VALUE;
343                            capabilities.max_scan_buckets = 8;
344                            capabilities.max_ap_cache_per_scan = MAX_AP_PER_SCAN;
345                            capabilities.max_rssi_sample_size = 8;
346                            capabilities.max_scan_reporting_threshold = 10;
347                            capabilities.max_hotlist_bssids = 0;
348                            capabilities.max_significant_wifi_change_aps = 0;
349                            return true;
350                        }
351                    });
352        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
353                ArgumentCaptor.forClass(BroadcastReceiver.class);
354        verify(mContext)
355                .registerReceiver(broadcastReceiverCaptor.capture(), any(IntentFilter.class));
356        mBroadcastReceiver = broadcastReceiverCaptor.getValue();
357        TestUtil.sendWifiScanAvailable(broadcastReceiverCaptor.getValue(), mContext,
358                WifiManager.WIFI_STATE_ENABLED);
359        mLooper.dispatchAll();
360    }
361
362    private String dumpService() {
363        StringWriter stringWriter = new StringWriter();
364        mWifiScanningServiceImpl.dump(new FileDescriptor(), new PrintWriter(stringWriter),
365                new String[0]);
366        return stringWriter.toString();
367    }
368
369    private void assertDumpContainsRequestLog(String type, int id) {
370        String serviceDump = dumpService();
371        Pattern logLineRegex = Pattern.compile("^.+" + type
372                + ": ClientInfo\\[uid=\\d+,android\\.os\\.Messenger@[a-f0-9]+\\],Id=" + id
373                + ".*$", Pattern.MULTILINE);
374        assertTrue("dump did not contain log with type=" + type + ", id=" + id +
375                ": " + serviceDump + "\n",
376                logLineRegex.matcher(serviceDump).find());
377    }
378
379    private void assertDumpContainsCallbackLog(String callback, int id, String extra) {
380        String serviceDump = dumpService();
381        String extraPattern = extra == null ? "" : "," + extra;
382        Pattern logLineRegex = Pattern.compile("^.+" + callback
383                + ": ClientInfo\\[uid=\\d+,android\\.os\\.Messenger@[a-f0-9]+\\],Id=" + id
384                + extraPattern + "$", Pattern.MULTILINE);
385        assertTrue("dump did not contain callback log with callback=" + callback + ", id=" + id +
386                ", extra=" + extra + ": " + serviceDump + "\n",
387                logLineRegex.matcher(serviceDump).find());
388    }
389
390    @Test
391    public void construct() throws Exception {
392        verifyNoMoreInteractions(mWifiScannerImpl, mWifiScannerImpl,
393                mWifiScannerImplFactory, mBatteryStats);
394        dumpService(); // make sure this succeeds
395    }
396
397    @Test
398    public void startService() throws Exception {
399        mWifiScanningServiceImpl.startService();
400        verifyNoMoreInteractions(mWifiScannerImplFactory);
401
402        Handler handler = mock(Handler.class);
403        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
404        InOrder order = inOrder(handler);
405        sendBackgroundScanRequest(controlChannel, 122, generateValidScanSettings(), null);
406        mLooper.dispatchAll();
407        verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available");
408    }
409
410    @Test
411    public void disconnectClientBeforeWifiEnabled() throws Exception {
412        mWifiScanningServiceImpl.startService();
413
414        BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class));
415        mLooper.dispatchAll();
416
417        controlChannel.disconnect();
418        mLooper.dispatchAll();
419    }
420
421    @Test
422    public void loadDriver() throws Exception {
423        startServiceAndLoadDriver();
424        verify(mWifiScannerImplFactory, times(1))
425                .create(any(Context.class), any(Looper.class), any(Clock.class));
426
427        Handler handler = mock(Handler.class);
428        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
429        InOrder order = inOrder(handler);
430        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
431                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
432        sendBackgroundScanRequest(controlChannel, 192, generateValidScanSettings(), null);
433        mLooper.dispatchAll();
434        verifySuccessfulResponse(order, handler, 192);
435        assertDumpContainsRequestLog("addBackgroundScanRequest", 192);
436    }
437
438    @Test
439    public void disconnectClientAfterStartingWifi() throws Exception {
440        mWifiScanningServiceImpl.startService();
441
442        BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class));
443        mLooper.dispatchAll();
444
445        setupAndLoadDriver();
446
447        controlChannel.disconnect();
448        mLooper.dispatchAll();
449    }
450
451    @Test
452    public void connectAndDisconnectClientAfterStartingWifi() throws Exception {
453        startServiceAndLoadDriver();
454
455        BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class));
456        mLooper.dispatchAll();
457        controlChannel.disconnect();
458        mLooper.dispatchAll();
459    }
460
461    @Test
462    public void sendInvalidCommand() throws Exception {
463        startServiceAndLoadDriver();
464
465        Handler handler = mock(Handler.class);
466        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
467        InOrder order = inOrder(handler, mWifiScannerImpl);
468        controlChannel.sendMessage(Message.obtain(null, Protocol.BASE_WIFI_MANAGER));
469        mLooper.dispatchAll();
470        verifyFailedResponse(order, handler, 0, WifiScanner.REASON_INVALID_REQUEST,
471                "Invalid request");
472    }
473
474    private void doSuccessfulSingleScan(WifiScanner.ScanSettings requestSettings,
475            WifiNative.ScanSettings nativeSettings, ScanResults results) throws RemoteException {
476        int requestId = 12;
477        WorkSource workSource = new WorkSource(2292);
478        startServiceAndLoadDriver();
479
480        Handler handler = mock(Handler.class);
481        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
482        InOrder order = inOrder(handler, mWifiScannerImpl);
483
484        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
485                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
486
487        sendSingleScanRequest(controlChannel, requestId, requestSettings, workSource);
488
489        mLooper.dispatchAll();
490        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings);
491        verifySuccessfulResponse(order, handler, requestId);
492        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource));
493
494        when(mWifiScannerImpl.getLatestSingleScanResults())
495                .thenReturn(results.getRawScanData());
496        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
497
498        mLooper.dispatchAll();
499        verifyScanResultsReceived(order, handler, requestId, results.getScanData());
500        verifySingleScanCompletedReceived(order, handler, requestId);
501        verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
502        verifyNoMoreInteractions(handler);
503        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource));
504        assertDumpContainsRequestLog("addSingleScanRequest", requestId);
505        assertDumpContainsCallbackLog("singleScanResults", requestId,
506                "results=" + results.getScanData().getResults().length);
507    }
508
509    /**
510     * Do a single scan for a band and verify that it is successful.
511     */
512    @Test
513    public void sendSingleScanBandRequest() throws Exception {
514        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
515                0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
516        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
517                ScanResults.create(0, true, 2400, 5150, 5175));
518    }
519
520    /**
521     * Do a single scan for a list of channels and verify that it is successful.
522     */
523    @Test
524    public void sendSingleScanChannelsRequest() throws Exception {
525        WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2400, 5150, 5175),
526                0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
527        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
528                ScanResults.create(0, 2400, 5150, 5175));
529    }
530
531    /**
532     * Do a single scan for a list of all channels and verify that it is successful.
533     */
534    @Test
535    public void sendSingleScanAllChannelsRequest() throws Exception {
536        WifiScanner.ScanSettings requestSettings = createRequest(
537                channelsToSpec(2400, 2450, 5150, 5175, 5600, 5650, 5660),
538                0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
539        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
540                ScanResults.create(0, true, 2400, 5150, 5175));
541    }
542
543    /**
544     * Do a single scan with no results and verify that it is successful.
545     */
546    @Test
547    public void sendSingleScanRequestWithNoResults() throws Exception {
548        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
549                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
550        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
551                ScanResults.create(0, new int[0]));
552    }
553
554    /**
555     * Do a single scan with results that do not match the requested scan and verify that it is
556     * still successful (and returns no results).
557     */
558    @Test
559    public void sendSingleScanRequestWithBadRawResults() throws Exception {
560        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_24_GHZ, 0,
561                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
562        // Create a set of scan results that has results not matching the request settings, but is
563        // limited to zero results for the expected results.
564        ScanResults results = ScanResults.createOverflowing(0, 0,
565                ScanResults.generateNativeResults(0, 5150, 5171));
566        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
567                results);
568    }
569
570    /**
571     * Do a single scan, which the hardware fails to start, and verify that a failure response is
572     * delivered.
573     */
574    @Test
575    public void sendSingleScanRequestWhichFailsToStart() throws Exception {
576        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
577                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
578        int requestId = 33;
579
580        startServiceAndLoadDriver();
581
582        Handler handler = mock(Handler.class);
583        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
584        InOrder order = inOrder(handler, mWifiScannerImpl);
585
586        // scan fails
587        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
588                        any(WifiNative.ScanEventHandler.class))).thenReturn(false);
589
590        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
591
592        mLooper.dispatchAll();
593        // Scan is successfully queue, but then fails to execute
594        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
595        order.verify(handler, times(2)).handleMessage(messageCaptor.capture());
596        assertSuccessfulResponse(requestId, messageCaptor.getAllValues().get(0));
597        assertFailedResponse(requestId, WifiScanner.REASON_UNSPECIFIED,
598                "Failed to start single scan", messageCaptor.getAllValues().get(1));
599        verifyNoMoreInteractions(mBatteryStats);
600
601        assertEquals(mWifiMetrics.getOneshotScanCount(), 1);
602        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1);
603        assertDumpContainsRequestLog("addSingleScanRequest", requestId);
604    }
605
606    /**
607     * Do a single scan, which successfully starts, but fails partway through and verify that a
608     * failure response is delivered.
609     */
610    @Test
611    public void sendSingleScanRequestWhichFailsAfterStart() throws Exception {
612        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
613                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
614        int requestId = 33;
615        WorkSource workSource = new WorkSource(Binder.getCallingUid()); // don't explicitly set
616
617        startServiceAndLoadDriver();
618
619        Handler handler = mock(Handler.class);
620        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
621        InOrder order = inOrder(handler, mWifiScannerImpl);
622
623        // successful start
624        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
625                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
626
627        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
628
629        // Scan is successfully queue
630        mLooper.dispatchAll();
631        WifiNative.ScanEventHandler eventHandler =
632                verifyStartSingleScan(order, computeSingleScanNativeSettings(requestSettings));
633        verifySuccessfulResponse(order, handler, requestId);
634        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource));
635
636        // but then fails to execute
637        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_FAILED);
638        mLooper.dispatchAll();
639        verifyFailedResponse(order, handler, requestId,
640                WifiScanner.REASON_UNSPECIFIED, "Scan failed");
641        assertDumpContainsCallbackLog("singleScanFailed", requestId,
642                "reason=" + WifiScanner.REASON_UNSPECIFIED + ", Scan failed");
643        assertEquals(mWifiMetrics.getOneshotScanCount(), 1);
644        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1);
645        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource));
646        verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
647    }
648
649    /**
650     * Send a single scan request and then disable Wi-Fi before it completes
651     */
652    @Test
653    public void sendSingleScanRequestThenDisableWifi() {
654        WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2400), 0,
655                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
656        int requestId = 2293;
657
658        startServiceAndLoadDriver();
659
660        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
661                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
662
663        Handler handler = mock(Handler.class);
664        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
665        InOrder order = inOrder(handler, mWifiScannerImpl);
666
667        // Run scan 1
668        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
669        mLooper.dispatchAll();
670        verifySuccessfulResponse(order, handler, requestId);
671
672        // disable wifi
673        TestUtil.sendWifiScanAvailable(mBroadcastReceiver, mContext,
674                WifiManager.WIFI_STATE_DISABLED);
675
676        // validate failed response
677        mLooper.dispatchAll();
678        verifyFailedResponse(order, handler, requestId, WifiScanner.REASON_UNSPECIFIED,
679                "Scan was interrupted");
680        verifyNoMoreInteractions(handler);
681    }
682
683    /**
684     * Send a single scan request, schedule a second pending scan and disable Wi-Fi before the first
685     * scan completes.
686     */
687    @Test
688    public void sendSingleScanAndPendingScanAndListenerThenDisableWifi() {
689        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
690                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
691        int requestId1 = 2293;
692
693        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450), 0,
694                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
695        int requestId2 = 2294;
696
697        int listenerRequestId = 2295;
698
699        startServiceAndLoadDriver();
700
701        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
702                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
703
704        Handler handler = mock(Handler.class);
705        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
706        InOrder order = inOrder(handler, mWifiScannerImpl);
707
708        // Request scan 1
709        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
710        mLooper.dispatchAll();
711        verifySuccessfulResponse(order, handler, requestId1);
712
713        // Request scan 2
714        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
715        mLooper.dispatchAll();
716        verifySuccessfulResponse(order, handler, requestId2);
717
718        // Setup scan listener
719        registerScanListener(controlChannel, listenerRequestId);
720        mLooper.dispatchAll();
721        verifySuccessfulResponse(order, handler, listenerRequestId);
722
723        // disable wifi
724        TestUtil.sendWifiScanAvailable(mBroadcastReceiver, mContext,
725                WifiManager.WIFI_STATE_DISABLED);
726
727        // validate failed response
728        mLooper.dispatchAll();
729        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
730        order.verify(handler, times(2)).handleMessage(messageCaptor.capture());
731        assertFailedResponse(requestId1, WifiScanner.REASON_UNSPECIFIED,
732                "Scan was interrupted", messageCaptor.getAllValues().get(0));
733        assertFailedResponse(requestId2, WifiScanner.REASON_UNSPECIFIED,
734                "Scan was interrupted", messageCaptor.getAllValues().get(1));
735        // No additional callbacks for scan listener
736        verifyNoMoreInteractions(handler);
737    }
738
739    /**
740     * Send a single scan request and then a second one after the first completes.
741     */
742    @Test
743    public void sendSingleScanRequestAfterPreviousCompletes() {
744        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
745                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
746        int requestId1 = 12;
747        ScanResults results1 = ScanResults.create(0, 2400);
748
749
750        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
751                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
752        int requestId2 = 13;
753        ScanResults results2 = ScanResults.create(0, 2450);
754
755
756        startServiceAndLoadDriver();
757
758        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
759                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
760
761        Handler handler = mock(Handler.class);
762        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
763        InOrder order = inOrder(handler, mWifiScannerImpl, mContext);
764
765        // Run scan 1
766        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
767
768        mLooper.dispatchAll();
769        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(order,
770                computeSingleScanNativeSettings(requestSettings1));
771        verifySuccessfulResponse(order, handler, requestId1);
772
773        // dispatch scan 1 results
774        when(mWifiScannerImpl.getLatestSingleScanResults())
775                .thenReturn(results1.getScanData());
776        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
777
778        mLooper.dispatchAll();
779        // Note: The order of the following verification calls looks out of order if you compare to
780        // the source code of WifiScanningServiceImpl WifiSingleScanStateMachine.reportScanResults.
781        // This is due to the fact that verifyScanResultsReceived and
782        // verifySingleScanCompletedReceived require an additional call to handle the message that
783        // is created in reportScanResults.  This handling is done in the two verify*Received calls
784        // that is run AFTER the reportScanResults method in WifiScanningServiceImpl completes.
785        order.verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
786        verifyScanResultsReceived(order, handler, requestId1, results1.getScanData());
787        verifySingleScanCompletedReceived(order, handler, requestId1);
788
789        // Run scan 2
790        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
791
792        mLooper.dispatchAll();
793        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(order,
794                computeSingleScanNativeSettings(requestSettings2));
795        verifySuccessfulResponse(order, handler, requestId2);
796
797        // dispatch scan 2 results
798        when(mWifiScannerImpl.getLatestSingleScanResults())
799                .thenReturn(results2.getScanData());
800        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
801
802        mLooper.dispatchAll();
803        order.verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
804        verifyScanResultsReceived(order, handler, requestId2, results2.getScanData());
805        verifySingleScanCompletedReceived(order, handler, requestId2);
806    }
807
808    /**
809     * Send a single scan request and then a second one not satisfied by the first before the first
810     * completes. Verify that both are scheduled and succeed.
811     */
812    @Test
813    public void sendSingleScanRequestWhilePreviousScanRunning() {
814        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
815                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
816        int requestId1 = 12;
817        ScanResults results1 = ScanResults.create(0, 2400);
818
819        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
820                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
821        int requestId2 = 13;
822        ScanResults results2 = ScanResults.create(0, 2450);
823
824
825        startServiceAndLoadDriver();
826
827        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
828                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
829
830        Handler handler = mock(Handler.class);
831        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
832        InOrder handlerOrder = inOrder(handler);
833        InOrder nativeOrder = inOrder(mWifiScannerImpl);
834
835        // Run scan 1
836        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
837
838        mLooper.dispatchAll();
839        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
840                computeSingleScanNativeSettings(requestSettings1));
841        verifySuccessfulResponse(handlerOrder, handler, requestId1);
842
843        // Queue scan 2 (will not run because previous is in progress)
844        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
845        mLooper.dispatchAll();
846        verifySuccessfulResponse(handlerOrder, handler, requestId2);
847
848        // dispatch scan 1 results
849        when(mWifiScannerImpl.getLatestSingleScanResults())
850                .thenReturn(results1.getScanData());
851        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
852
853        mLooper.dispatchAll();
854        verifyScanResultsReceived(handlerOrder, handler, requestId1, results1.getScanData());
855        verifySingleScanCompletedReceived(handlerOrder, handler, requestId1);
856        verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
857
858        // now that the first scan completed we expect the second one to start
859        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(nativeOrder,
860                computeSingleScanNativeSettings(requestSettings2));
861
862        // dispatch scan 2 results
863        when(mWifiScannerImpl.getLatestSingleScanResults())
864                .thenReturn(results2.getScanData());
865        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
866
867        mLooper.dispatchAll();
868        verifyScanResultsReceived(handlerOrder, handler, requestId2, results2.getScanData());
869        verifySingleScanCompletedReceived(handlerOrder, handler, requestId2);
870        verify(mContext, times(2)).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
871        assertEquals(mWifiMetrics.getOneshotScanCount(), 2);
872        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 2);
873    }
874
875
876    /**
877     * Send a single scan request and then two more before the first completes. Neither are
878     * satisfied by the first scan. Verify that the first completes and the second two are merged.
879     */
880    @Test
881    public void sendMultipleSingleScanRequestWhilePreviousScanRunning() throws RemoteException {
882        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
883                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
884        int requestId1 = 12;
885        WorkSource workSource1 = new WorkSource(1121);
886        ScanResults results1 = ScanResults.create(0, 2400);
887
888        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
889                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
890        int requestId2 = 13;
891        WorkSource workSource2 = new WorkSource(Binder.getCallingUid()); // don't explicitly set
892        ScanResults results2 = ScanResults.create(0, 2450, 5175, 2450);
893
894        WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(5150), 0,
895                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
896        int requestId3 = 15;
897        WorkSource workSource3 = new WorkSource(2292);
898        ScanResults results3 = ScanResults.create(0, 5150, 5150, 5150, 5150);
899
900        WifiNative.ScanSettings nativeSettings2and3 = createSingleScanNativeSettingsForChannels(
901                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, channelsToSpec(2450, 5175, 5150));
902        ScanResults results2and3 = ScanResults.merge(results2, results3);
903        WorkSource workSource2and3 = new WorkSource();
904        workSource2and3.add(workSource2);
905        workSource2and3.add(workSource3);
906
907
908        startServiceAndLoadDriver();
909
910        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
911                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
912
913        Handler handler = mock(Handler.class);
914        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
915        InOrder handlerOrder = inOrder(handler);
916        InOrder nativeOrder = inOrder(mWifiScannerImpl);
917
918        // Run scan 1
919        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, workSource1);
920
921        mLooper.dispatchAll();
922        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
923                computeSingleScanNativeSettings(requestSettings1));
924        verifySuccessfulResponse(handlerOrder, handler, requestId1);
925        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource1));
926
927
928        // Queue scan 2 (will not run because previous is in progress)
929        // uses uid of calling process
930        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
931        mLooper.dispatchAll();
932        verifySuccessfulResponse(handlerOrder, handler, requestId2);
933
934        // Queue scan 3 (will not run because previous is in progress)
935        sendSingleScanRequest(controlChannel, requestId3, requestSettings3, workSource3);
936        mLooper.dispatchAll();
937        verifySuccessfulResponse(handlerOrder, handler, requestId3);
938
939        // dispatch scan 1 results
940        when(mWifiScannerImpl.getLatestSingleScanResults())
941                .thenReturn(results1.getScanData());
942        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
943
944        mLooper.dispatchAll();
945        verifyScanResultsReceived(handlerOrder, handler, requestId1, results1.getScanData());
946        verifySingleScanCompletedReceived(handlerOrder, handler, requestId1);
947        verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
948        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource1));
949        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource2and3));
950
951        // now that the first scan completed we expect the second and third ones to start
952        WifiNative.ScanEventHandler eventHandler2and3 = verifyStartSingleScan(nativeOrder,
953                nativeSettings2and3);
954
955        // dispatch scan 2 and 3 results
956        when(mWifiScannerImpl.getLatestSingleScanResults())
957                .thenReturn(results2and3.getScanData());
958        eventHandler2and3.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
959
960        mLooper.dispatchAll();
961
962        verifyMultipleSingleScanResults(handlerOrder, handler, requestId2, results2, requestId3,
963                results3);
964        assertEquals(mWifiMetrics.getOneshotScanCount(), 3);
965        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 3);
966
967        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource2and3));
968
969        assertDumpContainsRequestLog("addSingleScanRequest", requestId1);
970        assertDumpContainsRequestLog("addSingleScanRequest", requestId2);
971        assertDumpContainsRequestLog("addSingleScanRequest", requestId3);
972        assertDumpContainsCallbackLog("singleScanResults", requestId1,
973                "results=" + results1.getRawScanResults().length);
974        assertDumpContainsCallbackLog("singleScanResults", requestId2,
975                "results=" + results2.getRawScanResults().length);
976        assertDumpContainsCallbackLog("singleScanResults", requestId3,
977                "results=" + results3.getRawScanResults().length);
978    }
979
980
981    /**
982     * Send a single scan request and then a second one satisfied by the first before the first
983     * completes. Verify that only one scan is scheduled.
984     */
985    @Test
986    public void sendSingleScanRequestWhilePreviousScanRunningAndMergeIntoFirstScan() {
987        // Split by frequency to make it easier to determine which results each request is expecting
988        ScanResults results24GHz = ScanResults.create(0, 2400, 2400, 2400, 2450);
989        ScanResults results5GHz = ScanResults.create(0, 5150, 5150, 5175);
990        ScanResults resultsBoth = ScanResults.merge(results24GHz, results5GHz);
991
992        WifiScanner.ScanSettings requestSettings1 = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
993                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
994        int requestId1 = 12;
995        ScanResults results1 = resultsBoth;
996
997        WifiScanner.ScanSettings requestSettings2 = createRequest(WifiScanner.WIFI_BAND_24_GHZ, 0,
998                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
999        int requestId2 = 13;
1000        ScanResults results2 = results24GHz;
1001
1002
1003        startServiceAndLoadDriver();
1004
1005        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1006                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1007
1008        Handler handler = mock(Handler.class);
1009        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1010        InOrder handlerOrder = inOrder(handler);
1011        InOrder nativeOrder = inOrder(mWifiScannerImpl);
1012
1013        // Run scan 1
1014        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
1015
1016        mLooper.dispatchAll();
1017        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(nativeOrder,
1018                computeSingleScanNativeSettings(requestSettings1));
1019        verifySuccessfulResponse(handlerOrder, handler, requestId1);
1020
1021        // Queue scan 2 (will be folded into ongoing scan)
1022        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
1023        mLooper.dispatchAll();
1024        verifySuccessfulResponse(handlerOrder, handler, requestId2);
1025
1026        // dispatch scan 1 results
1027        when(mWifiScannerImpl.getLatestSingleScanResults())
1028                .thenReturn(resultsBoth.getScanData());
1029        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1030
1031        mLooper.dispatchAll();
1032        verifyMultipleSingleScanResults(handlerOrder, handler, requestId1, results1, requestId2,
1033                results2);
1034
1035        assertEquals(mWifiMetrics.getOneshotScanCount(), 2);
1036        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 2);
1037    }
1038
1039    /**
1040     * Send a single scan request and then two more before the first completes, one of which is
1041     * satisfied by the first scan. Verify that the first two complete together the second scan is
1042     * just for the other scan.
1043     */
1044    @Test
1045    public void sendMultipleSingleScanRequestWhilePreviousScanRunningAndMergeOneIntoFirstScan()
1046          throws RemoteException {
1047        // Split by frequency to make it easier to determine which results each request is expecting
1048        ScanResults results2400 = ScanResults.create(0, 2400, 2400, 2400);
1049        ScanResults results2450 = ScanResults.create(0, 2450);
1050        ScanResults results1and3 = ScanResults.merge(results2400, results2450);
1051
1052        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400, 2450), 0,
1053                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1054        int requestId1 = 12;
1055        WorkSource workSource1 = new WorkSource(1121);
1056        ScanResults results1 = results1and3;
1057
1058        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
1059                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1060        int requestId2 = 13;
1061        WorkSource workSource2 = new WorkSource(Binder.getCallingUid()); // don't explicitly set
1062        ScanResults results2 = ScanResults.create(0, 2450, 5175, 2450);
1063
1064        WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(2400), 0,
1065                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1066        int requestId3 = 15;
1067        WorkSource workSource3 = new WorkSource(2292);
1068        ScanResults results3 = results2400;
1069
1070        startServiceAndLoadDriver();
1071
1072        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1073                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1074
1075        Handler handler = mock(Handler.class);
1076        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1077        InOrder handlerOrder = inOrder(handler);
1078        InOrder nativeOrder = inOrder(mWifiScannerImpl);
1079
1080        // Run scan 1
1081        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, workSource1);
1082
1083        mLooper.dispatchAll();
1084        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
1085                computeSingleScanNativeSettings(requestSettings1));
1086        verifySuccessfulResponse(handlerOrder, handler, requestId1);
1087        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource1));
1088
1089
1090        // Queue scan 2 (will not run because previous is in progress)
1091        // uses uid of calling process
1092        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
1093        mLooper.dispatchAll();
1094        verifySuccessfulResponse(handlerOrder, handler, requestId2);
1095
1096        // Queue scan 3 (will be merged into the active scan)
1097        sendSingleScanRequest(controlChannel, requestId3, requestSettings3, workSource3);
1098        mLooper.dispatchAll();
1099        verifySuccessfulResponse(handlerOrder, handler, requestId3);
1100
1101        // dispatch scan 1 results
1102        when(mWifiScannerImpl.getLatestSingleScanResults())
1103                .thenReturn(results1and3.getScanData());
1104        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1105
1106        mLooper.dispatchAll();
1107        verifyMultipleSingleScanResults(handlerOrder, handler, requestId1, results1, requestId3,
1108                results3);
1109        // only the requests know at the beginning of the scan get blamed
1110        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource1));
1111        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource2));
1112
1113        // now that the first scan completed we expect the second and third ones to start
1114        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(nativeOrder,
1115                computeSingleScanNativeSettings(requestSettings2));
1116
1117        // dispatch scan 2 and 3 results
1118        when(mWifiScannerImpl.getLatestSingleScanResults())
1119                .thenReturn(results2.getScanData());
1120        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1121
1122        mLooper.dispatchAll();
1123
1124        verifyScanResultsReceived(handlerOrder, handler, requestId2, results2.getScanData());
1125        verifySingleScanCompletedReceived(handlerOrder, handler, requestId2);
1126        verify(mContext, times(2)).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
1127        assertEquals(mWifiMetrics.getOneshotScanCount(), 3);
1128        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 3);
1129
1130        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource2));
1131
1132        assertDumpContainsRequestLog("addSingleScanRequest", requestId1);
1133        assertDumpContainsRequestLog("addSingleScanRequest", requestId2);
1134        assertDumpContainsRequestLog("addSingleScanRequest", requestId3);
1135        assertDumpContainsCallbackLog("singleScanResults", requestId1,
1136                "results=" + results1.getRawScanResults().length);
1137        assertDumpContainsCallbackLog("singleScanResults", requestId2,
1138                "results=" + results2.getRawScanResults().length);
1139        assertDumpContainsCallbackLog("singleScanResults", requestId3,
1140                "results=" + results3.getRawScanResults().length);
1141    }
1142
1143    /**
1144     * Verify that WifiService provides a way to get the most recent SingleScan results.
1145     */
1146    @Test
1147    public void retrieveSingleScanResults() throws Exception {
1148        WifiScanner.ScanSettings requestSettings =
1149                createRequest(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
1150                              0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1151        ScanResults expectedResults = ScanResults.create(0, true, 2400, 5150, 5175);
1152        doSuccessfulSingleScan(requestSettings,
1153                               computeSingleScanNativeSettings(requestSettings),
1154                               expectedResults);
1155        Handler handler = mock(Handler.class);
1156        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1157        InOrder order = inOrder(handler, mWifiScannerImpl);
1158
1159        controlChannel.sendMessage(
1160                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1161        mLooper.dispatchAll();
1162        Message response = verifyHandleMessageAndGetMessage(order, handler);
1163        List<ScanResult> results = Arrays.asList(
1164                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1165        assertEquals(results.size(), expectedResults.getRawScanResults().length);
1166    }
1167
1168    /**
1169     * Verify that WifiService provides a way to get the most recent SingleScan results even when
1170     * they are empty.
1171     */
1172    @Test
1173    public void retrieveSingleScanResultsEmpty() throws Exception {
1174        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1175                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1176        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
1177                ScanResults.create(0, new int[0]));
1178
1179        Handler handler = mock(Handler.class);
1180        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1181        InOrder order = inOrder(handler, mWifiScannerImpl);
1182
1183        controlChannel.sendMessage(
1184                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1185        mLooper.dispatchAll();
1186        Message response = verifyHandleMessageAndGetMessage(order, handler);
1187
1188        List<ScanResult> results = Arrays.asList(
1189                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1190        assertEquals(results.size(), 0);
1191    }
1192
1193    /**
1194     * Verify that WifiService will return empty SingleScan results if a scan has not been
1195     * performed.
1196     */
1197    @Test
1198    public void retrieveSingleScanResultsBeforeAnySingleScans() throws Exception {
1199        startServiceAndLoadDriver();
1200        Handler handler = mock(Handler.class);
1201        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1202        InOrder order = inOrder(handler, mWifiScannerImpl);
1203
1204        controlChannel.sendMessage(
1205                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1206        mLooper.dispatchAll();
1207        Message response = verifyHandleMessageAndGetMessage(order, handler);
1208
1209        List<ScanResult> results = Arrays.asList(
1210                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1211        assertEquals(results.size(), 0);
1212    }
1213
1214    /**
1215     * Verify that the newest scan results are returned by WifiService.getSingleScanResults.
1216     */
1217    @Test
1218    public void retrieveMostRecentSingleScanResults() throws Exception {
1219        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1220                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1221        ScanResults expectedResults = ScanResults.create(0, true, 2400, 5150, 5175);
1222        doSuccessfulSingleScan(requestSettings,
1223                               computeSingleScanNativeSettings(requestSettings),
1224                               expectedResults);
1225
1226        Handler handler = mock(Handler.class);
1227        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1228        InOrder order = inOrder(handler, mWifiScannerImpl);
1229
1230        controlChannel.sendMessage(
1231                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1232        mLooper.dispatchAll();
1233        Message response = verifyHandleMessageAndGetMessage(order, handler);
1234
1235        List<ScanResult> results = Arrays.asList(
1236                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1237        assertEquals(results.size(), expectedResults.getRawScanResults().length);
1238
1239        // now update with a new scan that only has one result
1240        int secondScanRequestId = 35;
1241        ScanResults expectedSingleResult = ScanResults.create(0, true, 5150);
1242        sendSingleScanRequest(controlChannel, secondScanRequestId, requestSettings, null);
1243
1244        mLooper.dispatchAll();
1245        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order,
1246                computeSingleScanNativeSettings(requestSettings));
1247        verifySuccessfulResponse(order, handler, secondScanRequestId);
1248
1249        // dispatch scan 2 results
1250        when(mWifiScannerImpl.getLatestSingleScanResults())
1251                .thenReturn(expectedSingleResult.getScanData());
1252        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1253
1254        mLooper.dispatchAll();
1255        verifyScanResultsReceived(order, handler, secondScanRequestId,
1256                expectedSingleResult.getScanData());
1257        verifySingleScanCompletedReceived(order, handler, secondScanRequestId);
1258
1259        controlChannel.sendMessage(
1260                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1261        mLooper.dispatchAll();
1262        Message response2 = verifyHandleMessageAndGetMessage(order, handler);
1263
1264        List<ScanResult> results2 = Arrays.asList(
1265                ((WifiScanner.ParcelableScanResults) response2.obj).getResults());
1266        assertEquals(results2.size(), expectedSingleResult.getRawScanResults().length);
1267    }
1268
1269    /**
1270     * Cached scan results should be cleared after the driver is unloaded.
1271     */
1272    @Test
1273    public void validateScanResultsClearedAfterDriverUnloaded() throws Exception {
1274        WifiScanner.ScanSettings requestSettings =
1275                createRequest(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
1276                              0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1277        ScanResults expectedResults = ScanResults.create(0, true, 2400, 5150, 5175);
1278        doSuccessfulSingleScan(requestSettings,
1279                               computeSingleScanNativeSettings(requestSettings),
1280                               expectedResults);
1281        Handler handler = mock(Handler.class);
1282        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1283        InOrder order = inOrder(handler, mWifiScannerImpl);
1284
1285        controlChannel.sendMessage(
1286                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1287        mLooper.dispatchAll();
1288        Message response = verifyHandleMessageAndGetMessage(order, handler);
1289        List<ScanResult> results = Arrays.asList(
1290                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1291        assertEquals(results.size(), expectedResults.getRawScanResults().length);
1292
1293        // disable wifi
1294        TestUtil.sendWifiScanAvailable(mBroadcastReceiver,
1295                                       mContext,
1296                                       WifiManager.WIFI_STATE_DISABLED);
1297        // Now get scan results again. The returned list should be empty since we
1298        // clear the cache when exiting the DriverLoaded state.
1299        controlChannel.sendMessage(
1300                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1301        mLooper.dispatchAll();
1302        Message response2 = verifyHandleMessageAndGetMessage(order, handler);
1303        List<ScanResult> results2 = Arrays.asList(
1304                ((WifiScanner.ParcelableScanResults) response2.obj).getResults());
1305        assertEquals(results2.size(), 0);
1306    }
1307
1308    /**
1309     * Register a single scan listener and do a single scan
1310     */
1311    @Test
1312    public void registerScanListener() throws Exception {
1313        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1314                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1315        WifiNative.ScanSettings nativeSettings = computeSingleScanNativeSettings(requestSettings);
1316        ScanResults results = ScanResults.create(0, 2400, 5150, 5175);
1317
1318        int requestId = 12;
1319        int listenerRequestId = 13;
1320
1321        startServiceAndLoadDriver();
1322
1323        Handler handler = mock(Handler.class);
1324        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1325        InOrder order = inOrder(handler, mWifiScannerImpl);
1326
1327        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1328                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1329
1330        registerScanListener(controlChannel, listenerRequestId);
1331        mLooper.dispatchAll();
1332        verifySuccessfulResponse(order, handler, listenerRequestId);
1333
1334        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
1335
1336        mLooper.dispatchAll();
1337        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings);
1338        verifySuccessfulResponse(order, handler, requestId);
1339
1340        when(mWifiScannerImpl.getLatestSingleScanResults())
1341                .thenReturn(results.getRawScanData());
1342        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1343
1344        mLooper.dispatchAll();
1345        verifyScanResultsReceived(order, handler, requestId, results.getScanData());
1346        verifySingleScanCompletedReceived(order, handler, requestId);
1347        verifyScanResultsReceived(order, handler, listenerRequestId, results.getScanData());
1348        verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
1349        verifyNoMoreInteractions(handler);
1350
1351        assertDumpContainsRequestLog("registerScanListener", listenerRequestId);
1352        assertDumpContainsCallbackLog("singleScanResults", listenerRequestId,
1353                "results=" + results.getScanData().getResults().length);
1354    }
1355
1356    /**
1357     * Register a single scan listener and do a single scan
1358     */
1359    @Test
1360    public void deregisterScanListener() throws Exception {
1361        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1362                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1363        WifiNative.ScanSettings nativeSettings = computeSingleScanNativeSettings(requestSettings);
1364        ScanResults results = ScanResults.create(0, 2400, 5150, 5175);
1365
1366        int requestId = 12;
1367        int listenerRequestId = 13;
1368
1369        startServiceAndLoadDriver();
1370
1371        Handler handler = mock(Handler.class);
1372        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1373        InOrder order = inOrder(handler, mWifiScannerImpl);
1374
1375        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1376                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1377
1378        registerScanListener(controlChannel, listenerRequestId);
1379        mLooper.dispatchAll();
1380        verifySuccessfulResponse(order, handler, listenerRequestId);
1381
1382        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
1383
1384        mLooper.dispatchAll();
1385        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings);
1386        verifySuccessfulResponse(order, handler, requestId);
1387
1388        deregisterScanListener(controlChannel, listenerRequestId);
1389        mLooper.dispatchAll();
1390
1391        when(mWifiScannerImpl.getLatestSingleScanResults())
1392                .thenReturn(results.getRawScanData());
1393        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1394
1395        mLooper.dispatchAll();
1396        verifyScanResultsReceived(order, handler, requestId, results.getScanData());
1397        verifySingleScanCompletedReceived(order, handler, requestId);
1398        verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
1399        verifyNoMoreInteractions(handler);
1400
1401        assertDumpContainsRequestLog("registerScanListener", listenerRequestId);
1402        assertDumpContainsRequestLog("deregisterScanListener", listenerRequestId);
1403    }
1404
1405    /**
1406     * Send a single scan request and then two more before the first completes. Neither are
1407     * satisfied by the first scan. Verify that the first completes and the second two are merged.
1408     */
1409    @Test
1410    public void scanListenerReceivesAllResults() throws RemoteException {
1411        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
1412                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1413        int requestId1 = 12;
1414        ScanResults results1 = ScanResults.create(0, 2400);
1415
1416        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
1417                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1418        int requestId2 = 13;
1419        ScanResults results2 = ScanResults.create(0, 2450, 5175, 2450);
1420
1421        WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(5150), 0,
1422                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1423        int requestId3 = 15;
1424        ScanResults results3 = ScanResults.create(0, 5150, 5150, 5150, 5150);
1425
1426        WifiNative.ScanSettings nativeSettings2and3 = createSingleScanNativeSettingsForChannels(
1427                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, channelsToSpec(2450, 5175, 5150));
1428        ScanResults results2and3 = ScanResults.merge(results2, results3);
1429
1430        int listenerRequestId = 13;
1431
1432
1433        startServiceAndLoadDriver();
1434
1435        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1436                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1437
1438        Handler handler = mock(Handler.class);
1439        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1440        InOrder handlerOrder = inOrder(handler);
1441        InOrder nativeOrder = inOrder(mWifiScannerImpl);
1442
1443        // Run scan 1
1444        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
1445
1446        mLooper.dispatchAll();
1447        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
1448                computeSingleScanNativeSettings(requestSettings1));
1449        verifySuccessfulResponse(handlerOrder, handler, requestId1);
1450
1451
1452        // Queue scan 2 (will not run because previous is in progress)
1453        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
1454        mLooper.dispatchAll();
1455        verifySuccessfulResponse(handlerOrder, handler, requestId2);
1456
1457        // Queue scan 3 (will not run because previous is in progress)
1458        sendSingleScanRequest(controlChannel, requestId3, requestSettings3, null);
1459        mLooper.dispatchAll();
1460        verifySuccessfulResponse(handlerOrder, handler, requestId3);
1461
1462        // Register scan listener
1463        registerScanListener(controlChannel, listenerRequestId);
1464        mLooper.dispatchAll();
1465        verifySuccessfulResponse(handlerOrder, handler, listenerRequestId);
1466
1467        // dispatch scan 1 results
1468        when(mWifiScannerImpl.getLatestSingleScanResults())
1469                .thenReturn(results1.getScanData());
1470        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1471
1472        mLooper.dispatchAll();
1473        verifyScanResultsReceived(handlerOrder, handler, requestId1, results1.getScanData());
1474        verifySingleScanCompletedReceived(handlerOrder, handler, requestId1);
1475        verifyScanResultsReceived(handlerOrder, handler, listenerRequestId, results1.getScanData());
1476        verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
1477
1478        // now that the first scan completed we expect the second and third ones to start
1479        WifiNative.ScanEventHandler eventHandler2and3 = verifyStartSingleScan(nativeOrder,
1480                nativeSettings2and3);
1481
1482        // dispatch scan 2 and 3 results
1483        when(mWifiScannerImpl.getLatestSingleScanResults())
1484                .thenReturn(results2and3.getScanData());
1485        eventHandler2and3.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1486
1487        mLooper.dispatchAll();
1488
1489        verifyMultipleSingleScanResults(handlerOrder, handler, requestId2, results2, requestId3,
1490                results3, listenerRequestId, results2and3);
1491
1492        assertDumpContainsRequestLog("registerScanListener", listenerRequestId);
1493        assertDumpContainsCallbackLog("singleScanResults", listenerRequestId,
1494                "results=" + results1.getRawScanResults().length);
1495        assertDumpContainsCallbackLog("singleScanResults", listenerRequestId,
1496                "results=" + results2and3.getRawScanResults().length);
1497    }
1498
1499
1500    private void doSuccessfulBackgroundScan(WifiScanner.ScanSettings requestSettings,
1501            WifiNative.ScanSettings nativeSettings) {
1502        startServiceAndLoadDriver();
1503
1504        Handler handler = mock(Handler.class);
1505        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1506        InOrder order = inOrder(handler, mWifiScannerImpl);
1507
1508        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
1509                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1510
1511        sendBackgroundScanRequest(controlChannel, 12, requestSettings, null);
1512        mLooper.dispatchAll();
1513        verifyStartBackgroundScan(order, nativeSettings);
1514        verifySuccessfulResponse(order, handler, 12);
1515        verifyNoMoreInteractions(handler);
1516        assertDumpContainsRequestLog("addBackgroundScanRequest", 12);
1517    }
1518
1519    /**
1520     * Do a background scan for a band and verify that it is successful.
1521     */
1522    @Test
1523    public void sendBackgroundScanBandRequest() throws Exception {
1524        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 30000,
1525                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1526        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
1527                .withBasePeriod(30000)
1528                .withMaxApPerScan(MAX_AP_PER_SCAN)
1529                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
1530                .addBucketWithBand(30000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
1531                        WifiScanner.WIFI_BAND_BOTH)
1532                .build();
1533        doSuccessfulBackgroundScan(requestSettings, nativeSettings);
1534        assertEquals(mWifiMetrics.getBackgroundScanCount(), 1);
1535    }
1536
1537    /**
1538     * Do a background scan for a list of channels and verify that it is successful.
1539     */
1540    @Test
1541    public void sendBackgroundScanChannelsRequest() throws Exception {
1542        WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(5150), 30000,
1543                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1544        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
1545                .withBasePeriod(30000)
1546                .withMaxApPerScan(MAX_AP_PER_SCAN)
1547                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
1548                .addBucketWithChannels(30000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5150)
1549                .build();
1550        doSuccessfulBackgroundScan(requestSettings, nativeSettings);
1551    }
1552
1553    private Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> createScanSettingsForHwPno()
1554            throws Exception {
1555        WifiScanner.ScanSettings requestSettings = createRequest(
1556                channelsToSpec(0, 2400, 5150, 5175), 30000, 0, 20,
1557                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1558        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
1559                .withBasePeriod(30000)
1560                .withMaxApPerScan(MAX_AP_PER_SCAN)
1561                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
1562                .addBucketWithChannels(30000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
1563                        0, 2400, 5150, 5175)
1564                .build();
1565        return Pair.create(requestSettings, nativeSettings);
1566    }
1567
1568    private Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> createScanSettingsForSwPno()
1569            throws Exception {
1570        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> settingsPair =
1571                createScanSettingsForHwPno();
1572
1573        WifiScanner.ScanSettings requestSettings = settingsPair.first;
1574        WifiNative.ScanSettings nativeSettings = settingsPair.second;
1575        // reportEvents field is overridden for SW PNO
1576        for (int i = 0; i < nativeSettings.buckets.length; i++) {
1577            nativeSettings.buckets[i].report_events = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
1578                    | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
1579        }
1580        return Pair.create(requestSettings, nativeSettings);
1581    }
1582
1583    private Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> createPnoSettings(
1584            ScanResults results)
1585            throws Exception {
1586        WifiScanner.PnoSettings requestPnoSettings = new WifiScanner.PnoSettings();
1587        requestPnoSettings.networkList =
1588                new WifiScanner.PnoSettings.PnoNetwork[results.getRawScanResults().length];
1589        int i = 0;
1590        for (ScanResult scanResult : results.getRawScanResults()) {
1591            requestPnoSettings.networkList[i++] =
1592                    new WifiScanner.PnoSettings.PnoNetwork(scanResult.SSID);
1593        }
1594
1595        WifiNative.PnoSettings nativePnoSettings = new WifiNative.PnoSettings();
1596        nativePnoSettings.min5GHzRssi = requestPnoSettings.min5GHzRssi;
1597        nativePnoSettings.min24GHzRssi = requestPnoSettings.min24GHzRssi;
1598        nativePnoSettings.initialScoreMax = requestPnoSettings.initialScoreMax;
1599        nativePnoSettings.currentConnectionBonus = requestPnoSettings.currentConnectionBonus;
1600        nativePnoSettings.sameNetworkBonus = requestPnoSettings.sameNetworkBonus;
1601        nativePnoSettings.secureBonus = requestPnoSettings.secureBonus;
1602        nativePnoSettings.band5GHzBonus = requestPnoSettings.band5GHzBonus;
1603        nativePnoSettings.isConnected = requestPnoSettings.isConnected;
1604        nativePnoSettings.networkList =
1605                new WifiNative.PnoNetwork[requestPnoSettings.networkList.length];
1606        for (i = 0; i < requestPnoSettings.networkList.length; i++) {
1607            nativePnoSettings.networkList[i] = new WifiNative.PnoNetwork();
1608            nativePnoSettings.networkList[i].ssid = requestPnoSettings.networkList[i].ssid;
1609            nativePnoSettings.networkList[i].flags = requestPnoSettings.networkList[i].flags;
1610            nativePnoSettings.networkList[i].auth_bit_field =
1611                    requestPnoSettings.networkList[i].authBitField;
1612        }
1613        return Pair.create(requestPnoSettings, nativePnoSettings);
1614    }
1615
1616    private ScanResults createScanResultsForPno() {
1617        return ScanResults.create(0, 2400, 5150, 5175);
1618    }
1619
1620    private ScanResults createScanResultsForPnoWithNoIE() {
1621        return ScanResults.createWithNoIE(0, 2400, 5150, 5175);
1622    }
1623
1624    private WifiNative.PnoEventHandler verifyHwPno(InOrder order,
1625            WifiNative.PnoSettings expected) {
1626        ArgumentCaptor<WifiNative.PnoSettings> pnoSettingsCaptor =
1627                ArgumentCaptor.forClass(WifiNative.PnoSettings.class);
1628        ArgumentCaptor<WifiNative.PnoEventHandler> pnoEventHandlerCaptor =
1629                ArgumentCaptor.forClass(WifiNative.PnoEventHandler.class);
1630        order.verify(mWifiScannerImpl).setHwPnoList(pnoSettingsCaptor.capture(),
1631                pnoEventHandlerCaptor.capture());
1632        assertNativePnoSettingsEquals(expected, pnoSettingsCaptor.getValue());
1633        return pnoEventHandlerCaptor.getValue();
1634    }
1635
1636    private void sendPnoScanRequest(BidirectionalAsyncChannel controlChannel,
1637            int scanRequestId, WifiScanner.ScanSettings scanSettings,
1638            WifiScanner.PnoSettings pnoSettings) {
1639        Bundle pnoParams = new Bundle();
1640        scanSettings.isPnoScan = true;
1641        pnoParams.putParcelable(WifiScanner.PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings);
1642        pnoParams.putParcelable(WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings);
1643        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_PNO_SCAN, 0,
1644                scanRequestId, pnoParams));
1645    }
1646
1647    private void assertPnoNetworkFoundMessage(int listenerId, ScanResult[] expected,
1648            Message networkFoundMessage) {
1649        assertEquals("what", WifiScanner.CMD_PNO_NETWORK_FOUND, networkFoundMessage.what);
1650        assertEquals("listenerId", listenerId, networkFoundMessage.arg2);
1651        assertScanResultsEquals(expected,
1652                ((WifiScanner.ParcelableScanResults) networkFoundMessage.obj).getResults());
1653    }
1654
1655    private void verifyPnoNetworkFoundReceived(InOrder order, Handler handler, int listenerId,
1656            ScanResult[] expected) {
1657        Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler,
1658                WifiScanner.CMD_PNO_NETWORK_FOUND);
1659        assertPnoNetworkFoundMessage(listenerId, expected, scanResultMessage);
1660    }
1661
1662    private void expectSuccessfulBackgroundScan(InOrder order,
1663            WifiNative.ScanSettings nativeSettings, ScanResults results) {
1664        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
1665                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1666        mLooper.dispatchAll();
1667        WifiNative.ScanEventHandler eventHandler = verifyStartBackgroundScan(order, nativeSettings);
1668        WifiScanner.ScanData[] scanDatas = new WifiScanner.ScanData[1];
1669        scanDatas[0] = results.getScanData();
1670        for (ScanResult fullScanResult : results.getRawScanResults()) {
1671            eventHandler.onFullScanResult(fullScanResult, 0);
1672        }
1673        when(mWifiScannerImpl.getLatestBatchedScanResults(anyBoolean())).thenReturn(scanDatas);
1674        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1675        mLooper.dispatchAll();
1676    }
1677
1678    private void expectHwPnoScanWithNoBackgroundScan(InOrder order, Handler handler, int requestId,
1679            WifiNative.PnoSettings nativeSettings, ScanResults results) {
1680        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(true);
1681        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(false);
1682
1683        when(mWifiScannerImpl.setHwPnoList(any(WifiNative.PnoSettings.class),
1684                any(WifiNative.PnoEventHandler.class))).thenReturn(true);
1685        mLooper.dispatchAll();
1686        WifiNative.PnoEventHandler eventHandler = verifyHwPno(order, nativeSettings);
1687        verifySuccessfulResponse(order, handler, requestId);
1688        eventHandler.onPnoNetworkFound(results.getRawScanResults());
1689        mLooper.dispatchAll();
1690    }
1691
1692    private void expectHwPnoScanWithBackgroundScan(InOrder order, Handler handler, int requestId,
1693            WifiNative.ScanSettings nativeScanSettings,
1694            WifiNative.PnoSettings nativePnoSettings, ScanResults results) {
1695        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(true);
1696        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(true);
1697
1698        when(mWifiScannerImpl.setHwPnoList(any(WifiNative.PnoSettings.class),
1699                any(WifiNative.PnoEventHandler.class))).thenReturn(true);
1700        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
1701                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1702        mLooper.dispatchAll();
1703        WifiNative.PnoEventHandler eventHandler = verifyHwPno(order, nativePnoSettings);
1704        verifySuccessfulResponse(order, handler, requestId);
1705        verifyStartBackgroundScan(order, nativeScanSettings);
1706        eventHandler.onPnoNetworkFound(results.getRawScanResults());
1707        mLooper.dispatchAll();
1708    }
1709
1710    private void expectHwPnoScanWithBackgroundScanWithNoIE(InOrder order, Handler handler,
1711            int requestId, WifiNative.ScanSettings nativeBackgroundScanSettings,
1712            WifiNative.ScanSettings nativeSingleScanSettings,
1713            WifiNative.PnoSettings nativePnoSettings, ScanResults results) {
1714        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1715                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1716
1717        expectHwPnoScanWithBackgroundScan(order, handler, requestId, nativeBackgroundScanSettings,
1718                nativePnoSettings, results);
1719        WifiNative.ScanEventHandler eventHandler =
1720                verifyStartSingleScan(order, nativeSingleScanSettings);
1721        when(mWifiScannerImpl.getLatestSingleScanResults()).thenReturn(results.getScanData());
1722        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1723        mLooper.dispatchAll();
1724    }
1725    private void expectSwPnoScan(InOrder order, WifiNative.ScanSettings nativeScanSettings,
1726            ScanResults results) {
1727        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(false);
1728        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(true);
1729
1730        expectSuccessfulBackgroundScan(order, nativeScanSettings, results);
1731    }
1732
1733    /**
1734     * Tests Supplicant PNO scan when the PNO scan results contain IE info. This ensures that the
1735     * PNO scan results are plumbed back to the client as a PNO network found event.
1736     */
1737    @Test
1738    public void testSuccessfulHwPnoScanWithNoBackgroundScan() throws Exception {
1739        startServiceAndLoadDriver();
1740        Handler handler = mock(Handler.class);
1741        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1742        InOrder order = inOrder(handler, mWifiScannerImpl);
1743        int requestId = 12;
1744
1745        ScanResults scanResults = createScanResultsForPno();
1746        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1747                createScanSettingsForHwPno();
1748        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1749                createPnoSettings(scanResults);
1750
1751        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1752        expectHwPnoScanWithNoBackgroundScan(order, handler, requestId, pnoSettings.second,
1753                scanResults);
1754        verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults());
1755    }
1756
1757    /**
1758     * Tests Hal ePNO scan when the PNO scan results contain IE info. This ensures that the
1759     * PNO scan results are plumbed back to the client as a PNO network found event.
1760     */
1761    @Test
1762    public void testSuccessfulHwPnoScanWithBackgroundScan() throws Exception {
1763        startServiceAndLoadDriver();
1764        Handler handler = mock(Handler.class);
1765        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1766        InOrder order = inOrder(handler, mWifiScannerImpl);
1767        int requestId = 12;
1768
1769        ScanResults scanResults = createScanResultsForPno();
1770        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1771                createScanSettingsForHwPno();
1772        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1773                createPnoSettings(scanResults);
1774
1775        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1776        expectHwPnoScanWithBackgroundScan(order, handler, requestId, scanSettings.second,
1777                pnoSettings.second, scanResults);
1778        verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults());
1779    }
1780
1781    /**
1782     * Tests Hal ePNO scan when the PNO scan results don't contain IE info. This ensures that the
1783     * single scan results are plumbed back to the client as a PNO network found event.
1784     */
1785    @Test
1786    public void testSuccessfulHwPnoScanWithBackgroundScanWithNoIE() throws Exception {
1787        startServiceAndLoadDriver();
1788        Handler handler = mock(Handler.class);
1789        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1790        InOrder order = inOrder(handler, mWifiScannerImpl);
1791        int requestId = 12;
1792
1793        ScanResults scanResults = createScanResultsForPnoWithNoIE();
1794        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1795                createScanSettingsForHwPno();
1796        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1797                createPnoSettings(scanResults);
1798
1799        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1800        expectHwPnoScanWithBackgroundScanWithNoIE(order, handler, requestId, scanSettings.second,
1801                computeSingleScanNativeSettings(scanSettings.first), pnoSettings.second,
1802                scanResults);
1803
1804        ArrayList<ScanResult> sortScanList =
1805                new ArrayList<ScanResult>(Arrays.asList(scanResults.getRawScanResults()));
1806        Collections.sort(sortScanList, WifiScannerImpl.SCAN_RESULT_SORT_COMPARATOR);
1807        verifyPnoNetworkFoundReceived(order, handler, requestId,
1808                sortScanList.toArray(new ScanResult[sortScanList.size()]));
1809    }
1810
1811    /**
1812     * Tests SW PNO scan. This ensures that the background scan results are plumbed back to the
1813     * client as a PNO network found event.
1814     */
1815    @Test
1816    public void testSuccessfulSwPnoScan() throws Exception {
1817        startServiceAndLoadDriver();
1818        Handler handler = mock(Handler.class);
1819        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1820        InOrder order = inOrder(handler, mWifiScannerImpl);
1821        int requestId = 12;
1822
1823        ScanResults scanResults = createScanResultsForPno();
1824        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1825                createScanSettingsForSwPno();
1826        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1827                createPnoSettings(scanResults);
1828
1829        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1830        expectSwPnoScan(order, scanSettings.second, scanResults);
1831        verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults());
1832    }
1833
1834    /**
1835     * Tries to simulate the race scenario where a client is disconnected immediately after single
1836     * scan request is sent to |SingleScanStateMachine|.
1837     */
1838    @Test
1839    public void processSingleScanRequestAfterDisconnect() throws Exception {
1840        startServiceAndLoadDriver();
1841        BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class));
1842        mLooper.dispatchAll();
1843
1844        // Send the single scan request and then send the disconnect immediately after.
1845        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1846                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1847        int requestId = 10;
1848
1849        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
1850        // Can't call |disconnect| here because that sends |CMD_CHANNEL_DISCONNECT| followed by
1851        // |CMD_CHANNEL_DISCONNECTED|.
1852        controlChannel.sendMessage(Message.obtain(null, AsyncChannel.CMD_CHANNEL_DISCONNECTED,
1853                        AsyncChannel.STATUS_REMOTE_DISCONNECTION, 0, null));
1854
1855        // Now process the above 2 actions. This should result in first processing the single scan
1856        // request (which forwards the request to SingleScanStateMachine) and then processing the
1857        // disconnect after.
1858        mLooper.dispatchAll();
1859
1860        // Now check that we logged the invalid request.
1861        String serviceDump = dumpService();
1862        Pattern logLineRegex = Pattern.compile("^.+" + "singleScanInvalidRequest: "
1863                + "ClientInfo\\[unknown\\],Id=" + requestId + ",bad request$", Pattern.MULTILINE);
1864        assertTrue("dump did not contain log with ClientInfo[unknown]: " + serviceDump + "\n",
1865                logLineRegex.matcher(serviceDump).find());
1866    }
1867
1868    /**
1869     * Tries to simulate the race scenario where a client is disconnected immediately after single
1870     * scan request is sent to |SingleScanStateMachine|.
1871     */
1872    @Test
1873    public void sendScanRequestAfterUnsuccessfulSend() throws Exception {
1874        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1875                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1876        int requestId = 9;
1877
1878        startServiceAndLoadDriver();
1879        Handler handler = mock(Handler.class);
1880        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1881        mLooper.dispatchAll();
1882
1883        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1884                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1885        ScanResults results = ScanResults.create(0, 2400);
1886        when(mWifiScannerImpl.getLatestSingleScanResults())
1887                .thenReturn(results.getRawScanData());
1888
1889        InOrder order = inOrder(mWifiScannerImpl, handler);
1890
1891        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
1892        mLooper.dispatchAll();
1893        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(order,
1894                computeSingleScanNativeSettings(requestSettings));
1895        verifySuccessfulResponse(order, handler, requestId);
1896
1897        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1898        mLooper.dispatchAll();
1899        verifyScanResultsReceived(order, handler, requestId, results.getScanData());
1900        verifySingleScanCompletedReceived(order, handler, requestId);
1901        verifyNoMoreInteractions(handler);
1902
1903        controlChannel.sendMessage(Message.obtain(null, AsyncChannel.CMD_CHANNEL_DISCONNECTED,
1904                        AsyncChannel.STATUS_SEND_UNSUCCESSFUL, 0, null));
1905        mLooper.dispatchAll();
1906
1907        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
1908        mLooper.dispatchAll();
1909        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(order,
1910                computeSingleScanNativeSettings(requestSettings));
1911        verifySuccessfulResponse(order, handler, requestId);
1912
1913        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1914        mLooper.dispatchAll();
1915        verifyScanResultsReceived(order, handler, requestId, results.getScanData());
1916        verifySingleScanCompletedReceived(order, handler, requestId);
1917        verifyNoMoreInteractions(handler);
1918    }
1919}
1920