diff options
| -rwxr-xr-x | wifi/java/android/net/wifi/WifiNetworkScoreCache.java | 63 | ||||
| -rw-r--r-- | wifi/tests/Android.mk | 13 | ||||
| -rw-r--r-- | wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java | 58 |
3 files changed, 81 insertions, 53 deletions
diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java index f61dfdc2f6f9..b22ae07015c8 100755 --- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java +++ b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java @@ -26,15 +26,14 @@ import android.net.ScoredNetwork; import android.os.Handler; import android.os.Process; import android.util.Log; +import android.util.LruCache; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** * {@link INetworkScoreCache} implementation for Wifi Networks. @@ -50,18 +49,21 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { // scorer to provide an RSSI threshold below which a network should not be used. public static final int INVALID_NETWORK_SCORE = Byte.MIN_VALUE; + /** Default number entries to be stored in the {@link LruCache}. */ + private static final int DEFAULT_MAX_CACHE_SIZE = 100; + // See {@link #CacheListener}. @Nullable - @GuardedBy("mCacheLock") + @GuardedBy("mLock") private CacheListener mListener; private final Context mContext; - private final Object mCacheLock = new Object(); + private final Object mLock = new Object(); // The key is of the form "<ssid>"<bssid> // TODO: What about SSIDs that can't be encoded as UTF-8? - private final Map<String, ScoredNetwork> mNetworkCache; - + @GuardedBy("mLock") + private final LruCache<String, ScoredNetwork> mCache; public WifiNetworkScoreCache(Context context) { this(context, null /* listener */); @@ -74,9 +76,14 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { * @param listener CacheListener for cache updates */ public WifiNetworkScoreCache(Context context, @Nullable CacheListener listener) { + this(context, listener, DEFAULT_MAX_CACHE_SIZE); + } + + public WifiNetworkScoreCache( + Context context, @Nullable CacheListener listener, int maxCacheSize) { mContext = context.getApplicationContext(); mListener = listener; - mNetworkCache = new HashMap<>(); + mCache = new LruCache<>(maxCacheSize); } @Override public final void updateScores(List<ScoredNetwork> networks) { @@ -89,7 +96,7 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { boolean changed = false; - synchronized(mNetworkCache) { + synchronized(mLock) { for (ScoredNetwork network : networks) { String networkKey = buildNetworkKey(network); if (networkKey == null) { @@ -98,12 +105,10 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } continue; } - mNetworkCache.put(networkKey, network); + mCache.put(networkKey, network); changed = true; } - } - synchronized (mCacheLock) { if (mListener != null && changed) { mListener.post(networks); } @@ -111,8 +116,8 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } @Override public final void clearScores() { - synchronized (mNetworkCache) { - mNetworkCache.clear(); + synchronized (mLock) { + mCache.evictAll(); } } @@ -138,7 +143,6 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } public int getNetworkScore(ScanResult result) { - int score = INVALID_NETWORK_SCORE; ScoredNetwork network = getScoredNetwork(result); @@ -164,7 +168,6 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } public int getNetworkScore(ScanResult result, boolean isActiveNetwork) { - int score = INVALID_NETWORK_SCORE; ScoredNetwork network = getScoredNetwork(result); @@ -185,8 +188,8 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { String key = buildNetworkKey(result); if (key == null) return null; - synchronized(mNetworkCache) { - ScoredNetwork network = mNetworkCache.get(key); + synchronized(mLock) { + ScoredNetwork network = mCache.get(key); return network; } } @@ -201,8 +204,8 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { } return null; } - synchronized (mNetworkCache) { - return mNetworkCache.get(key); + synchronized (mLock) { + return mCache.get(key); } } @@ -248,33 +251,35 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { mContext.getPackageName(), Process.myUid()); writer.println(header); writer.println(" All score curves:"); - for (ScoredNetwork score : mNetworkCache.values()) { - writer.println(" " + score); - } - writer.println(" Current network scores:"); - WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - for (ScanResult scanResult : wifiManager.getScanResults()) { - writer.println(" " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult)); + synchronized (mLock) { + for (ScoredNetwork score : mCache.snapshot().values()) { + writer.println(" " + score); + } + writer.println(" Network scores for latest ScanResults:"); + WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + for (ScanResult scanResult : wifiManager.getScanResults()) { + writer.println( + " " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult)); + } } } /** Registers a CacheListener instance, replacing the previous listener if it existed. */ public void registerListener(CacheListener listener) { - synchronized (mCacheLock) { + synchronized (mLock) { mListener = listener; } } /** Removes the registered CacheListener. */ public void unregisterListener() { - synchronized (mCacheLock) { + synchronized (mLock) { mListener = null; } } /** Listener for updates to the cache inside WifiNetworkScoreCache. */ public abstract static class CacheListener { - private Handler mHandler; /** diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk index afab1a3721db..c98e40a2c2d9 100644 --- a/wifi/tests/Android.mk +++ b/wifi/tests/Android.mk @@ -49,14 +49,15 @@ LOCAL_JACK_COVERAGE_INCLUDE_FILTER := $(jacoco_include) LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude) LOCAL_STATIC_JAVA_LIBRARIES := \ - android-support-test \ - core-test-rules \ - guava \ - mockito-target-minus-junit4 \ - frameworks-base-testutils \ + android-support-test \ + core-test-rules \ + guava \ + mockito-target-minus-junit4 \ + frameworks-base-testutils \ + truth-prebuilt \ LOCAL_JAVA_LIBRARIES := \ - android.test.runner \ + android.test.runner \ LOCAL_PACKAGE_NAME := FrameworksWifiApiTests LOCAL_COMPATIBILITY_SUITE := device-tests diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java index 18f6bc848081..997282b24b46 100644 --- a/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java +++ b/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java @@ -16,9 +16,9 @@ package android.net.wifi; -import static org.junit.Assert.*; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.verify; +import static com.google.common.truth.Truth.assertThat; + +import static org.junit.Assert.fail; import static org.mockito.Mockito.when; import android.content.Context; @@ -34,12 +34,9 @@ import android.support.test.runner.AndroidJUnit4; import com.google.common.collect.ImmutableList; -import org.junit.Rule; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -54,7 +51,11 @@ import java.util.concurrent.TimeUnit; public class WifiNetworkScoreCacheTest { public static final String SSID = "ssid"; + public static final String SSID2 = "ssid2"; + public static final String SSID3 = "ssid3"; public static final String FORMATTED_SSID = "\"" + SSID + "\""; + public static final String FORMATTED_SSID2 = "\"" + SSID2 + "\""; + public static final String FORMATTED_SSID3 = "\"" + SSID3 + "\""; public static final String BSSID = "AA:AA:AA:AA:AA:AA"; public static final WifiKey VALID_KEY = new WifiKey(FORMATTED_SSID, BSSID); @@ -120,13 +121,13 @@ public class WifiNetworkScoreCacheTest { @Test public void isScoredNetworkShouldReturnTrueAfterUpdateScoresIsCalled() { - assertTrue(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)); + assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue(); } @Test public void isScoredNetworkShouldReturnFalseAfterClearScoresIsCalled() { mScoreCache.clearScores(); - assertFalse(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)); + assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isFalse(); } @Test @@ -137,19 +138,19 @@ public class WifiNetworkScoreCacheTest { mScoreCache.updateScores(ImmutableList.of(network2)); - assertTrue(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)); - assertTrue(mScoreCache.isScoredNetwork(result2)); + assertThat(mScoreCache.isScoredNetwork(VALID_SCAN_RESULT)).isTrue(); + assertThat(mScoreCache.isScoredNetwork(result2)).isTrue(); } @Test public void hasScoreCurveShouldReturnTrue() { - assertTrue(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)); + assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isTrue(); } @Test public void hasScoreCurveShouldReturnFalseWhenNoCachedNetwork() { ScanResult unscored = buildScanResult("fake", BSSID); - assertFalse(mScoreCache.hasScoreCurve(unscored)); + assertThat(mScoreCache.hasScoreCurve(unscored)).isFalse(); } @Test @@ -157,7 +158,7 @@ public class WifiNetworkScoreCacheTest { ScoredNetwork noCurve = buildScoredNetwork(VALID_KEY, null /* rssiCurve */); mScoreCache.updateScores(ImmutableList.of(noCurve)); - assertFalse(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)); + assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse(); } @Test @@ -169,12 +170,12 @@ public class WifiNetworkScoreCacheTest { when(mockRssiCurve.lookupScore(rssi)).thenReturn(score); - assertEquals(score, mScoreCache.getNetworkScore(result)); + assertThat(mScoreCache.getNetworkScore(result)).isEqualTo(score); } @Test public void getMeteredHintShouldReturnFalse() { - assertFalse(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)); + assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isFalse(); } @Test @@ -184,7 +185,7 @@ public class WifiNetworkScoreCacheTest { new NetworkKey(VALID_KEY), mockRssiCurve, true /* metered Hint */); mScoreCache.updateScores(ImmutableList.of(network)); - assertTrue(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)); + assertThat(mScoreCache.getMeteredHint(VALID_SCAN_RESULT)).isTrue(); } @Test @@ -197,7 +198,28 @@ public class WifiNetworkScoreCacheTest { } catch (InterruptedException e) { fail("Interrupted Exception while waiting for listener to be invoked."); } - assertEquals("One network should be updated", 1, mUpdatedNetworksCaptor.size()); - assertEquals(mValidScoredNetwork, mUpdatedNetworksCaptor.get(0)); + // One network should be updated. + assertThat(mUpdatedNetworksCaptor.size()).isEqualTo(1); + assertThat(mUpdatedNetworksCaptor.get(0)).isEqualTo(mValidScoredNetwork); + } + + @Test + public void leastRecentlyUsedScore_shouldBeEvictedFromCache() { + mScoreCache = new WifiNetworkScoreCache(mockContext, mCacheListener, 2 /* maxCacheSize */); + + ScoredNetwork network1 = mValidScoredNetwork; + ScoredNetwork network2 = buildScoredNetwork( + new WifiKey(FORMATTED_SSID2, BSSID), mockRssiCurve); + ScoredNetwork network3 = buildScoredNetwork( + new WifiKey(FORMATTED_SSID3, BSSID), mockRssiCurve); + mScoreCache.updateScores(ImmutableList.of(network1)); + mScoreCache.updateScores(ImmutableList.of(network2)); + + // First score should be evicted because max cache size has been reached. + mScoreCache.updateScores(ImmutableList.of(network3)); + + assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID2, BSSID))).isTrue(); + assertThat(mScoreCache.hasScoreCurve(buildScanResult(SSID3, BSSID))).isTrue(); + assertThat(mScoreCache.hasScoreCurve(VALID_SCAN_RESULT)).isFalse(); } } |