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