blob: 4a1d3929604ef2057c24644d46c08555dfce8967 [file] [log] [blame]
Ajay Nadathur7d176bc2016-10-24 16:55:24 -07001/*
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 */
16package com.android.settingslib.wifi;
17
Sundeep Ghuman2b489902017-02-22 18:17:29 -080018import static com.google.common.truth.Truth.assertThat;
19
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080020import static org.junit.Assert.assertEquals;
Stephen Chen21f68682017-04-04 13:23:31 -070021import static org.junit.Assert.assertFalse;
Ajay Nadathur7d176bc2016-10-24 16:55:24 -070022import static org.junit.Assert.assertTrue;
Sundeep Ghuman71f4a822017-04-18 19:51:46 -070023import static org.junit.Assert.fail;
Peter Qiuf5628382017-03-28 13:24:34 -070024import static org.mockito.Mockito.any;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080025import static org.mockito.Mockito.anyInt;
Sundeep Ghuman71f4a822017-04-18 19:51:46 -070026import static org.mockito.Mockito.atMost;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080027import static org.mockito.Mockito.doAnswer;
28import static org.mockito.Mockito.doNothing;
Peter Qiuf5628382017-03-28 13:24:34 -070029import static org.mockito.Mockito.doThrow;
Sundeep Ghumance6bab82017-04-19 16:21:46 -070030import static org.mockito.Mockito.mock;
Sundeep Ghumand4a79ac2017-06-07 18:11:39 -070031import static org.mockito.Mockito.never;
Sundeep Ghumance6bab82017-04-19 16:21:46 -070032import static org.mockito.Mockito.times;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080033import static org.mockito.Mockito.verify;
Sundeep Ghuman71f4a822017-04-18 19:51:46 -070034import static org.mockito.Mockito.verifyNoMoreInteractions;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080035import static org.mockito.Mockito.when;
36
37import android.content.Context;
38import android.content.Intent;
Eric Schwarzenbach5e0535e2017-08-16 15:47:33 -070039import android.content.IntentFilter;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080040import android.net.ConnectivityManager;
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -070041import android.net.Network;
Sundeep Ghuman2b489902017-02-22 18:17:29 -080042import android.net.NetworkInfo;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080043import android.net.NetworkKey;
44import android.net.NetworkScoreManager;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080045import android.net.RssiCurve;
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -070046import android.net.ScoredNetwork;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080047import android.net.WifiKey;
Ajay Nadathur7d176bc2016-10-24 16:55:24 -070048import android.net.wifi.ScanResult;
49import android.net.wifi.WifiConfiguration;
Sundeep Ghuman2b489902017-02-22 18:17:29 -080050import android.net.wifi.WifiInfo;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080051import android.net.wifi.WifiManager;
52import android.net.wifi.WifiNetworkScoreCache;
53import android.net.wifi.WifiSsid;
54import android.os.Bundle;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080055import android.os.Handler;
56import android.os.HandlerThread;
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -070057import android.os.SystemClock;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080058import android.provider.Settings;
Ajay Nadathur7d176bc2016-10-24 16:55:24 -070059import android.support.test.InstrumentationRegistry;
60import android.support.test.filters.SmallTest;
61import android.support.test.runner.AndroidJUnit4;
Sundeep Ghuman266b4092017-06-16 15:12:56 -070062import android.support.test.filters.FlakyTest;
Ajay Nadathur7d176bc2016-10-24 16:55:24 -070063
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080064import org.junit.After;
65import org.junit.Before;
Ajay Nadathur7d176bc2016-10-24 16:55:24 -070066import org.junit.Test;
67import org.junit.runner.RunWith;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080068import org.mockito.ArgumentCaptor;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080069import org.mockito.Captor;
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -070070import org.mockito.Matchers;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080071import org.mockito.Mock;
72import org.mockito.MockitoAnnotations;
73import org.mockito.invocation.InvocationOnMock;
74import org.mockito.stubbing.Answer;
75
Ajay Nadathur7d176bc2016-10-24 16:55:24 -070076import java.util.ArrayList;
77import java.util.Arrays;
78import java.util.BitSet;
79import java.util.List;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080080import java.util.concurrent.CountDownLatch;
81import java.util.concurrent.TimeUnit;
Ajay Nadathur7d176bc2016-10-24 16:55:24 -070082
Sundeep Ghuman2b489902017-02-22 18:17:29 -080083// TODO(sghuman): Change these to robolectric tests b/35766684.
84
Ajay Nadathur7d176bc2016-10-24 16:55:24 -070085@SmallTest
86@RunWith(AndroidJUnit4.class)
87public class WifiTrackerTest {
88
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080089 private static final String TAG = "WifiTrackerTest";
Sundeep Ghumanac7b4362017-02-08 17:19:27 -080090 private static final int LATCH_TIMEOUT = 4000;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080091
92 private static final String SSID_1 = "ssid1";
93 private static final String BSSID_1 = "00:00:00:00:00:00";
94 private static final NetworkKey NETWORK_KEY_1 =
95 new NetworkKey(new WifiKey('"' + SSID_1 + '"', BSSID_1));
96 private static final int RSSI_1 = -30;
97 private static final byte SCORE_1 = 10;
Sundeep Ghuman53200ed2017-06-21 16:54:36 -070098 private static final int BADGE_1 = AccessPoint.Speed.MODERATE;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080099
100 private static final String SSID_2 = "ssid2";
101 private static final String BSSID_2 = "AA:AA:AA:AA:AA:AA";
102 private static final NetworkKey NETWORK_KEY_2 =
103 new NetworkKey(new WifiKey('"' + SSID_2 + '"', BSSID_2));
104 private static final int RSSI_2 = -30;
105 private static final byte SCORE_2 = 15;
Sundeep Ghuman53200ed2017-06-21 16:54:36 -0700106 private static final int BADGE_2 = AccessPoint.Speed.FAST;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800107
Sundeep Ghumandb9b94c2017-09-06 11:46:21 -0700108 // TODO(b/65594609): Convert mutable Data objects to instance variables / builder pattern
109 private static final int NETWORK_ID_1 = 123;
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700110 private static final int CONNECTED_RSSI = -50;
111 private static final WifiInfo CONNECTED_AP_1_INFO = new WifiInfo();
112 static {
113 CONNECTED_AP_1_INFO.setSSID(WifiSsid.createFromAsciiEncoded(SSID_1));
114 CONNECTED_AP_1_INFO.setBSSID(BSSID_1);
Sundeep Ghumandb9b94c2017-09-06 11:46:21 -0700115 CONNECTED_AP_1_INFO.setNetworkId(NETWORK_ID_1);
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700116 CONNECTED_AP_1_INFO.setRssi(CONNECTED_RSSI);
117 }
Sundeep Ghumandb9b94c2017-09-06 11:46:21 -0700118 private static final WifiConfiguration CONFIGURATION_1 = new WifiConfiguration();
119 static {
120 CONFIGURATION_1.SSID = SSID_1;
121 CONFIGURATION_1.BSSID = BSSID_1;
122 CONFIGURATION_1.networkId = NETWORK_ID_1;
123 }
124
125 private static final int NETWORK_ID_2 = 2;
126 private static final WifiConfiguration CONFIGURATION_2 = new WifiConfiguration();
127 static {
128 CONFIGURATION_2.SSID = SSID_2;
129 CONFIGURATION_2.BSSID = BSSID_2;
130 CONFIGURATION_2.networkId = NETWORK_ID_2;
131 }
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700132
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800133 @Captor ArgumentCaptor<WifiNetworkScoreCache> mScoreCacheCaptor;
134 @Mock private ConnectivityManager mockConnectivityManager;
135 @Mock private NetworkScoreManager mockNetworkScoreManager;
136 @Mock private RssiCurve mockCurve1;
137 @Mock private RssiCurve mockCurve2;
138 @Mock private RssiCurve mockBadgeCurve1;
139 @Mock private RssiCurve mockBadgeCurve2;
140 @Mock private WifiManager mockWifiManager;
141 @Mock private WifiTracker.WifiListener mockWifiListener;
142
143 private final List<NetworkKey> mRequestedKeys = new ArrayList<>();
144
145 private Context mContext;
146 private CountDownLatch mAccessPointsChangedLatch;
147 private CountDownLatch mRequestScoresLatch;
148 private Handler mScannerHandler;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800149 private HandlerThread mWorkerThread;
Sundeep Ghuman42058742017-07-21 18:42:10 -0700150
Sundeep Ghumane869d832017-01-25 16:23:43 -0800151 private int mOriginalScoringUiSettingValue;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800152
153 @Before
154 public void setUp() {
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800155 MockitoAnnotations.initMocks(this);
156
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800157 mContext = InstrumentationRegistry.getTargetContext();
158
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800159 mWorkerThread = new HandlerThread("TestHandlerWorkerThread");
160 mWorkerThread.start();
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800161
162 // Make sure the scanner doesn't try to run on the testing thread.
163 HandlerThread scannerThread = new HandlerThread("ScannerWorkerThread");
164 scannerThread.start();
165 mScannerHandler = new Handler(scannerThread.getLooper());
166
167 when(mockWifiManager.isWifiEnabled()).thenReturn(true);
168 when(mockWifiManager.getScanResults())
169 .thenReturn(Arrays.asList(buildScanResult1(), buildScanResult2()));
Sundeep Ghumandb9b94c2017-09-06 11:46:21 -0700170 when(mockWifiManager.getConfiguredNetworks())
171 .thenReturn(Arrays.asList(CONFIGURATION_1, CONFIGURATION_2));
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800172
173
174 when(mockCurve1.lookupScore(RSSI_1)).thenReturn(SCORE_1);
175 when(mockCurve2.lookupScore(RSSI_2)).thenReturn(SCORE_2);
176
177 when(mockBadgeCurve1.lookupScore(RSSI_1)).thenReturn((byte) BADGE_1);
178 when(mockBadgeCurve2.lookupScore(RSSI_2)).thenReturn((byte) BADGE_2);
179
180 doNothing()
181 .when(mockNetworkScoreManager)
182 .registerNetworkScoreCache(
183 anyInt(),
184 mScoreCacheCaptor.capture(),
185 Matchers.anyInt());
186
187 // Capture requested keys and count down latch if present
188 doAnswer(
189 new Answer<Boolean>() {
190 @Override
191 public Boolean answer(InvocationOnMock input) {
192 if (mRequestScoresLatch != null) {
193 mRequestScoresLatch.countDown();
194 }
195 NetworkKey[] keys = (NetworkKey[]) input.getArguments()[0];
196 for (NetworkKey key : keys) {
197 mRequestedKeys.add(key);
198 }
199 return true;
200 }
201 }).when(mockNetworkScoreManager).requestScores(Matchers.<NetworkKey[]>any());
202
203 doAnswer(
204 new Answer<Void>() {
205 @Override
206 public Void answer (InvocationOnMock invocation) throws Throwable {
207 if (mAccessPointsChangedLatch != null) {
208 mAccessPointsChangedLatch.countDown();
209 }
210
211 return null;
212 }
213 }).when(mockWifiListener).onAccessPointsChanged();
214
Sundeep Ghumane869d832017-01-25 16:23:43 -0800215 // Turn on Scoring UI features
216 mOriginalScoringUiSettingValue = Settings.Global.getInt(
217 InstrumentationRegistry.getTargetContext().getContentResolver(),
218 Settings.Global.NETWORK_SCORING_UI_ENABLED,
219 0 /* disabled */);
220 Settings.Global.putInt(
221 InstrumentationRegistry.getTargetContext().getContentResolver(),
222 Settings.Global.NETWORK_SCORING_UI_ENABLED,
223 1 /* enabled */);
Sundeep Ghuman42058742017-07-21 18:42:10 -0700224
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800225 }
226
227 @After
228 public void cleanUp() {
229 Settings.Global.putInt(
Sundeep Ghumane869d832017-01-25 16:23:43 -0800230 InstrumentationRegistry.getTargetContext().getContentResolver(),
231 Settings.Global.NETWORK_SCORING_UI_ENABLED,
232 mOriginalScoringUiSettingValue);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800233 }
234
235 private static ScanResult buildScanResult1() {
236 return new ScanResult(
237 WifiSsid.createFromAsciiEncoded(SSID_1),
238 BSSID_1,
239 0, // hessid
240 0, //anqpDomainId
241 null, // osuProviders
242 "", // capabilities
243 RSSI_1,
244 0, // frequency
245 SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */);
246 }
247
248 private static ScanResult buildScanResult2() {
249 return new ScanResult(
250 WifiSsid.createFromAsciiEncoded(SSID_2),
251 BSSID_2,
252 0, // hessid
253 0, //anqpDomainId
254 null, // osuProviders
255 "", // capabilities
256 RSSI_2,
257 0, // frequency
258 SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */);
259 }
260
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800261 private WifiTracker createTrackerWithImmediateBroadcastsAndInjectInitialScanResults(
262 Intent ... intents)
263 throws InterruptedException {
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800264 WifiTracker tracker = createMockedWifiTracker();
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800265
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800266 startTracking(tracker);
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800267 for (Intent intent : intents) {
268 tracker.mReceiver.onReceive(mContext, intent);
269 }
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800270
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800271 sendScanResultsAndProcess(tracker);
Sundeep Ghumane8013092017-06-21 22:35:30 -0700272 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800273
274 return tracker;
275 }
276
277 private WifiTracker createMockedWifiTracker() {
Tony Mantler0edf09b2017-09-28 15:03:37 -0700278 final WifiTracker wifiTracker = new WifiTracker(
Eric Schwarzenbach5e0535e2017-08-16 15:47:33 -0700279 mContext,
280 mockWifiListener,
Eric Schwarzenbach5e0535e2017-08-16 15:47:33 -0700281 true,
282 true,
283 mockWifiManager,
284 mockConnectivityManager,
285 mockNetworkScoreManager,
Eric Schwarzenbach5e0535e2017-08-16 15:47:33 -0700286 new IntentFilter()); // empty filter to ignore system broadcasts
Tony Mantler0edf09b2017-09-28 15:03:37 -0700287 wifiTracker.setWorkThread(mWorkerThread);
288 return wifiTracker;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800289 }
290
291 private void startTracking(WifiTracker tracker) throws InterruptedException {
292 CountDownLatch latch = new CountDownLatch(1);
293 mScannerHandler.post(new Runnable() {
294 @Override
295 public void run() {
Tony Mantler0edf09b2017-09-28 15:03:37 -0700296 tracker.onStart();
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800297 latch.countDown();
298 }
299 });
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800300 assertTrue("Latch timed out", latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800301 }
302
303 private void sendScanResultsAndProcess(WifiTracker tracker) throws InterruptedException {
304 mAccessPointsChangedLatch = new CountDownLatch(1);
305 Intent i = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
306 tracker.mReceiver.onReceive(mContext, i);
307
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800308 assertTrue("Latch timed out",
309 mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800310 }
311
312 private void updateScores() {
313 Bundle attr1 = new Bundle();
314 attr1.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve1);
315 ScoredNetwork sc1 =
316 new ScoredNetwork(
317 NETWORK_KEY_1,
318 mockCurve1,
319 false /* meteredHint */,
320 attr1);
321
322 Bundle attr2 = new Bundle();
323 attr2.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve2);
324 ScoredNetwork sc2 =
325 new ScoredNetwork(
326 NETWORK_KEY_2,
327 mockCurve2,
Stephen Chen21f68682017-04-04 13:23:31 -0700328 true /* meteredHint */,
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800329 attr2);
330
331 WifiNetworkScoreCache scoreCache = mScoreCacheCaptor.getValue();
332 scoreCache.updateScores(Arrays.asList(sc1, sc2));
333 }
334
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800335 private WifiTracker createTrackerWithScanResultsAndAccessPoint1Connected()
336 throws InterruptedException {
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700337 when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO);
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800338
339 WifiConfiguration configuration = new WifiConfiguration();
340 configuration.SSID = SSID_1;
341 configuration.BSSID = BSSID_1;
Sundeep Ghumandb9b94c2017-09-06 11:46:21 -0700342 configuration.networkId = NETWORK_ID_1;
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800343
344 NetworkInfo networkInfo = new NetworkInfo(
345 ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
346 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
347
348 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
349 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
Sundeep Ghumandb2eabb2017-07-28 14:51:05 -0700350 WifiTracker tracker =
351 createTrackerWithImmediateBroadcastsAndInjectInitialScanResults(intent);
352 assertThat(tracker.isConnected()).isTrue();
353 return tracker;
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800354 }
355
Sundeep Ghumane8013092017-06-21 22:35:30 -0700356 private void waitForHandlersToProcessCurrentlyEnqueuedMessages(WifiTracker tracker)
357 throws InterruptedException {
358 CountDownLatch workerLatch = new CountDownLatch(1);
359 tracker.mWorkHandler.post(() -> {
360 workerLatch.countDown();
361 });
362 assertTrue("Latch timed out while waiting for WorkerHandler",
363 workerLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
364
365 CountDownLatch mainLatch = new CountDownLatch(1);
366 tracker.mMainHandler.post(() -> {
367 mainLatch.countDown();
368 });
369 assertTrue("Latch timed out while waiting for MainHandler",
370 mainLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
371 }
372
Sundeep Ghumandb9b94c2017-09-06 11:46:21 -0700373 private void switchToNetwork2(WifiTracker tracker) throws InterruptedException {
374 NetworkInfo networkInfo = new NetworkInfo(
375 ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
376 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "connecting", "test");
377
378 WifiInfo info = new WifiInfo();
379 info.setSSID(WifiSsid.createFromAsciiEncoded(SSID_2));
380 info.setBSSID(BSSID_2);
381 info.setRssi(CONNECTED_RSSI);
382 info.setNetworkId(NETWORK_ID_2);
383 when(mockWifiManager.getConnectionInfo()).thenReturn(info);
384
385 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
386 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
387 tracker.mReceiver.onReceive(mContext, intent);
388 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
389 }
390
Ajay Nadathur7d176bc2016-10-24 16:55:24 -0700391 @Test
392 public void testAccessPointListenerSetWhenLookingUpUsingScanResults() {
393 ScanResult scanResult = new ScanResult();
394 scanResult.level = 123;
395 scanResult.BSSID = "bssid-" + 111;
396 scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
397 scanResult.capabilities = "";
398
399 WifiTracker tracker = new WifiTracker(
Tony Mantler0edf09b2017-09-28 15:03:37 -0700400 InstrumentationRegistry.getTargetContext(), null, true, true);
Ajay Nadathur7d176bc2016-10-24 16:55:24 -0700401
402 AccessPoint result = tracker.getCachedOrCreate(scanResult, new ArrayList<AccessPoint>());
403 assertTrue(result.mAccessPointListener != null);
404 }
405
406 @Test
407 public void testAccessPointListenerSetWhenLookingUpUsingWifiConfiguration() {
408 WifiConfiguration configuration = new WifiConfiguration();
409 configuration.SSID = "test123";
410 configuration.BSSID="bssid";
411 configuration.networkId = 123;
412 configuration.allowedKeyManagement = new BitSet();
413 configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
414
415 WifiTracker tracker = new WifiTracker(
Tony Mantler0edf09b2017-09-28 15:03:37 -0700416 InstrumentationRegistry.getTargetContext(), null, true, true);
Ajay Nadathur7d176bc2016-10-24 16:55:24 -0700417
418 AccessPoint result = tracker.getCachedOrCreate(configuration, new ArrayList<AccessPoint>());
419 assertTrue(result.mAccessPointListener != null);
420 }
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800421
422 @Test
423 public void startAndStopTrackingShouldRegisterAndUnregisterScoreCache()
424 throws InterruptedException {
425 WifiTracker tracker = createMockedWifiTracker();
426
427 // Test register
428 startTracking(tracker);
429 verify(mockNetworkScoreManager)
430 .registerNetworkScoreCache(
431 Matchers.anyInt(),
432 mScoreCacheCaptor.capture(),
433 Matchers.anyInt());
434
435 WifiNetworkScoreCache scoreCache = mScoreCacheCaptor.getValue();
436
Sundeep Ghumane869d832017-01-25 16:23:43 -0800437 CountDownLatch latch = new CountDownLatch(1);
438 doAnswer(
439 (invocation) -> {
440 latch.countDown();
441 return null;
442 }).when(mockNetworkScoreManager)
443 .unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, scoreCache);
444
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800445 // Test unregister
Tony Mantler0edf09b2017-09-28 15:03:37 -0700446 tracker.onStop();
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800447
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800448 assertTrue("Latch timed out", latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800449 verify(mockNetworkScoreManager)
450 .unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, scoreCache);
451 }
452
453 @Test
Amin Shaikha80ae0c2017-03-23 16:18:30 -0700454 public void testGetNumSavedNetworks() throws InterruptedException {
455 WifiConfiguration validConfig = new WifiConfiguration();
456 validConfig.SSID = SSID_1;
457 validConfig.BSSID = BSSID_1;
458
459 WifiConfiguration selfAddedNoAssociation = new WifiConfiguration();
Peter Qiuabea7262017-05-31 10:18:17 -0700460 selfAddedNoAssociation.ephemeral = true;
Amin Shaikha80ae0c2017-03-23 16:18:30 -0700461 selfAddedNoAssociation.selfAdded = true;
462 selfAddedNoAssociation.numAssociation = 0;
463 selfAddedNoAssociation.SSID = SSID_2;
464 selfAddedNoAssociation.BSSID = BSSID_2;
465
466 when(mockWifiManager.getConfiguredNetworks())
467 .thenReturn(Arrays.asList(validConfig, selfAddedNoAssociation));
468
469 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
470
471 assertEquals(1, tracker.getNumSavedNetworks());
472 }
473
474 @Test
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800475 public void startTrackingShouldSetConnectedAccessPointAsActive() throws InterruptedException {
Sundeep Ghumane8013092017-06-21 22:35:30 -0700476 WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800477
478 List<AccessPoint> aps = tracker.getAccessPoints();
479
480 assertThat(aps).hasSize(2);
481 assertThat(aps.get(0).isActive()).isTrue();
482 }
483
484 @Test
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700485 public void startTrackingAfterStopTracking_shouldRequestNewScores()
486 throws InterruptedException {
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800487 // Start the tracker and inject the initial scan results and then stop tracking
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800488 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800489
Tony Mantler0edf09b2017-09-28 15:03:37 -0700490 tracker.onStop();
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800491 mRequestedKeys.clear();
492
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800493 mRequestScoresLatch = new CountDownLatch(1);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800494 startTracking(tracker);
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700495 tracker.forceUpdate();
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800496 assertTrue("Latch timed out",
497 mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800498
499 assertTrue(mRequestedKeys.contains(NETWORK_KEY_1));
500 assertTrue(mRequestedKeys.contains(NETWORK_KEY_2));
501 }
502
503 @Test
Sundeep Ghuman75f94802017-06-26 16:05:40 -0700504 public void stopTracking_shouldNotClearExistingScores()
505 throws InterruptedException {
506 // Start the tracker and inject the initial scan results and then stop tracking
507 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
508 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Tony Mantler0edf09b2017-09-28 15:03:37 -0700509 tracker.onStop();
Sundeep Ghuman75f94802017-06-26 16:05:40 -0700510
511 assertThat(mScoreCacheCaptor.getValue().getScoredNetwork(NETWORK_KEY_1)).isNotNull();
512 }
513
514 @Test
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700515 public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged()
516 throws InterruptedException {
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800517 WifiTracker tracker = createMockedWifiTracker();
518 startTracking(tracker);
519 sendScanResultsAndProcess(tracker);
520
Sundeep Ghumane8013092017-06-21 22:35:30 -0700521 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800522 }
523
Sundeep Ghumane8013092017-06-21 22:35:30 -0700524 private void updateScoresAndWaitForAccessPointsChangedCallback(WifiTracker tracker)
525 throws InterruptedException {
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800526 // Updating scores can happen together or one after the other, so the latch countdown is set
527 // to 2.
Sundeep Ghumane8013092017-06-21 22:35:30 -0700528 mAccessPointsChangedLatch = new CountDownLatch(1);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800529 updateScores();
Sundeep Ghumane8013092017-06-21 22:35:30 -0700530 assertTrue("onAccessPointChanged was not called after updating scores",
Sundeep Ghumance6bab82017-04-19 16:21:46 -0700531 mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghumane8013092017-06-21 22:35:30 -0700532 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800533 }
534
Sundeep Ghuman266b4092017-06-16 15:12:56 -0700535 @FlakyTest
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800536 @Test
537 public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException {
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700538 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800539 List<AccessPoint> aps = tracker.getAccessPoints();
540 assertTrue(aps.size() == 2);
541 assertEquals(aps.get(0).getSsidStr(), SSID_1);
542 assertEquals(aps.get(1).getSsidStr(), SSID_2);
543
Sundeep Ghumane8013092017-06-21 22:35:30 -0700544 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800545
546 aps = tracker.getAccessPoints();
547 assertTrue(aps.size() == 2);
548 assertEquals(aps.get(0).getSsidStr(), SSID_2);
549 assertEquals(aps.get(1).getSsidStr(), SSID_1);
Sundeep Ghumane869d832017-01-25 16:23:43 -0800550 }
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800551
Sundeep Ghumane869d832017-01-25 16:23:43 -0800552 @Test
553 public void scoreCacheUpdateScoresShouldNotChangeSortOrderWhenSortingDisabled()
554 throws InterruptedException {
555 Settings.Global.putInt(
556 InstrumentationRegistry.getTargetContext().getContentResolver(),
557 Settings.Global.NETWORK_SCORING_UI_ENABLED,
558 0 /* disabled */);
559
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800560 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghumane869d832017-01-25 16:23:43 -0800561 List<AccessPoint> aps = tracker.getAccessPoints();
562 assertTrue(aps.size() == 2);
563 assertEquals(aps.get(0).getSsidStr(), SSID_1);
564 assertEquals(aps.get(1).getSsidStr(), SSID_2);
565
Sundeep Ghumane8013092017-06-21 22:35:30 -0700566 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Sundeep Ghumane869d832017-01-25 16:23:43 -0800567
568 aps = tracker.getAccessPoints();
569 assertTrue(aps.size() == 2);
570 assertEquals(aps.get(0).getSsidStr(), SSID_1);
571 assertEquals(aps.get(1).getSsidStr(), SSID_2);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800572 }
573
Sundeep Ghuman266b4092017-06-16 15:12:56 -0700574 @FlakyTest
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800575 @Test
Sundeep Ghuman55adc6b2017-06-05 16:46:59 -0700576 public void scoreCacheUpdateScoresShouldInsertSpeedIntoAccessPoint()
577 throws InterruptedException {
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800578 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghumane8013092017-06-21 22:35:30 -0700579 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800580
581 List<AccessPoint> aps = tracker.getAccessPoints();
582
583 for (AccessPoint ap : aps) {
584 if (ap.getSsidStr().equals(SSID_1)) {
Sundeep Ghuman55adc6b2017-06-05 16:46:59 -0700585 assertEquals(BADGE_1, ap.getSpeed());
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800586 } else if (ap.getSsidStr().equals(SSID_2)) {
Sundeep Ghuman55adc6b2017-06-05 16:46:59 -0700587 assertEquals(BADGE_2, ap.getSpeed());
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800588 }
589 }
590 }
591
592 @Test
Stephen Chen21f68682017-04-04 13:23:31 -0700593 public void scoreCacheUpdateMeteredShouldUpdateAccessPointMetering()
594 throws InterruptedException {
595 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghumane8013092017-06-21 22:35:30 -0700596 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Stephen Chen21f68682017-04-04 13:23:31 -0700597
598 List<AccessPoint> aps = tracker.getAccessPoints();
599
600 for (AccessPoint ap : aps) {
601 if (ap.getSsidStr().equals(SSID_1)) {
602 assertFalse(ap.isMetered());
603 } else if (ap.getSsidStr().equals(SSID_2)) {
604 assertTrue(ap.isMetered());
605 }
606 }
607 }
608
609 @Test
Sundeep Ghuman55adc6b2017-06-05 16:46:59 -0700610 public void noSpeedsShouldBeInsertedIntoAccessPointWhenScoringUiDisabled()
Sundeep Ghumane869d832017-01-25 16:23:43 -0800611 throws InterruptedException {
612 Settings.Global.putInt(
613 InstrumentationRegistry.getTargetContext().getContentResolver(),
614 Settings.Global.NETWORK_SCORING_UI_ENABLED,
615 0 /* disabled */);
616
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800617 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghumane8013092017-06-21 22:35:30 -0700618 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Sundeep Ghumane869d832017-01-25 16:23:43 -0800619
620 List<AccessPoint> aps = tracker.getAccessPoints();
621
622 for (AccessPoint ap : aps) {
623 if (ap.getSsidStr().equals(SSID_1)) {
Sundeep Ghuman53200ed2017-06-21 16:54:36 -0700624 assertEquals(AccessPoint.Speed.NONE, ap.getSpeed());
Sundeep Ghumane869d832017-01-25 16:23:43 -0800625 } else if (ap.getSsidStr().equals(SSID_2)) {
Sundeep Ghuman53200ed2017-06-21 16:54:36 -0700626 assertEquals(AccessPoint.Speed.NONE, ap.getSpeed());
Sundeep Ghumane869d832017-01-25 16:23:43 -0800627 }
628 }
629 }
630
631 @Test
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800632 public void scoresShouldBeRequestedForNewScanResultOnly() throws InterruptedException {
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800633 // Scores can be requested together or serially depending on how the scan results are
634 // processed.
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800635 mRequestScoresLatch = new CountDownLatch(2);
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800636 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800637 mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
638 mRequestedKeys.clear();
639
640 String ssid = "ssid3";
641 String bssid = "00:00:00:00:00:00";
642 ScanResult newResult = new ScanResult(
643 WifiSsid.createFromAsciiEncoded(ssid),
644 bssid,
645 0, // hessid
646 0, //anqpDomainId
647 null, // osuProviders
648 "", // capabilities
649 RSSI_1,
650 0, // frequency
651 SystemClock.elapsedRealtime() * 1000);
652 when(mockWifiManager.getScanResults())
653 .thenReturn(Arrays.asList(buildScanResult1(), buildScanResult2(), newResult));
654
655 mRequestScoresLatch = new CountDownLatch(1);
656 sendScanResultsAndProcess(tracker);
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800657 assertTrue(mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800658
659 assertEquals(1, mRequestedKeys.size());
660 assertTrue(mRequestedKeys.contains(new NetworkKey(new WifiKey('"' + ssid + '"', bssid))));
661 }
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800662
663 @Test
664 public void scoreCacheAndListenerShouldBeUnregisteredWhenStopTrackingIsCalled() throws Exception
665 {
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800666 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800667 WifiNetworkScoreCache cache = mScoreCacheCaptor.getValue();
668
Tony Mantler0edf09b2017-09-28 15:03:37 -0700669 tracker.onStop();
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800670 verify(mockNetworkScoreManager).unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, cache);
671
672 // Verify listener is unregistered so updating a score does not throw an error by posting
673 // a message to the dead work handler
674 mWorkerThread.quit();
675 updateScores();
676 }
Peter Qiuf5628382017-03-28 13:24:34 -0700677
678 /**
679 * Verify that tracking a Passpoint AP on a device with Passpoint disabled doesn't cause
680 * any crash.
681 *
682 * @throws Exception
683 */
684 @Test
685 public void trackPasspointApWithPasspointDisabled() throws Exception {
686 WifiTracker tracker = createMockedWifiTracker();
687
688 // Add a Passpoint AP to the scan results.
689 List<ScanResult> results = new ArrayList<>();
690 ScanResult passpointAp = new ScanResult(
691 WifiSsid.createFromAsciiEncoded(SSID_1),
692 BSSID_1,
693 0, // hessid
694 0, //anqpDomainId
695 null, // osuProviders
696 "", // capabilities
697 RSSI_1,
698 0, // frequency
699 SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */);
700 passpointAp.setFlag(ScanResult.FLAG_PASSPOINT_NETWORK);
701 results.add(passpointAp);
702
703 // Update access point and verify UnsupportedOperationException is being caught for
704 // call to WifiManager#getMatchingWifiConfig.
705 when(mockWifiManager.getConfiguredNetworks())
706 .thenReturn(new ArrayList<WifiConfiguration>());
707 when(mockWifiManager.getScanResults()).thenReturn(results);
708 doThrow(new UnsupportedOperationException())
709 .when(mockWifiManager).getMatchingWifiConfig(any(ScanResult.class));
710 tracker.forceUpdate();
711 verify(mockWifiManager).getMatchingWifiConfig(any(ScanResult.class));
712 }
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700713
714 @Test
715 public void rssiChangeBroadcastShouldUpdateConnectedAp() throws Exception {
716 WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
717 assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
718
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700719 int newRssi = CONNECTED_RSSI + 10;
720 WifiInfo info = new WifiInfo(CONNECTED_AP_1_INFO);
721 info.setRssi(newRssi);
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700722
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700723 CountDownLatch latch = new CountDownLatch(1);
724
725 // Once the new info has been fetched, we need to wait for the access points to be copied
726 doAnswer(invocation -> {
727 latch.countDown();
728 mAccessPointsChangedLatch = new CountDownLatch(1);
729 return info;
730 }).when(mockWifiManager).getConnectionInfo();
731
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700732 tracker.mReceiver.onReceive(mContext, new Intent(WifiManager.RSSI_CHANGED_ACTION));
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700733 assertTrue("New connection info never retrieved",
734 latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
735 assertTrue("onAccessPointsChanged never called",
736 mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700737
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700738 assertThat(tracker.getAccessPoints().get(0).getRssi()).isEqualTo(newRssi);
739 }
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -0700740
741 @Test
742 public void forceUpdateShouldSynchronouslyFetchLatestInformation() throws Exception {
Sundeep Ghumance6bab82017-04-19 16:21:46 -0700743 Network mockNetwork = mock(Network.class);
744 when(mockWifiManager.getCurrentNetwork()).thenReturn(mockNetwork);
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700745
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -0700746 when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO);
747
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -0700748 NetworkInfo networkInfo = new NetworkInfo(
749 ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
750 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
751 when(mockConnectivityManager.getNetworkInfo(any(Network.class))).thenReturn(networkInfo);
752
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -0700753 WifiTracker tracker = createMockedWifiTracker();
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -0700754 tracker.forceUpdate();
755
Sundeep Ghumance6bab82017-04-19 16:21:46 -0700756 verify(mockWifiManager).getConnectionInfo();
757 verify(mockWifiManager, times(2)).getConfiguredNetworks();
758 verify(mockConnectivityManager).getNetworkInfo(any(Network.class));
759
Sundeep Ghumand2b84a82017-07-05 14:19:30 -0700760 verify(mockWifiListener, never()).onAccessPointsChanged(); // mStaleAccessPoints is true
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -0700761 assertThat(tracker.getAccessPoints().size()).isEqualTo(2);
762 assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
763 }
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700764
765 @Test
766 public void stopTrackingShouldRemoveWifiListenerCallbacks() throws Exception {
767 WifiTracker tracker = createMockedWifiTracker();
768 startTracking(tracker);
769
770 CountDownLatch latch = new CountDownLatch(1);
771 CountDownLatch lock = new CountDownLatch(1);
772 tracker.mMainHandler.post(() -> {
773 try {
774 lock.await();
775 latch.countDown();
776 } catch (InterruptedException e) {
777 fail("Interrupted Exception while awaiting lock release: " + e);
778 }
779 });
780
781 // Enqueue messages
782 tracker.mMainHandler.sendEmptyMessage(
783 WifiTracker.MainHandler.MSG_ACCESS_POINT_CHANGED);
784 tracker.mMainHandler.sendEmptyMessage(
785 WifiTracker.MainHandler.MSG_CONNECTED_CHANGED);
786 tracker.mMainHandler.sendEmptyMessage(
787 WifiTracker.MainHandler.MSG_WIFI_STATE_CHANGED);
788
Tony Mantler0edf09b2017-09-28 15:03:37 -0700789 tracker.onStop();
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700790
791 verify(mockWifiListener, atMost(1)).onAccessPointsChanged();
792 verify(mockWifiListener, atMost(1)).onConnectedChanged();
793 verify(mockWifiListener, atMost(1)).onWifiStateChanged(anyInt());
794
795 lock.countDown();
Sundeep Ghumance6bab82017-04-19 16:21:46 -0700796 assertTrue("Latch timed out", latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700797
798 assertThat(tracker.mMainHandler.hasMessages(
799 WifiTracker.MainHandler.MSG_ACCESS_POINT_CHANGED)).isFalse();
800 assertThat(tracker.mMainHandler.hasMessages(
801 WifiTracker.MainHandler.MSG_CONNECTED_CHANGED)).isFalse();
802 assertThat(tracker.mMainHandler.hasMessages(
803 WifiTracker.MainHandler.MSG_WIFI_STATE_CHANGED)).isFalse();
804
805 verifyNoMoreInteractions(mockWifiListener);
806 }
Sundeep Ghumand4a79ac2017-06-07 18:11:39 -0700807
808 @Test
809 public void stopTrackingShouldSetStaleBitWhichPreventsCallbacksUntilNextScanResult()
810 throws Exception {
811 WifiTracker tracker = createMockedWifiTracker();
812 startTracking(tracker);
Sundeep Ghumane8013092017-06-21 22:35:30 -0700813 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghumand4a79ac2017-06-07 18:11:39 -0700814
Tony Mantler0edf09b2017-09-28 15:03:37 -0700815 tracker.onStop();
Sundeep Ghumane8013092017-06-21 22:35:30 -0700816 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghumand4a79ac2017-06-07 18:11:39 -0700817
818 startTracking(tracker);
819
820 tracker.mReceiver.onReceive(mContext, new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION));
821 tracker.mReceiver.onReceive(
822 mContext, new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
823 tracker.mReceiver.onReceive(
824 mContext, new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION));
825
Sundeep Ghumane8013092017-06-21 22:35:30 -0700826 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghumand4a79ac2017-06-07 18:11:39 -0700827
828 verify(mockWifiListener, never()).onAccessPointsChanged();
829
830 sendScanResultsAndProcess(tracker); // verifies onAccessPointsChanged is invoked
831 }
Sundeep Ghumane8013092017-06-21 22:35:30 -0700832
833 @Test
Sundeep Ghumand2b84a82017-07-05 14:19:30 -0700834 public void startTrackingShouldNotSendAnyCallbacksUntilScanResultsAreProcessed()
835 throws Exception {
836 WifiTracker tracker = createMockedWifiTracker();
837 startTracking(tracker);
838 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
839
840 tracker.mReceiver.onReceive(mContext, new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION));
841 tracker.mReceiver.onReceive(
842 mContext, new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
843 tracker.mReceiver.onReceive(
844 mContext, new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION));
845
846 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
847 verify(mockWifiListener, never()).onAccessPointsChanged();
848
849 sendScanResultsAndProcess(tracker); // verifies onAccessPointsChanged is invoked
850 }
851
852 @Test
Sundeep Ghumane8013092017-06-21 22:35:30 -0700853 public void disablingWifiShouldClearExistingAccessPoints() throws Exception {
854 WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
855
856 when(mockWifiManager.isWifiEnabled()).thenReturn(false);
857 mAccessPointsChangedLatch = new CountDownLatch(1);
858 tracker.mReceiver.onReceive(mContext, new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION));
859
860 mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
861 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
862
863 assertThat(tracker.getAccessPoints()).isEmpty();
864 }
Sundeep Ghuman42058742017-07-21 18:42:10 -0700865
866 @Test
867 public void onConnectedChangedCallback_shouldNotBeInvokedWhenNoStateChange() throws Exception {
868 WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
869 verify(mockWifiListener, times(1)).onConnectedChanged();
870
871 NetworkInfo networkInfo = new NetworkInfo(
872 ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
873 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
874
875 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
876 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
877 tracker.mReceiver.onReceive(mContext, intent);
878
Sundeep Ghumandb2eabb2017-07-28 14:51:05 -0700879 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghuman42058742017-07-21 18:42:10 -0700880 verify(mockWifiListener, times(1)).onConnectedChanged();
881 }
882
883 @Test
Sundeep Ghumandb2eabb2017-07-28 14:51:05 -0700884 public void onConnectedChangedCallback_shouldBeInvokedWhenStateChanges() throws Exception {
Sundeep Ghuman42058742017-07-21 18:42:10 -0700885 WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
886 verify(mockWifiListener, times(1)).onConnectedChanged();
887
888 NetworkInfo networkInfo = new NetworkInfo(
889 ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
890 networkInfo.setDetailedState(
Sundeep Ghumandb2eabb2017-07-28 14:51:05 -0700891 NetworkInfo.DetailedState.DISCONNECTED, "disconnected", "test");
Sundeep Ghuman42058742017-07-21 18:42:10 -0700892
893 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
894 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
895 tracker.mReceiver.onReceive(mContext, intent);
896
Sundeep Ghumandb2eabb2017-07-28 14:51:05 -0700897 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
898 assertThat(tracker.isConnected()).isFalse();
Sundeep Ghuman42058742017-07-21 18:42:10 -0700899 verify(mockWifiListener, times(2)).onConnectedChanged();
900 }
Sundeep Ghumandb9b94c2017-09-06 11:46:21 -0700901
902 @Test
903 public void updateNetworkInfoWithNewConnectedNetwork_switchesNetworks() throws Exception {
904 WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
905
906 switchToNetwork2(tracker);
907
908 List<AccessPoint> aps = tracker.getAccessPoints();
909 assertThat(aps.get(0).getSsidStr()).isEqualTo(SSID_2);
910
911 assertThat(aps.get(0).isReachable()).isTrue();
912 assertThat(aps.get(1).isReachable()).isTrue();
913 }
Peter Qiuabea7262017-05-31 10:18:17 -0700914}