blob: 76d9823c6ab6aac318ff161906b1695807a2b21b [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;
39import android.net.ConnectivityManager;
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -070040import android.net.Network;
Sundeep Ghuman2b489902017-02-22 18:17:29 -080041import android.net.NetworkInfo;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080042import android.net.NetworkKey;
43import android.net.NetworkScoreManager;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080044import android.net.RssiCurve;
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -070045import android.net.ScoredNetwork;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080046import android.net.WifiKey;
Ajay Nadathur7d176bc2016-10-24 16:55:24 -070047import android.net.wifi.ScanResult;
48import android.net.wifi.WifiConfiguration;
Sundeep Ghuman2b489902017-02-22 18:17:29 -080049import android.net.wifi.WifiInfo;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080050import android.net.wifi.WifiManager;
51import android.net.wifi.WifiNetworkScoreCache;
52import android.net.wifi.WifiSsid;
53import android.os.Bundle;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -080054import android.os.Handler;
55import android.os.HandlerThread;
56import android.os.Looper;
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 Ghuman8c792882017-04-04 17:23:29 -0700108 private static final int CONNECTED_NETWORK_ID = 123;
109 private static final int CONNECTED_RSSI = -50;
110 private static final WifiInfo CONNECTED_AP_1_INFO = new WifiInfo();
111 static {
112 CONNECTED_AP_1_INFO.setSSID(WifiSsid.createFromAsciiEncoded(SSID_1));
113 CONNECTED_AP_1_INFO.setBSSID(BSSID_1);
114 CONNECTED_AP_1_INFO.setNetworkId(CONNECTED_NETWORK_ID);
115 CONNECTED_AP_1_INFO.setRssi(CONNECTED_RSSI);
116 }
117
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800118 @Captor ArgumentCaptor<WifiNetworkScoreCache> mScoreCacheCaptor;
119 @Mock private ConnectivityManager mockConnectivityManager;
120 @Mock private NetworkScoreManager mockNetworkScoreManager;
121 @Mock private RssiCurve mockCurve1;
122 @Mock private RssiCurve mockCurve2;
123 @Mock private RssiCurve mockBadgeCurve1;
124 @Mock private RssiCurve mockBadgeCurve2;
125 @Mock private WifiManager mockWifiManager;
126 @Mock private WifiTracker.WifiListener mockWifiListener;
127
128 private final List<NetworkKey> mRequestedKeys = new ArrayList<>();
129
130 private Context mContext;
131 private CountDownLatch mAccessPointsChangedLatch;
132 private CountDownLatch mRequestScoresLatch;
133 private Handler mScannerHandler;
134 private HandlerThread mMainThread;
135 private HandlerThread mWorkerThread;
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700136 private Looper mWorkerLooper;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800137 private Looper mMainLooper;
Sundeep Ghuman42058742017-07-21 18:42:10 -0700138
Sundeep Ghumane869d832017-01-25 16:23:43 -0800139 private int mOriginalScoringUiSettingValue;
Sundeep Ghuman42058742017-07-21 18:42:10 -0700140 private boolean mOriginalStaleScanResultsValue;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800141
142 @Before
143 public void setUp() {
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800144 MockitoAnnotations.initMocks(this);
145
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800146 mContext = InstrumentationRegistry.getTargetContext();
147
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800148 mWorkerThread = new HandlerThread("TestHandlerWorkerThread");
149 mWorkerThread.start();
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700150 mWorkerLooper = mWorkerThread.getLooper();
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800151 mMainThread = new HandlerThread("TestHandlerThread");
152 mMainThread.start();
153 mMainLooper = mMainThread.getLooper();
154
155 // Make sure the scanner doesn't try to run on the testing thread.
156 HandlerThread scannerThread = new HandlerThread("ScannerWorkerThread");
157 scannerThread.start();
158 mScannerHandler = new Handler(scannerThread.getLooper());
159
160 when(mockWifiManager.isWifiEnabled()).thenReturn(true);
161 when(mockWifiManager.getScanResults())
162 .thenReturn(Arrays.asList(buildScanResult1(), buildScanResult2()));
163
164
165 when(mockCurve1.lookupScore(RSSI_1)).thenReturn(SCORE_1);
166 when(mockCurve2.lookupScore(RSSI_2)).thenReturn(SCORE_2);
167
168 when(mockBadgeCurve1.lookupScore(RSSI_1)).thenReturn((byte) BADGE_1);
169 when(mockBadgeCurve2.lookupScore(RSSI_2)).thenReturn((byte) BADGE_2);
170
171 doNothing()
172 .when(mockNetworkScoreManager)
173 .registerNetworkScoreCache(
174 anyInt(),
175 mScoreCacheCaptor.capture(),
176 Matchers.anyInt());
177
178 // Capture requested keys and count down latch if present
179 doAnswer(
180 new Answer<Boolean>() {
181 @Override
182 public Boolean answer(InvocationOnMock input) {
183 if (mRequestScoresLatch != null) {
184 mRequestScoresLatch.countDown();
185 }
186 NetworkKey[] keys = (NetworkKey[]) input.getArguments()[0];
187 for (NetworkKey key : keys) {
188 mRequestedKeys.add(key);
189 }
190 return true;
191 }
192 }).when(mockNetworkScoreManager).requestScores(Matchers.<NetworkKey[]>any());
193
194 doAnswer(
195 new Answer<Void>() {
196 @Override
197 public Void answer (InvocationOnMock invocation) throws Throwable {
198 if (mAccessPointsChangedLatch != null) {
199 mAccessPointsChangedLatch.countDown();
200 }
201
202 return null;
203 }
204 }).when(mockWifiListener).onAccessPointsChanged();
205
Sundeep Ghumane869d832017-01-25 16:23:43 -0800206 // Turn on Scoring UI features
207 mOriginalScoringUiSettingValue = Settings.Global.getInt(
208 InstrumentationRegistry.getTargetContext().getContentResolver(),
209 Settings.Global.NETWORK_SCORING_UI_ENABLED,
210 0 /* disabled */);
211 Settings.Global.putInt(
212 InstrumentationRegistry.getTargetContext().getContentResolver(),
213 Settings.Global.NETWORK_SCORING_UI_ENABLED,
214 1 /* enabled */);
Sundeep Ghuman42058742017-07-21 18:42:10 -0700215
216 mOriginalStaleScanResultsValue = WifiTracker.sStaleScanResults;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800217 }
218
219 @After
220 public void cleanUp() {
221 Settings.Global.putInt(
Sundeep Ghumane869d832017-01-25 16:23:43 -0800222 InstrumentationRegistry.getTargetContext().getContentResolver(),
223 Settings.Global.NETWORK_SCORING_UI_ENABLED,
224 mOriginalScoringUiSettingValue);
Sundeep Ghuman42058742017-07-21 18:42:10 -0700225
226 WifiTracker.sStaleScanResults = mOriginalStaleScanResultsValue;
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800227 }
228
229 private static ScanResult buildScanResult1() {
230 return new ScanResult(
231 WifiSsid.createFromAsciiEncoded(SSID_1),
232 BSSID_1,
233 0, // hessid
234 0, //anqpDomainId
235 null, // osuProviders
236 "", // capabilities
237 RSSI_1,
238 0, // frequency
239 SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */);
240 }
241
242 private static ScanResult buildScanResult2() {
243 return new ScanResult(
244 WifiSsid.createFromAsciiEncoded(SSID_2),
245 BSSID_2,
246 0, // hessid
247 0, //anqpDomainId
248 null, // osuProviders
249 "", // capabilities
250 RSSI_2,
251 0, // frequency
252 SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */);
253 }
254
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800255 private WifiTracker createTrackerWithImmediateBroadcastsAndInjectInitialScanResults(
256 Intent ... intents)
257 throws InterruptedException {
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800258 WifiTracker tracker = createMockedWifiTracker();
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800259
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800260 startTracking(tracker);
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800261 for (Intent intent : intents) {
262 tracker.mReceiver.onReceive(mContext, intent);
263 }
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800264
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800265 sendScanResultsAndProcess(tracker);
Sundeep Ghumane8013092017-06-21 22:35:30 -0700266 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800267
268 return tracker;
269 }
270
271 private WifiTracker createMockedWifiTracker() {
272 WifiTracker tracker =
273 new WifiTracker(
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800274 mContext,
275 mockWifiListener,
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700276 mWorkerLooper,
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800277 true,
278 true,
279 true,
280 mockWifiManager,
281 mockConnectivityManager,
282 mockNetworkScoreManager,
283 mMainLooper
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800284 );
285
286 return tracker;
287 }
288
289 private void startTracking(WifiTracker tracker) throws InterruptedException {
290 CountDownLatch latch = new CountDownLatch(1);
291 mScannerHandler.post(new Runnable() {
292 @Override
293 public void run() {
294 tracker.startTracking();
295 latch.countDown();
296 }
297 });
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800298 assertTrue("Latch timed out", latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800299 }
300
301 private void sendScanResultsAndProcess(WifiTracker tracker) throws InterruptedException {
302 mAccessPointsChangedLatch = new CountDownLatch(1);
303 Intent i = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
304 tracker.mReceiver.onReceive(mContext, i);
305
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800306 assertTrue("Latch timed out",
307 mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800308 }
309
310 private void updateScores() {
311 Bundle attr1 = new Bundle();
312 attr1.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve1);
313 ScoredNetwork sc1 =
314 new ScoredNetwork(
315 NETWORK_KEY_1,
316 mockCurve1,
317 false /* meteredHint */,
318 attr1);
319
320 Bundle attr2 = new Bundle();
321 attr2.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve2);
322 ScoredNetwork sc2 =
323 new ScoredNetwork(
324 NETWORK_KEY_2,
325 mockCurve2,
Stephen Chen21f68682017-04-04 13:23:31 -0700326 true /* meteredHint */,
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800327 attr2);
328
329 WifiNetworkScoreCache scoreCache = mScoreCacheCaptor.getValue();
330 scoreCache.updateScores(Arrays.asList(sc1, sc2));
331 }
332
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800333 private WifiTracker createTrackerWithScanResultsAndAccessPoint1Connected()
334 throws InterruptedException {
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700335 when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO);
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800336
337 WifiConfiguration configuration = new WifiConfiguration();
338 configuration.SSID = SSID_1;
339 configuration.BSSID = BSSID_1;
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700340 configuration.networkId = CONNECTED_NETWORK_ID;
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800341 when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
342
343 NetworkInfo networkInfo = new NetworkInfo(
344 ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
345 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
346
347 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
348 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
Sundeep Ghumandb2eabb2017-07-28 14:51:05 -0700349 WifiTracker tracker =
350 createTrackerWithImmediateBroadcastsAndInjectInitialScanResults(intent);
351 assertThat(tracker.isConnected()).isTrue();
352 return tracker;
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800353 }
354
Sundeep Ghumane8013092017-06-21 22:35:30 -0700355 private void waitForHandlersToProcessCurrentlyEnqueuedMessages(WifiTracker tracker)
356 throws InterruptedException {
357 CountDownLatch workerLatch = new CountDownLatch(1);
358 tracker.mWorkHandler.post(() -> {
359 workerLatch.countDown();
360 });
361 assertTrue("Latch timed out while waiting for WorkerHandler",
362 workerLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
363
364 CountDownLatch mainLatch = new CountDownLatch(1);
365 tracker.mMainHandler.post(() -> {
366 mainLatch.countDown();
367 });
368 assertTrue("Latch timed out while waiting for MainHandler",
369 mainLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
370 }
371
Ajay Nadathur7d176bc2016-10-24 16:55:24 -0700372 @Test
373 public void testAccessPointListenerSetWhenLookingUpUsingScanResults() {
374 ScanResult scanResult = new ScanResult();
375 scanResult.level = 123;
376 scanResult.BSSID = "bssid-" + 111;
377 scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
378 scanResult.capabilities = "";
379
380 WifiTracker tracker = new WifiTracker(
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700381 InstrumentationRegistry.getTargetContext(), null, mWorkerLooper, true, true);
Ajay Nadathur7d176bc2016-10-24 16:55:24 -0700382
383 AccessPoint result = tracker.getCachedOrCreate(scanResult, new ArrayList<AccessPoint>());
384 assertTrue(result.mAccessPointListener != null);
385 }
386
387 @Test
388 public void testAccessPointListenerSetWhenLookingUpUsingWifiConfiguration() {
389 WifiConfiguration configuration = new WifiConfiguration();
390 configuration.SSID = "test123";
391 configuration.BSSID="bssid";
392 configuration.networkId = 123;
393 configuration.allowedKeyManagement = new BitSet();
394 configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
395
396 WifiTracker tracker = new WifiTracker(
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700397 InstrumentationRegistry.getTargetContext(), null, mWorkerLooper, true, true);
Ajay Nadathur7d176bc2016-10-24 16:55:24 -0700398
399 AccessPoint result = tracker.getCachedOrCreate(configuration, new ArrayList<AccessPoint>());
400 assertTrue(result.mAccessPointListener != null);
401 }
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800402
403 @Test
404 public void startAndStopTrackingShouldRegisterAndUnregisterScoreCache()
405 throws InterruptedException {
406 WifiTracker tracker = createMockedWifiTracker();
407
408 // Test register
409 startTracking(tracker);
410 verify(mockNetworkScoreManager)
411 .registerNetworkScoreCache(
412 Matchers.anyInt(),
413 mScoreCacheCaptor.capture(),
414 Matchers.anyInt());
415
416 WifiNetworkScoreCache scoreCache = mScoreCacheCaptor.getValue();
417
Sundeep Ghumane869d832017-01-25 16:23:43 -0800418 CountDownLatch latch = new CountDownLatch(1);
419 doAnswer(
420 (invocation) -> {
421 latch.countDown();
422 return null;
423 }).when(mockNetworkScoreManager)
424 .unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, scoreCache);
425
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800426 // Test unregister
427 tracker.stopTracking();
428
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800429 assertTrue("Latch timed out", latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800430 verify(mockNetworkScoreManager)
431 .unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, scoreCache);
432 }
433
434 @Test
Amin Shaikha80ae0c2017-03-23 16:18:30 -0700435 public void testGetNumSavedNetworks() throws InterruptedException {
436 WifiConfiguration validConfig = new WifiConfiguration();
437 validConfig.SSID = SSID_1;
438 validConfig.BSSID = BSSID_1;
439
440 WifiConfiguration selfAddedNoAssociation = new WifiConfiguration();
Peter Qiuabea7262017-05-31 10:18:17 -0700441 selfAddedNoAssociation.ephemeral = true;
Amin Shaikha80ae0c2017-03-23 16:18:30 -0700442 selfAddedNoAssociation.selfAdded = true;
443 selfAddedNoAssociation.numAssociation = 0;
444 selfAddedNoAssociation.SSID = SSID_2;
445 selfAddedNoAssociation.BSSID = BSSID_2;
446
447 when(mockWifiManager.getConfiguredNetworks())
448 .thenReturn(Arrays.asList(validConfig, selfAddedNoAssociation));
449
450 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
451
452 assertEquals(1, tracker.getNumSavedNetworks());
453 }
454
455 @Test
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800456 public void startTrackingShouldSetConnectedAccessPointAsActive() throws InterruptedException {
Sundeep Ghumane8013092017-06-21 22:35:30 -0700457 WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800458
459 List<AccessPoint> aps = tracker.getAccessPoints();
460
461 assertThat(aps).hasSize(2);
462 assertThat(aps.get(0).isActive()).isTrue();
463 }
464
465 @Test
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700466 public void startTrackingAfterStopTracking_shouldRequestNewScores()
467 throws InterruptedException {
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800468 // Start the tracker and inject the initial scan results and then stop tracking
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800469 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800470
471 tracker.stopTracking();
472 mRequestedKeys.clear();
473
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800474 mRequestScoresLatch = new CountDownLatch(1);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800475 startTracking(tracker);
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700476 tracker.forceUpdate();
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800477 assertTrue("Latch timed out",
478 mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800479
480 assertTrue(mRequestedKeys.contains(NETWORK_KEY_1));
481 assertTrue(mRequestedKeys.contains(NETWORK_KEY_2));
482 }
483
484 @Test
Sundeep Ghuman75f94802017-06-26 16:05:40 -0700485 public void stopTracking_shouldNotClearExistingScores()
486 throws InterruptedException {
487 // Start the tracker and inject the initial scan results and then stop tracking
488 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
489 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
490 tracker.stopTracking();
491
492 assertThat(mScoreCacheCaptor.getValue().getScoredNetwork(NETWORK_KEY_1)).isNotNull();
493 }
494
495 @Test
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700496 public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged()
497 throws InterruptedException {
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800498 WifiTracker tracker = createMockedWifiTracker();
499 startTracking(tracker);
500 sendScanResultsAndProcess(tracker);
501
Sundeep Ghumane8013092017-06-21 22:35:30 -0700502 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800503 }
504
Sundeep Ghumane8013092017-06-21 22:35:30 -0700505 private void updateScoresAndWaitForAccessPointsChangedCallback(WifiTracker tracker)
506 throws InterruptedException {
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800507 // Updating scores can happen together or one after the other, so the latch countdown is set
508 // to 2.
Sundeep Ghumane8013092017-06-21 22:35:30 -0700509 mAccessPointsChangedLatch = new CountDownLatch(1);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800510 updateScores();
Sundeep Ghumane8013092017-06-21 22:35:30 -0700511 assertTrue("onAccessPointChanged was not called after updating scores",
Sundeep Ghumance6bab82017-04-19 16:21:46 -0700512 mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghumane8013092017-06-21 22:35:30 -0700513 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800514 }
515
Sundeep Ghuman266b4092017-06-16 15:12:56 -0700516 @FlakyTest
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800517 @Test
518 public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException {
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700519 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800520 List<AccessPoint> aps = tracker.getAccessPoints();
521 assertTrue(aps.size() == 2);
522 assertEquals(aps.get(0).getSsidStr(), SSID_1);
523 assertEquals(aps.get(1).getSsidStr(), SSID_2);
524
Sundeep Ghumane8013092017-06-21 22:35:30 -0700525 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800526
527 aps = tracker.getAccessPoints();
528 assertTrue(aps.size() == 2);
529 assertEquals(aps.get(0).getSsidStr(), SSID_2);
530 assertEquals(aps.get(1).getSsidStr(), SSID_1);
Sundeep Ghumane869d832017-01-25 16:23:43 -0800531 }
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800532
Sundeep Ghumane869d832017-01-25 16:23:43 -0800533 @Test
534 public void scoreCacheUpdateScoresShouldNotChangeSortOrderWhenSortingDisabled()
535 throws InterruptedException {
536 Settings.Global.putInt(
537 InstrumentationRegistry.getTargetContext().getContentResolver(),
538 Settings.Global.NETWORK_SCORING_UI_ENABLED,
539 0 /* disabled */);
540
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800541 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghumane869d832017-01-25 16:23:43 -0800542 List<AccessPoint> aps = tracker.getAccessPoints();
543 assertTrue(aps.size() == 2);
544 assertEquals(aps.get(0).getSsidStr(), SSID_1);
545 assertEquals(aps.get(1).getSsidStr(), SSID_2);
546
Sundeep Ghumane8013092017-06-21 22:35:30 -0700547 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Sundeep Ghumane869d832017-01-25 16:23:43 -0800548
549 aps = tracker.getAccessPoints();
550 assertTrue(aps.size() == 2);
551 assertEquals(aps.get(0).getSsidStr(), SSID_1);
552 assertEquals(aps.get(1).getSsidStr(), SSID_2);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800553 }
554
Sundeep Ghuman266b4092017-06-16 15:12:56 -0700555 @FlakyTest
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800556 @Test
Sundeep Ghuman55adc6b2017-06-05 16:46:59 -0700557 public void scoreCacheUpdateScoresShouldInsertSpeedIntoAccessPoint()
558 throws InterruptedException {
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800559 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghumane8013092017-06-21 22:35:30 -0700560 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800561
562 List<AccessPoint> aps = tracker.getAccessPoints();
563
564 for (AccessPoint ap : aps) {
565 if (ap.getSsidStr().equals(SSID_1)) {
Sundeep Ghuman55adc6b2017-06-05 16:46:59 -0700566 assertEquals(BADGE_1, ap.getSpeed());
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800567 } else if (ap.getSsidStr().equals(SSID_2)) {
Sundeep Ghuman55adc6b2017-06-05 16:46:59 -0700568 assertEquals(BADGE_2, ap.getSpeed());
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800569 }
570 }
571 }
572
573 @Test
Stephen Chen21f68682017-04-04 13:23:31 -0700574 public void scoreCacheUpdateMeteredShouldUpdateAccessPointMetering()
575 throws InterruptedException {
576 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghumane8013092017-06-21 22:35:30 -0700577 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Stephen Chen21f68682017-04-04 13:23:31 -0700578
579 List<AccessPoint> aps = tracker.getAccessPoints();
580
581 for (AccessPoint ap : aps) {
582 if (ap.getSsidStr().equals(SSID_1)) {
583 assertFalse(ap.isMetered());
584 } else if (ap.getSsidStr().equals(SSID_2)) {
585 assertTrue(ap.isMetered());
586 }
587 }
588 }
589
590 @Test
Sundeep Ghuman55adc6b2017-06-05 16:46:59 -0700591 public void noSpeedsShouldBeInsertedIntoAccessPointWhenScoringUiDisabled()
Sundeep Ghumane869d832017-01-25 16:23:43 -0800592 throws InterruptedException {
593 Settings.Global.putInt(
594 InstrumentationRegistry.getTargetContext().getContentResolver(),
595 Settings.Global.NETWORK_SCORING_UI_ENABLED,
596 0 /* disabled */);
597
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800598 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghumane8013092017-06-21 22:35:30 -0700599 updateScoresAndWaitForAccessPointsChangedCallback(tracker);
Sundeep Ghumane869d832017-01-25 16:23:43 -0800600
601 List<AccessPoint> aps = tracker.getAccessPoints();
602
603 for (AccessPoint ap : aps) {
604 if (ap.getSsidStr().equals(SSID_1)) {
Sundeep Ghuman53200ed2017-06-21 16:54:36 -0700605 assertEquals(AccessPoint.Speed.NONE, ap.getSpeed());
Sundeep Ghumane869d832017-01-25 16:23:43 -0800606 } else if (ap.getSsidStr().equals(SSID_2)) {
Sundeep Ghuman53200ed2017-06-21 16:54:36 -0700607 assertEquals(AccessPoint.Speed.NONE, ap.getSpeed());
Sundeep Ghumane869d832017-01-25 16:23:43 -0800608 }
609 }
610 }
611
612 @Test
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800613 public void scoresShouldBeRequestedForNewScanResultOnly() throws InterruptedException {
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800614 // Scores can be requested together or serially depending on how the scan results are
615 // processed.
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800616 mRequestScoresLatch = new CountDownLatch(2);
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800617 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800618 mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
619 mRequestedKeys.clear();
620
621 String ssid = "ssid3";
622 String bssid = "00:00:00:00:00:00";
623 ScanResult newResult = new ScanResult(
624 WifiSsid.createFromAsciiEncoded(ssid),
625 bssid,
626 0, // hessid
627 0, //anqpDomainId
628 null, // osuProviders
629 "", // capabilities
630 RSSI_1,
631 0, // frequency
632 SystemClock.elapsedRealtime() * 1000);
633 when(mockWifiManager.getScanResults())
634 .thenReturn(Arrays.asList(buildScanResult1(), buildScanResult2(), newResult));
635
636 mRequestScoresLatch = new CountDownLatch(1);
637 sendScanResultsAndProcess(tracker);
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800638 assertTrue(mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman5519b7b2016-12-14 17:53:31 -0800639
640 assertEquals(1, mRequestedKeys.size());
641 assertTrue(mRequestedKeys.contains(new NetworkKey(new WifiKey('"' + ssid + '"', bssid))));
642 }
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800643
644 @Test
645 public void scoreCacheAndListenerShouldBeUnregisteredWhenStopTrackingIsCalled() throws Exception
646 {
Sundeep Ghuman2b489902017-02-22 18:17:29 -0800647 WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
Sundeep Ghumanac7b4362017-02-08 17:19:27 -0800648 WifiNetworkScoreCache cache = mScoreCacheCaptor.getValue();
649
650 tracker.stopTracking();
651 verify(mockNetworkScoreManager).unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, cache);
652
653 // Verify listener is unregistered so updating a score does not throw an error by posting
654 // a message to the dead work handler
655 mWorkerThread.quit();
656 updateScores();
657 }
Peter Qiuf5628382017-03-28 13:24:34 -0700658
659 /**
660 * Verify that tracking a Passpoint AP on a device with Passpoint disabled doesn't cause
661 * any crash.
662 *
663 * @throws Exception
664 */
665 @Test
666 public void trackPasspointApWithPasspointDisabled() throws Exception {
667 WifiTracker tracker = createMockedWifiTracker();
668
669 // Add a Passpoint AP to the scan results.
670 List<ScanResult> results = new ArrayList<>();
671 ScanResult passpointAp = new ScanResult(
672 WifiSsid.createFromAsciiEncoded(SSID_1),
673 BSSID_1,
674 0, // hessid
675 0, //anqpDomainId
676 null, // osuProviders
677 "", // capabilities
678 RSSI_1,
679 0, // frequency
680 SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */);
681 passpointAp.setFlag(ScanResult.FLAG_PASSPOINT_NETWORK);
682 results.add(passpointAp);
683
684 // Update access point and verify UnsupportedOperationException is being caught for
685 // call to WifiManager#getMatchingWifiConfig.
686 when(mockWifiManager.getConfiguredNetworks())
687 .thenReturn(new ArrayList<WifiConfiguration>());
688 when(mockWifiManager.getScanResults()).thenReturn(results);
689 doThrow(new UnsupportedOperationException())
690 .when(mockWifiManager).getMatchingWifiConfig(any(ScanResult.class));
691 tracker.forceUpdate();
692 verify(mockWifiManager).getMatchingWifiConfig(any(ScanResult.class));
693 }
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700694
695 @Test
696 public void rssiChangeBroadcastShouldUpdateConnectedAp() throws Exception {
697 WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
698 assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
699
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700700 int newRssi = CONNECTED_RSSI + 10;
701 WifiInfo info = new WifiInfo(CONNECTED_AP_1_INFO);
702 info.setRssi(newRssi);
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700703
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700704 CountDownLatch latch = new CountDownLatch(1);
705
706 // Once the new info has been fetched, we need to wait for the access points to be copied
707 doAnswer(invocation -> {
708 latch.countDown();
709 mAccessPointsChangedLatch = new CountDownLatch(1);
710 return info;
711 }).when(mockWifiManager).getConnectionInfo();
712
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700713 tracker.mReceiver.onReceive(mContext, new Intent(WifiManager.RSSI_CHANGED_ACTION));
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700714 assertTrue("New connection info never retrieved",
715 latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
716 assertTrue("onAccessPointsChanged never called",
717 mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700718
Sundeep Ghuman8c792882017-04-04 17:23:29 -0700719 assertThat(tracker.getAccessPoints().get(0).getRssi()).isEqualTo(newRssi);
720 }
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -0700721
722 @Test
723 public void forceUpdateShouldSynchronouslyFetchLatestInformation() throws Exception {
Sundeep Ghumance6bab82017-04-19 16:21:46 -0700724 Network mockNetwork = mock(Network.class);
725 when(mockWifiManager.getCurrentNetwork()).thenReturn(mockNetwork);
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700726
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -0700727 when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO);
728
729 WifiConfiguration configuration = new WifiConfiguration();
730 configuration.SSID = SSID_1;
731 configuration.BSSID = BSSID_1;
732 configuration.networkId = CONNECTED_NETWORK_ID;
733 when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
734
735 NetworkInfo networkInfo = new NetworkInfo(
736 ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
737 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
738 when(mockConnectivityManager.getNetworkInfo(any(Network.class))).thenReturn(networkInfo);
739
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -0700740 WifiTracker tracker = createMockedWifiTracker();
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -0700741 tracker.forceUpdate();
742
Sundeep Ghumance6bab82017-04-19 16:21:46 -0700743 verify(mockWifiManager).getConnectionInfo();
744 verify(mockWifiManager, times(2)).getConfiguredNetworks();
745 verify(mockConnectivityManager).getNetworkInfo(any(Network.class));
746
Sundeep Ghumand2b84a82017-07-05 14:19:30 -0700747 verify(mockWifiListener, never()).onAccessPointsChanged(); // mStaleAccessPoints is true
Sundeep Ghuman9c0b97e2017-04-13 16:05:46 -0700748 assertThat(tracker.getAccessPoints().size()).isEqualTo(2);
749 assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
750 }
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700751
752 @Test
753 public void stopTrackingShouldRemoveWifiListenerCallbacks() throws Exception {
754 WifiTracker tracker = createMockedWifiTracker();
755 startTracking(tracker);
756
757 CountDownLatch latch = new CountDownLatch(1);
758 CountDownLatch lock = new CountDownLatch(1);
759 tracker.mMainHandler.post(() -> {
760 try {
761 lock.await();
762 latch.countDown();
763 } catch (InterruptedException e) {
764 fail("Interrupted Exception while awaiting lock release: " + e);
765 }
766 });
767
768 // Enqueue messages
769 tracker.mMainHandler.sendEmptyMessage(
770 WifiTracker.MainHandler.MSG_ACCESS_POINT_CHANGED);
771 tracker.mMainHandler.sendEmptyMessage(
772 WifiTracker.MainHandler.MSG_CONNECTED_CHANGED);
773 tracker.mMainHandler.sendEmptyMessage(
774 WifiTracker.MainHandler.MSG_WIFI_STATE_CHANGED);
775
776 tracker.stopTracking();
777
778 verify(mockWifiListener, atMost(1)).onAccessPointsChanged();
779 verify(mockWifiListener, atMost(1)).onConnectedChanged();
780 verify(mockWifiListener, atMost(1)).onWifiStateChanged(anyInt());
781
782 lock.countDown();
Sundeep Ghumance6bab82017-04-19 16:21:46 -0700783 assertTrue("Latch timed out", latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
Sundeep Ghuman71f4a822017-04-18 19:51:46 -0700784
785 assertThat(tracker.mMainHandler.hasMessages(
786 WifiTracker.MainHandler.MSG_ACCESS_POINT_CHANGED)).isFalse();
787 assertThat(tracker.mMainHandler.hasMessages(
788 WifiTracker.MainHandler.MSG_CONNECTED_CHANGED)).isFalse();
789 assertThat(tracker.mMainHandler.hasMessages(
790 WifiTracker.MainHandler.MSG_WIFI_STATE_CHANGED)).isFalse();
791
792 verifyNoMoreInteractions(mockWifiListener);
793 }
Sundeep Ghumand4a79ac2017-06-07 18:11:39 -0700794
795 @Test
796 public void stopTrackingShouldSetStaleBitWhichPreventsCallbacksUntilNextScanResult()
797 throws Exception {
798 WifiTracker tracker = createMockedWifiTracker();
799 startTracking(tracker);
Sundeep Ghumane8013092017-06-21 22:35:30 -0700800 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghumand4a79ac2017-06-07 18:11:39 -0700801
Sundeep Ghumane8013092017-06-21 22:35:30 -0700802 tracker.stopTracking();
803 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghumand4a79ac2017-06-07 18:11:39 -0700804
805 startTracking(tracker);
806
807 tracker.mReceiver.onReceive(mContext, new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION));
808 tracker.mReceiver.onReceive(
809 mContext, new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
810 tracker.mReceiver.onReceive(
811 mContext, new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION));
812
Sundeep Ghumane8013092017-06-21 22:35:30 -0700813 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghumand4a79ac2017-06-07 18:11:39 -0700814
815 verify(mockWifiListener, never()).onAccessPointsChanged();
816
817 sendScanResultsAndProcess(tracker); // verifies onAccessPointsChanged is invoked
818 }
Sundeep Ghumane8013092017-06-21 22:35:30 -0700819
820 @Test
Sundeep Ghumand2b84a82017-07-05 14:19:30 -0700821 public void startTrackingShouldNotSendAnyCallbacksUntilScanResultsAreProcessed()
822 throws Exception {
823 WifiTracker tracker = createMockedWifiTracker();
824 startTracking(tracker);
825 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
826
827 tracker.mReceiver.onReceive(mContext, new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION));
828 tracker.mReceiver.onReceive(
829 mContext, new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
830 tracker.mReceiver.onReceive(
831 mContext, new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION));
832
833 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
834 verify(mockWifiListener, never()).onAccessPointsChanged();
835
836 sendScanResultsAndProcess(tracker); // verifies onAccessPointsChanged is invoked
837 }
838
839 @Test
Sundeep Ghumane8013092017-06-21 22:35:30 -0700840 public void disablingWifiShouldClearExistingAccessPoints() throws Exception {
841 WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
842
843 when(mockWifiManager.isWifiEnabled()).thenReturn(false);
844 mAccessPointsChangedLatch = new CountDownLatch(1);
845 tracker.mReceiver.onReceive(mContext, new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION));
846
847 mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
848 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
849
850 assertThat(tracker.getAccessPoints()).isEmpty();
851 }
Sundeep Ghuman42058742017-07-21 18:42:10 -0700852
853 @Test
854 public void onConnectedChangedCallback_shouldNotBeInvokedWhenNoStateChange() throws Exception {
855 WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
856 verify(mockWifiListener, times(1)).onConnectedChanged();
857
858 NetworkInfo networkInfo = new NetworkInfo(
859 ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
860 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
861
862 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
863 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
864 tracker.mReceiver.onReceive(mContext, intent);
865
Sundeep Ghumandb2eabb2017-07-28 14:51:05 -0700866 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
Sundeep Ghuman42058742017-07-21 18:42:10 -0700867 verify(mockWifiListener, times(1)).onConnectedChanged();
868 }
869
870 @Test
Sundeep Ghumandb2eabb2017-07-28 14:51:05 -0700871 public void onConnectedChangedCallback_shouldBeInvokedWhenStateChanges() throws Exception {
Sundeep Ghuman42058742017-07-21 18:42:10 -0700872 WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
873 verify(mockWifiListener, times(1)).onConnectedChanged();
874
875 NetworkInfo networkInfo = new NetworkInfo(
876 ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
877 networkInfo.setDetailedState(
Sundeep Ghumandb2eabb2017-07-28 14:51:05 -0700878 NetworkInfo.DetailedState.DISCONNECTED, "disconnected", "test");
Sundeep Ghuman42058742017-07-21 18:42:10 -0700879
880 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
881 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
882 tracker.mReceiver.onReceive(mContext, intent);
883
Sundeep Ghumandb2eabb2017-07-28 14:51:05 -0700884 waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
885 assertThat(tracker.isConnected()).isFalse();
Sundeep Ghuman42058742017-07-21 18:42:10 -0700886 verify(mockWifiListener, times(2)).onConnectedChanged();
887 }
Peter Qiuabea7262017-05-31 10:18:17 -0700888}