Updates to the cache filtering impl.

Addressing comments from ag/1828816.

Test: runtest frameworks-services -c com.android.server.NetworkScoreServiceTest
Bug: 34127291
Change-Id: I4c927caaedc722400c8cb52334ab261afa1ffaa5
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index dab4dfb..8d37b0f 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -60,6 +60,7 @@
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
 import android.util.TimedRemoteCaller;
@@ -77,12 +78,13 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.BiConsumer;
-import java.util.function.Function;
 import java.util.function.Supplier;
+import java.util.function.UnaryOperator;
 
 /**
  * Backing service for {@link android.net.NetworkScoreManager}.
@@ -91,6 +93,7 @@
 public class NetworkScoreService extends INetworkScoreService.Stub {
     private static final String TAG = "NetworkScoreService";
     private static final boolean DBG = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean VERBOSE = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE);
 
     private final Context mContext;
     private final NetworkScorerAppManager mNetworkScorerAppManager;
@@ -407,7 +410,7 @@
                 }
 
                 final BiConsumer<INetworkScoreCache, Object> consumer =
-                        new FilteringCacheUpdatingConsumer(mContext, entry.getValue(),
+                        FilteringCacheUpdatingConsumer.create(mContext, entry.getValue(),
                                 entry.getKey());
                 sendCacheUpdateCallback(consumer, Collections.singleton(callbackList));
             }
@@ -424,25 +427,28 @@
      * accepted {@link INetworkScoreCache} implementation.
      */
     @VisibleForTesting
-    public static class FilteringCacheUpdatingConsumer
+    static class FilteringCacheUpdatingConsumer
             implements BiConsumer<INetworkScoreCache, Object> {
         private final Context mContext;
         private final List<ScoredNetwork> mScoredNetworkList;
         private final int mNetworkType;
-        // TODO(jjoslin): 1/23/17 - Consider a Map if we implement more filters.
-        private Function<List<ScoredNetwork>, List<ScoredNetwork>> mCurrentNetworkFilter;
-        private Function<List<ScoredNetwork>, List<ScoredNetwork>> mScanResultsFilter;
+        // TODO: 1/23/17 - Consider a Map if we implement more filters.
+        // These are created on-demand to defer the construction cost until
+        // an instance is actually needed.
+        private UnaryOperator<List<ScoredNetwork>> mCurrentNetworkFilter;
+        private UnaryOperator<List<ScoredNetwork>> mScanResultsFilter;
 
-        public FilteringCacheUpdatingConsumer(Context context,
+        static FilteringCacheUpdatingConsumer create(Context context,
                 List<ScoredNetwork> scoredNetworkList, int networkType) {
-            this(context, scoredNetworkList, networkType, null, null);
+            return new FilteringCacheUpdatingConsumer(context, scoredNetworkList, networkType,
+                    null, null);
         }
 
         @VisibleForTesting
-        public FilteringCacheUpdatingConsumer(Context context,
+        FilteringCacheUpdatingConsumer(Context context,
                 List<ScoredNetwork> scoredNetworkList, int networkType,
-                Function<List<ScoredNetwork>, List<ScoredNetwork>> currentNetworkFilter,
-                Function<List<ScoredNetwork>, List<ScoredNetwork>> scanResultsFilter) {
+                UnaryOperator<List<ScoredNetwork>> currentNetworkFilter,
+                UnaryOperator<List<ScoredNetwork>> scanResultsFilter) {
             mContext = context;
             mScoredNetworkList = scoredNetworkList;
             mNetworkType = networkType;
@@ -461,11 +467,10 @@
                 final List<ScoredNetwork> filteredNetworkList =
                         filterScores(mScoredNetworkList, filterType);
                 if (!filteredNetworkList.isEmpty()) {
-                    networkScoreCache.updateScores(
-                            Collections.unmodifiableList(filteredNetworkList));
+                    networkScoreCache.updateScores(filteredNetworkList);
                 }
             } catch (RemoteException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                if (VERBOSE) {
                     Log.v(TAG, "Unable to update scores of type " + mNetworkType, e);
                 }
             }
@@ -554,10 +559,8 @@
      *       the computation is only done once.
      */
     @VisibleForTesting
-    public static class CurrentNetworkScoreCacheFilter
-            implements Function<List<ScoredNetwork>, List<ScoredNetwork>> {
+    static class CurrentNetworkScoreCacheFilter implements UnaryOperator<List<ScoredNetwork>> {
         private final NetworkKey mCurrentNetwork;
-        private Pair<List<ScoredNetwork>, Integer> mCache;
 
         CurrentNetworkScoreCacheFilter(Supplier<WifiInfo> wifiInfoSupplier) {
             mCurrentNetwork = NetworkKey.createFromWifiInfo(wifiInfoSupplier.get());
@@ -569,25 +572,14 @@
                 return Collections.emptyList();
             }
 
-            final int inputListHash = scoredNetworks.hashCode();
-            if (mCache == null || mCache.second != inputListHash) {
-                ScoredNetwork currentScore = null;
-                for (int i = 0; i < scoredNetworks.size(); i++) {
-                    final ScoredNetwork scoredNetwork = scoredNetworks.get(i);
-                    if (scoredNetwork.networkKey.equals(mCurrentNetwork)) {
-                        currentScore = scoredNetwork;
-                        break;
-                    }
-                }
-
-                if (currentScore == null) {
-                    mCache = Pair.create(Collections.emptyList(), inputListHash);
-                } else {
-                    mCache = Pair.create(Collections.singletonList(currentScore), inputListHash);
+            for (int i = 0; i < scoredNetworks.size(); i++) {
+                final ScoredNetwork scoredNetwork = scoredNetworks.get(i);
+                if (scoredNetwork.networkKey.equals(mCurrentNetwork)) {
+                    return Collections.singletonList(scoredNetwork);
                 }
             }
 
-            return mCache.first;
+            return Collections.emptyList();
         }
     }
 
@@ -602,15 +594,14 @@
      *       times in a row the computation is only done once.
      */
     @VisibleForTesting
-    public static class ScanResultsScoreCacheFilter
-            implements Function<List<ScoredNetwork>, List<ScoredNetwork>> {
-        private final List<NetworkKey> mScanResultKeys;
-        private Pair<List<ScoredNetwork>, Integer> mCache;
+    static class ScanResultsScoreCacheFilter implements UnaryOperator<List<ScoredNetwork>> {
+        private final Set<NetworkKey> mScanResultKeys;
 
         ScanResultsScoreCacheFilter(Supplier<List<ScanResult>> resultsSupplier) {
-            mScanResultKeys = new ArrayList<>();
             List<ScanResult> scanResults = resultsSupplier.get();
-            for (int i = 0; i < scanResults.size(); i++) {
+            final int size = scanResults.size();
+            mScanResultKeys = new ArraySet<>(size);
+            for (int i = 0; i < size; i++) {
                 ScanResult scanResult = scanResults.get(i);
                 mScanResultKeys.add(NetworkKey.createFromScanResult(scanResult));
             }
@@ -622,22 +613,15 @@
                 return Collections.emptyList();
             }
 
-            final int inputListHash = scoredNetworks.hashCode();
-            if (mCache == null || mCache.second != inputListHash) {
-                List<ScoredNetwork> filteredScores = new ArrayList<>();
-                for (int i = 0; i < scoredNetworks.size(); i++) {
-                    final ScoredNetwork scoredNetwork = scoredNetworks.get(i);
-                    for (int j = 0; j < mScanResultKeys.size(); j++) {
-                        final NetworkKey scanResultKey = mScanResultKeys.get(j);
-                        if (scanResultKey.equals(scoredNetwork.networkKey)) {
-                            filteredScores.add(scoredNetwork);
-                        }
-                    }
+            List<ScoredNetwork> filteredScores = new ArrayList<>();
+            for (int i = 0; i < scoredNetworks.size(); i++) {
+                final ScoredNetwork scoredNetwork = scoredNetworks.get(i);
+                if (mScanResultKeys.contains(scoredNetwork.networkKey)) {
+                    filteredScores.add(scoredNetwork);
                 }
-                mCache = Pair.create(filteredScores, inputListHash);
             }
 
-            return mCache.first;
+            return filteredScores;
         }
     }
 
@@ -796,7 +780,7 @@
                     return caller.getRecommendationResult(provider, request);
                 } catch (RemoteException | TimeoutException e) {
                     Log.w(TAG, "Failed to request a recommendation.", e);
-                    // TODO(jjoslin): 12/15/16 - Keep track of failures.
+                    // TODO: 12/15/16 - Keep track of failures.
                 }
             }
 
@@ -850,7 +834,7 @@
                     return;
                 } catch (RemoteException e) {
                     Log.w(TAG, "Failed to request a recommendation.", e);
-                    // TODO(jjoslin): 12/15/16 - Keep track of failures.
+                    // TODO: 12/15/16 - Keep track of failures.
                     // Remove the timeout message
                     mHandler.removeMessages(timeoutMsg.what, pair);
                     // Will fall through and send back the default recommendation.
@@ -873,12 +857,12 @@
             if (provider != null) {
                 try {
                     provider.requestScores(networks);
-                    // TODO(jjoslin): 12/15/16 - Consider pushing null scores into the cache to
+                    // TODO: 12/15/16 - Consider pushing null scores into the cache to
                     // prevent repeated requests for the same scores.
                     return true;
                 } catch (RemoteException e) {
                     Log.w(TAG, "Failed to request scores.", e);
-                    // TODO(jjoslin): 12/15/16 - Keep track of failures.
+                    // TODO: 12/15/16 - Keep track of failures.
                 }
             }
             return false;