summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java301
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java4
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java25
3 files changed, 163 insertions, 167 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 04aaf8fca9c1..646b6ba84ebb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -15,6 +15,7 @@
*/
package com.android.settingslib.wifi;
+import android.annotation.MainThread;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -40,6 +41,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
+import android.support.annotation.GuardedBy;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
@@ -64,8 +66,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
* Tracks saved or available wifi networks and their state.
*/
public class WifiTracker {
- // TODO(sghuman): Document remaining methods with @UiThread and @WorkerThread where possible.
- // TODO(sghuman): Refactor to avoid calling certain methods on the UiThread.
// TODO(b/36733768): Remove flag includeSaved and includePasspoints.
private static final String TAG = "WifiTracker";
@@ -96,34 +96,34 @@ public class WifiTracker {
private WifiTrackerNetworkCallback mNetworkCallback;
private int mNumSavedNetworks;
+
+ @GuardedBy("mLock")
private boolean mRegistered;
- /** Updated using main handler. Clone of this collection is returned
- * from {@link #getAccessPoints()}
+ /**
+ * The externally visible access point list.
+ *
+ * Updated using main handler. Clone of this collection is returned from
+ * {@link #getAccessPoints()}
*/
private final List<AccessPoint> mAccessPoints = new ArrayList<>();
/**
- * Protects APs contained in {@link #mInternalAccessPoints} from being modified concurrently
- * while its being read. Usage contract:
+ * The internal list of access points, synchronized on itself.
*
- * 1. MainHandler opens the condition after copying the states thereby
- * allowing WorkerHandler to mutate the contents.
- * 2. WorkerHandler after mutating the contents, sends a message to MainHandler to copy the
- * states and closes the condition.
- *
- * This is better than synchronizing on a variable because it prevents MainHandler from
- * unnecessarily blocking/waiting to acquire lock for copying states. When MainHandler is about
- * to access {@link #mInternalAccessPoints}, it is assumed that it has exclusively lock on the
- * contents.
- */
- private final ConditionVariable mInternalAccessPointsWriteLock = new ConditionVariable(true);
-
- /** Guarded by mInternalAccessPointsWriteLock, updated using worker handler.
* Never exposed outside this class.
*/
+ @GuardedBy("mLock")
private final List<AccessPoint> mInternalAccessPoints = new ArrayList<>();
+ /**
+ * Synchronization lock for managing concurrency between main and worker threads.
+ *
+ * <p>This lock should be held for all background work.
+ * TODO(b/37674366): Remove the worker thread so synchronization is no longer necessary.
+ */
+ private final Object mLock = new Object();
+
//visible to both worker and main thread. Guarded by #mInternalAccessPoints
private final AccessPointListenerAdapter mAccessPointListenerAdapter
= new AccessPointListenerAdapter();
@@ -137,10 +137,12 @@ public class WifiTracker {
private final NetworkScoreManager mNetworkScoreManager;
private final WifiNetworkScoreCache mScoreCache;
- private final Set<NetworkKey> mRequestedScores = new ArraySet<>();
private boolean mNetworkScoringUiEnabled;
private final ContentObserver mObserver;
+ @GuardedBy("mLock")
+ private final Set<NetworkKey> mRequestedScores = new ArraySet<>();
+
@VisibleForTesting
Scanner mScanner;
@@ -211,13 +213,17 @@ public class WifiTracker {
mNetworkScoreManager = networkScoreManager;
- mScoreCache = new WifiNetworkScoreCache(context, new CacheListener(mMainHandler) {
+ mScoreCache = new WifiNetworkScoreCache(context, new CacheListener(mWorkHandler) {
@Override
public void networkCacheUpdated(List<ScoredNetwork> networks) {
+ synchronized (mLock) {
+ if (!mRegistered) return;
+ }
+
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Score cache was updated with networks: " + networks);
}
- Message.obtain(mWorkHandler, WorkHandler.MSG_UPDATE_NETWORK_SCORES).sendToTarget();
+ updateNetworkScores();
}
});
@@ -235,17 +241,19 @@ public class WifiTracker {
/**
* Synchronously update the list of access points with the latest information.
*/
+ @MainThread
public void forceUpdate() {
- mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
-
- mLastInfo = mWifiManager.getConnectionInfo();
- mLastNetworkInfo = mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());
- updateAccessPoints();
-
- // Synchronously copy access points
- mMainHandler.removeMessages(MainHandler.MSG_ACCESS_POINT_CHANGED);
- mMainHandler.handleMessage(
- Message.obtain(mMainHandler, MainHandler.MSG_ACCESS_POINT_CHANGED));
+ synchronized (mLock) {
+ mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+ mLastInfo = mWifiManager.getConnectionInfo();
+ mLastNetworkInfo = mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());
+ updateAccessPointsLocked();
+
+ // Synchronously copy access points
+ mMainHandler.removeMessages(MainHandler.MSG_ACCESS_POINT_CHANGED);
+ mMainHandler.handleMessage(
+ Message.obtain(mMainHandler, MainHandler.MSG_ACCESS_POINT_CHANGED));
+ }
}
/**
@@ -289,22 +297,25 @@ public class WifiTracker {
* <p>Registers listeners and starts scanning for wifi networks. If this is not called
* then forceUpdate() must be called to populate getAccessPoints().
*/
+ @MainThread
public void startTracking() {
- registerScoreCache();
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.NETWORK_SCORING_UI_ENABLED),
- false /* notifyForDescendants */,
- mObserver);
- mObserver.onChange(false /* selfChange */); // Set the initial value for mScoringUiEnabled
-
- resumeScanning();
- if (!mRegistered) {
- mContext.registerReceiver(mReceiver, mFilter);
- // NetworkCallback objects cannot be reused. http://b/20701525 .
- mNetworkCallback = new WifiTrackerNetworkCallback();
- mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
- mRegistered = true;
+ synchronized (mLock) {
+ registerScoreCache();
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.NETWORK_SCORING_UI_ENABLED),
+ false /* notifyForDescendants */,
+ mObserver);
+ mObserver.onChange(false /* selfChange */); // Set mScoringUiEnabled
+
+ resumeScanning();
+ if (!mRegistered) {
+ mContext.registerReceiver(mReceiver, mFilter);
+ // NetworkCallback objects cannot be reused. http://b/20701525 .
+ mNetworkCallback = new WifiTrackerNetworkCallback();
+ mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
+ mRegistered = true;
+ }
}
}
@@ -322,44 +333,49 @@ public class WifiTracker {
Log.d(TAG, "Requesting scores for Network Keys: " + keys);
}
mNetworkScoreManager.requestScores(keys.toArray(new NetworkKey[keys.size()]));
- mRequestedScores.addAll(keys);
+ synchronized (mLock) {
+ mRequestedScores.addAll(keys);
+ }
}
/**
* Stop tracking wifi networks and scores.
*
- * <p>Unregisters all listeners and stops scanning for wifi networks. This should always
- * be called when done with a WifiTracker (if startTracking was called) to ensure
- * proper cleanup.
+ * <p>This should always be called when done with a WifiTracker (if startTracking was called) to
+ * ensure proper cleanup and prevent any further callbacks from occuring.
*/
+ @MainThread
public void stopTracking() {
- if (mRegistered) {
- mContext.unregisterReceiver(mReceiver);
- mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
- mRegistered = false;
- }
- mWorkHandler.removePendingMessages();
- mMainHandler.removePendingMessages();
-
- pauseScanning();
-
- unregisterAndClearScoreCache();
+ synchronized (mLock) {
+ if (mRegistered) {
+ mContext.unregisterReceiver(mReceiver);
+ mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
+ mRegistered = false;
+ }
+ unregisterAndClearScoreCache();
+ pauseScanning();
+ mContext.getContentResolver().unregisterContentObserver(mObserver);
- mContext.getContentResolver().unregisterContentObserver(mObserver);
+ mWorkHandler.removePendingMessages();
+ mMainHandler.removePendingMessages();
+ }
}
private void unregisterAndClearScoreCache() {
mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, mScoreCache);
mScoreCache.clearScores();
- // Clear the scores on the work handler to avoid concurrent modification exceptions
- mWorkHandler.post(() -> mRequestedScores.clear());
+ // Synchronize on mLock to avoid concurrent modification during updateAccessPointsLocked
+ synchronized (mLock) {
+ mRequestedScores.clear();
+ }
}
/**
* Gets the current list of access points. Should be called from main thread, otherwise
* expect inconsistencies
*/
+ @MainThread
public List<AccessPoint> getAccessPoints() {
return new ArrayList<>(mAccessPoints);
}
@@ -440,16 +456,20 @@ public class WifiTracker {
return null;
}
- private void updateAccessPoints() {
- // Wait until main worker is done copying the states. This is done to prevent propagation
- // of accesspoint states while the update is in progress.
- long before = System.currentTimeMillis();
- mInternalAccessPointsWriteLock.block();
- if (DBG) {
- Log.d(TAG, "Acquired AP lock on WorkerHandler. Time to wait = "
- + (System.currentTimeMillis() - before) + " ms.");
+ /** Safely modify {@link #mInternalAccessPoints} by acquiring {@link #mLock} first. */
+ private void updateAccessPointsLocked() {
+ synchronized (mLock) {
+ updateAccessPoints();
}
+ }
+ /**
+ * Update the internal list of access points.
+ *
+ * <p>Should never be called directly, use {@link #updateAccessPointsLocked()} instead.
+ */
+ @GuardedBy("mLock")
+ private void updateAccessPoints() {
// Swap the current access points into a cached list.
List<AccessPoint> cachedAccessPoints = new ArrayList<>(mInternalAccessPoints);
ArrayList<AccessPoint> accessPoints = new ArrayList<>();
@@ -459,8 +479,8 @@ public class WifiTracker {
accessPoint.clearConfig();
}
- /* Lookup table to more quickly update AccessPoints by only considering objects with the
- * correct SSID. Maps SSID -> List of AccessPoints with the given SSID. */
+ /* Lookup table to more quickly update AccessPoints by only considering objects with the
+ * correct SSID. Maps SSID -> List of AccessPoints with the given SSID. */
Multimap<String, AccessPoint> apMap = new Multimap<String, AccessPoint>();
WifiConfiguration connectionConfig = null;
if (mLastInfo != null) {
@@ -583,7 +603,8 @@ public class WifiTracker {
mInternalAccessPoints.clear();
mInternalAccessPoints.addAll(accessPoints);
- mMainHandler.scheduleAPCopyingAndCloseWriteLock();
+
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_ACCESS_POINT_CHANGED);
}
@VisibleForTesting
@@ -640,59 +661,48 @@ public class WifiTracker {
connectionConfig = getWifiConfigurationForNetworkId(mLastInfo.getNetworkId());
}
- // Lock required to prevent accidental copying of AccessPoint states while the modification
- // is in progress. see #copyAndNotifyListeners
- long before = System.currentTimeMillis();
- mInternalAccessPointsWriteLock.block();
- if (DBG) {
- Log.d(TAG, "Acquired AP lock on WorkerHandler for updating NetworkInfo. Wait time = " +
- (System.currentTimeMillis() - before) + "ms.");
- }
-
boolean updated = false;
boolean reorder = false; // Only reorder if connected AP was changed
- for (int i = mInternalAccessPoints.size() - 1; i >= 0; --i) {
- AccessPoint ap = mInternalAccessPoints.get(i);
- boolean previouslyConnected = ap.isActive();
- if (ap.update(connectionConfig, mLastInfo, mLastNetworkInfo)) {
- updated = true;
- if (previouslyConnected != ap.isActive()) reorder = true;
- }
- if (ap.update(mScoreCache, mNetworkScoringUiEnabled)) {
- reorder = true;
- updated = true;
+
+ synchronized (mLock) {
+ for (int i = mInternalAccessPoints.size() - 1; i >= 0; --i) {
+ AccessPoint ap = mInternalAccessPoints.get(i);
+ boolean previouslyConnected = ap.isActive();
+ if (ap.update(connectionConfig, mLastInfo, mLastNetworkInfo)) {
+ updated = true;
+ if (previouslyConnected != ap.isActive()) reorder = true;
+ }
+ if (ap.update(mScoreCache, mNetworkScoringUiEnabled)) {
+ reorder = true;
+ updated = true;
+ }
}
- }
- if (reorder) Collections.sort(mInternalAccessPoints);
+ if (reorder) Collections.sort(mInternalAccessPoints);
- if (updated) mMainHandler.scheduleAPCopyingAndCloseWriteLock();
+ if (updated) mMainHandler.sendEmptyMessage(MainHandler.MSG_ACCESS_POINT_CHANGED);
+ }
}
/**
* Update all the internal access points rankingScores, badge and metering.
*
* <p>Will trigger a resort and notify listeners of changes if applicable.
+ *
+ * <p>Synchronized on {@link #mLock}.
*/
private void updateNetworkScores() {
- // Lock required to prevent accidental copying of AccessPoint states while the modification
- // is in progress. see #copyAndNotifyListeners
- long before = System.currentTimeMillis();
- mInternalAccessPointsWriteLock.block();
- if (DBG) {
- Log.d(TAG, "Acquired AP lock on WorkerHandler for inserting NetworkScores. Wait time = " +
- (System.currentTimeMillis() - before) + "ms.");
- }
-
- boolean reorder = false;
- for (int i = 0; i < mInternalAccessPoints.size(); i++) {
- if (mInternalAccessPoints.get(i).update(mScoreCache, mNetworkScoringUiEnabled)) {
- reorder = true;
+ synchronized (mLock) {
+ boolean updated = false;
+ for (int i = 0; i < mInternalAccessPoints.size(); i++) {
+ if (mInternalAccessPoints.get(i).update(mScoreCache, mNetworkScoringUiEnabled)) {
+ updated = true;
+ }
+ }
+ if (updated) {
+ Collections.sort(mInternalAccessPoints);
+ mMainHandler.sendEmptyMessage(MainHandler.MSG_ACCESS_POINT_CHANGED);
}
- }
- if (reorder) {
- Collections.sort(mInternalAccessPoints);
- mMainHandler.scheduleAPCopyingAndCloseWriteLock();
}
}
@@ -732,7 +742,10 @@ public class WifiTracker {
.sendToTarget();
mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
} else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
- mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_NETWORK_INFO);
+ NetworkInfo info =
+ mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());
+ mWorkHandler.obtainMessage(WorkHandler.MSG_UPDATE_NETWORK_INFO, info)
+ .sendToTarget();
}
}
};
@@ -789,19 +802,8 @@ public class WifiTracker {
}
}
- void scheduleAPCopyingAndCloseWriteLock() {
- //prevent worker thread from modifying mInternalAccessPoints
- mInternalAccessPointsWriteLock.close();
- sendEmptyMessage(MSG_ACCESS_POINT_CHANGED);
- }
-
void removePendingMessages() {
- // Only release the lock if there was a pending message which would have done the same
- if (mMainHandler.hasMessages(MSG_ACCESS_POINT_CHANGED)) {
- mMainHandler.removeMessages(MSG_ACCESS_POINT_CHANGED);
- mInternalAccessPointsWriteLock.open();
- }
-
+ removeMessages(MSG_ACCESS_POINT_CHANGED);
removeMessages(MSG_CONNECTED_CHANGED);
removeMessages(MSG_WIFI_STATE_CHANGED);
removeMessages(MSG_PAUSE_SCANNING);
@@ -814,7 +816,6 @@ public class WifiTracker {
private static final int MSG_UPDATE_NETWORK_INFO = 1;
private static final int MSG_RESUME = 2;
private static final int MSG_UPDATE_WIFI_STATE = 3;
- private static final int MSG_UPDATE_NETWORK_SCORES = 4;
public WorkHandler(Looper looper) {
super(looper);
@@ -822,9 +823,18 @@ public class WifiTracker {
@Override
public void handleMessage(Message msg) {
+ synchronized (mLock) {
+ processMessage(msg);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void processMessage(Message msg) {
+ if (!mRegistered) return;
+
switch (msg.what) {
case MSG_UPDATE_ACCESS_POINTS:
- updateAccessPoints();
+ updateAccessPointsLocked();
break;
case MSG_UPDATE_NETWORK_INFO:
updateNetworkInfo((NetworkInfo) msg.obj);
@@ -849,9 +859,6 @@ public class WifiTracker {
mMainHandler.obtainMessage(MainHandler.MSG_WIFI_STATE_CHANGED, msg.arg1, 0)
.sendToTarget();
break;
- case MSG_UPDATE_NETWORK_SCORES:
- updateNetworkScores();
- break;
}
}
@@ -860,7 +867,6 @@ public class WifiTracker {
removeMessages(MSG_UPDATE_NETWORK_INFO);
removeMessages(MSG_RESUME);
removeMessages(MSG_UPDATE_WIFI_STATE);
- removeMessages(MSG_UPDATE_NETWORK_SCORES);
}
}
@@ -980,11 +986,12 @@ public class WifiTracker {
/**
* Responsible for copying access points from {@link #mInternalAccessPoints} and notifying
- * accesspoint listeners. Mutation of the accesspoints returned is done on the main thread.
+ * accesspoint listeners.
*
* @param notifyListeners if true, accesspoint listeners are notified, otherwise notifications
* dropped.
*/
+ @MainThread
private void copyAndNotifyListeners(boolean notifyListeners) {
// Need to watch out for memory allocations on main thread.
SparseArray<AccessPoint> oldAccessPoints = new SparseArray<>();
@@ -995,17 +1002,15 @@ public class WifiTracker {
oldAccessPoints.put(accessPoint.mId, accessPoint);
}
- //synchronize to prevent modification of "mInternalAccessPoints" by worker thread.
- long before = System.currentTimeMillis();
- try {
- if (DBG) {
- Log.d(TAG, "Starting to copy AP items on the MainHandler");
- }
- if (notifyListeners) {
- notificationMap = mAccessPointListenerAdapter.mPendingNotifications.clone();
- }
+ if (DBG) {
+ Log.d(TAG, "Starting to copy AP items on the MainHandler");
+ }
+ if (notifyListeners) {
+ notificationMap = mAccessPointListenerAdapter.mPendingNotifications.clone();
+ }
- mAccessPointListenerAdapter.mPendingNotifications.clear();
+ mAccessPointListenerAdapter.mPendingNotifications.clear();
+ synchronized (mLock) {
for (AccessPoint internalAccessPoint : mInternalAccessPoints) {
AccessPoint accessPoint = oldAccessPoints.get(internalAccessPoint.mId);
if (accessPoint == null) {
@@ -1015,12 +1020,6 @@ public class WifiTracker {
}
updatedAccessPoints.add(accessPoint);
}
- } finally {
- mInternalAccessPointsWriteLock.open();
- if (DBG) {
- Log.d(TAG, "Opened AP Write lock on the MainHandler. Time to copy = " +
- (System.currentTimeMillis() - before) + " ms.");
- }
}
mAccessPoints.clear();
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java
index a2becf717e89..79cee046140d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java
@@ -23,8 +23,6 @@ import android.support.annotation.Keep;
* Factory method used to inject WifiTracker instances.
*/
public class WifiTrackerFactory {
- private static boolean sTestingMode = false;
-
private static WifiTracker sTestingWifiTracker;
@Keep // Keep proguard from stripping this method since it is only used in tests
@@ -35,7 +33,7 @@ public class WifiTrackerFactory {
public static WifiTracker create(
Context context, WifiTracker.WifiListener wifiListener, Looper workerLooper,
boolean includeSaved, boolean includeScans, boolean includePasspoints) {
- if(sTestingMode) {
+ if(sTestingWifiTracker != null) {
return sTestingWifiTracker;
}
return new WifiTracker(
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 621041a4675d..f519a906eab5 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -27,6 +27,8 @@ import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -253,9 +255,7 @@ public class WifiTrackerTest {
tracker.mReceiver.onReceive(mContext, intent);
}
- mAccessPointsChangedLatch = new CountDownLatch(1);
sendScanResultsAndProcess(tracker);
- assertTrue(mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
return tracker;
}
@@ -465,9 +465,10 @@ public class WifiTrackerTest {
private void updateScoresAndWaitForAccessPointsChangedCallback() throws InterruptedException {
// Updating scores can happen together or one after the other, so the latch countdown is set
// to 2.
- mAccessPointsChangedLatch = new CountDownLatch(2);
+ mAccessPointsChangedLatch = new CountDownLatch(3);
updateScores();
- mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertTrue("onAccessPointChanged was not called three times",
+ mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
}
@Test
@@ -651,12 +652,6 @@ public class WifiTrackerTest {
WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
- WifiConfiguration configuration = new WifiConfiguration();
- configuration.SSID = SSID_1;
- configuration.BSSID = BSSID_1;
- configuration.networkId = CONNECTED_NETWORK_ID;
- when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
-
int newRssi = CONNECTED_RSSI + 10;
WifiInfo info = new WifiInfo(CONNECTED_AP_1_INFO);
info.setRssi(newRssi);
@@ -681,7 +676,8 @@ public class WifiTrackerTest {
@Test
public void forceUpdateShouldSynchronouslyFetchLatestInformation() throws Exception {
- // TODO(sghuman): Fix flakiness of this test
+ Network mockNetwork = mock(Network.class);
+ when(mockWifiManager.getCurrentNetwork()).thenReturn(mockNetwork);
when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO);
@@ -697,9 +693,12 @@ public class WifiTrackerTest {
when(mockConnectivityManager.getNetworkInfo(any(Network.class))).thenReturn(networkInfo);
WifiTracker tracker = createMockedWifiTracker();
- startTracking(tracker);
tracker.forceUpdate();
+ verify(mockWifiManager).getConnectionInfo();
+ verify(mockWifiManager, times(2)).getConfiguredNetworks();
+ verify(mockConnectivityManager).getNetworkInfo(any(Network.class));
+
verify(mockWifiListener).onAccessPointsChanged();
assertThat(tracker.getAccessPoints().size()).isEqualTo(2);
assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
@@ -736,7 +735,7 @@ public class WifiTrackerTest {
verify(mockWifiListener, atMost(1)).onWifiStateChanged(anyInt());
lock.countDown();
- assertTrue(latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
+ assertTrue("Latch timed out", latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
assertThat(tracker.mMainHandler.hasMessages(
WifiTracker.MainHandler.MSG_ACCESS_POINT_CHANGED)).isFalse();