Observe settings in RecommendedNetworkEvaluator.

If NETWORK_RECOMMENDATIONS_ENABLED is set, use
RecommendedNetworkEvaluator, otherwise use ExternalScoreEvaluator.
Previously, this setting was only respected at boot time, however,
users can toggle this setting at runtime. This change forwards method
calls on RecommendedNetworkEvaluator to ExternalScoreEvaluator when
this setting is disabled. ExternalScoreEvaluator will be removed in
a later change.

Test: runtests.sh
Bug: 33694202
Change-Id: I67e73d4e2c4cdff465d23056b59554fc9d8ab64a
diff --git a/service/java/com/android/server/wifi/RecommendedNetworkEvaluator.java b/service/java/com/android/server/wifi/RecommendedNetworkEvaluator.java
index 2d481ec..88e17b9 100644
--- a/service/java/com/android/server/wifi/RecommendedNetworkEvaluator.java
+++ b/service/java/com/android/server/wifi/RecommendedNetworkEvaluator.java
@@ -16,6 +16,9 @@
 
 package com.android.server.wifi;
 
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
 import android.net.NetworkKey;
 import android.net.NetworkScoreManager;
 import android.net.RecommendationRequest;
@@ -25,11 +28,15 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiNetworkScoreCache;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.Process;
+import android.provider.Settings;
 import android.util.LocalLog;
 import android.util.Pair;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.wifi.util.ScanResultUtil;
 
 import java.util.ArrayList;
@@ -45,19 +52,42 @@
     private final WifiNetworkScoreCache mNetworkScoreCache;
     private final WifiConfigManager mWifiConfigManager;
     private final LocalLog mLocalLog;
+    private final ExternalScoreEvaluator mExternalScoreEvaluator;
+    @VisibleForTesting final ContentObserver mContentObserver;
+    private boolean mNetworkRecommendationsEnabled;
 
-    RecommendedNetworkEvaluator(WifiNetworkScoreCache networkScoreCache,
+    RecommendedNetworkEvaluator(final Context context, ContentResolver contentResolver,
+            Looper looper, final FrameworkFacade frameworkFacade,
+            WifiNetworkScoreCache networkScoreCache,
             NetworkScoreManager networkScoreManager, WifiConfigManager wifiConfigManager,
-            LocalLog localLog) {
+            LocalLog localLog, ExternalScoreEvaluator externalScoreEvaluator) {
         mNetworkScoreCache = networkScoreCache;
         mNetworkScoreManager = networkScoreManager;
         mWifiConfigManager = wifiConfigManager;
         mLocalLog = localLog;
+        mExternalScoreEvaluator = externalScoreEvaluator; // TODO(b/33694202): Remove
+        mContentObserver = new ContentObserver(new Handler(looper)) {
+            @Override
+            public void onChange(boolean selfChange) {
+                mNetworkRecommendationsEnabled = frameworkFacade.getIntegerSetting(context,
+                        Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) == 1;
+            }
+        };
+        contentResolver.registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED),
+                false /* notifyForDescendents */, mContentObserver);
+        mContentObserver.onChange(false /* unused */);
+        mLocalLog.log("RecommendedNetworkEvaluator constructed. mNetworkRecommendationsEnabled: "
+                + mNetworkRecommendationsEnabled);
     }
 
     @Override
     public void update(List<ScanDetail> scanDetails) {
-        updateNetworkScoreCache(scanDetails);
+        if (mNetworkRecommendationsEnabled) {
+            updateNetworkScoreCache(scanDetails);
+        } else {
+            mExternalScoreEvaluator.update(scanDetails);
+        }
     }
 
     private void updateNetworkScoreCache(List<ScanDetail> scanDetails) {
@@ -91,6 +121,10 @@
             WifiConfiguration currentNetwork, String currentBssid, boolean connected,
             boolean untrustedNetworkAllowed,
             List<Pair<ScanDetail, WifiConfiguration>> connectableNetworks) {
+        if (!mNetworkRecommendationsEnabled) {
+            return mExternalScoreEvaluator.evaluateNetworks(scanDetails, currentNetwork,
+                    currentBssid, connected, untrustedNetworkAllowed, connectableNetworks);
+        }
         List<ScanResult> scanResults = new ArrayList<>();
         for (int i = 0; i < scanDetails.size(); i++) {
             ScanDetail scanDetail = scanDetails.get(i);
@@ -169,6 +203,9 @@
 
     @Override
     public String getName() {
-        return TAG;
+        if (mNetworkRecommendationsEnabled) {
+            return TAG;
+        }
+        return TAG + "-" + mExternalScoreEvaluator.getName();
     }
 }
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index feda606..bd4887a 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -29,7 +29,6 @@
 import android.net.wifi.WifiScanner.ScanSettings;
 import android.os.Handler;
 import android.os.Looper;
-import android.provider.Settings;
 import android.util.LocalLog;
 
 import com.android.internal.R;
@@ -119,7 +118,7 @@
 
     // Saved network evaluator priority
     private static final int SAVED_NETWORK_EVALUATOR_PRIORITY = 1;
-    private static final int EXTERNAL_SCORE_EVALUATOR_PRIORITY = 2;
+    private static final int RECOMMENDED_NETWORK_EVALUATOR_PRIORITY = 2;
 
     private final WifiStateMachine mStateMachine;
     private final WifiScanner mScanner;
@@ -472,7 +471,6 @@
             WifiLastResortWatchdog wifiLastResortWatchdog, WifiMetrics wifiMetrics,
             Looper looper, Clock clock, boolean enable, FrameworkFacade frameworkFacade,
             SavedNetworkEvaluator savedNetworkEvaluator,
-            ExternalScoreEvaluator externalScoreEvaluator,
             RecommendedNetworkEvaluator recommendedNetworkEvaluator) {
         mStateMachine = stateMachine;
         mScanner = scanner;
@@ -520,12 +518,8 @@
         // Register the network evaluators
         mNetworkSelector.registerNetworkEvaluator(savedNetworkEvaluator,
                 SAVED_NETWORK_EVALUATOR_PRIORITY);
-        final WifiNetworkSelector.NetworkEvaluator networkEvaluator =
-                frameworkFacade.getIntegerSetting(context,
-                        Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) == 1
-                        ? recommendedNetworkEvaluator : externalScoreEvaluator;
-        mNetworkSelector.registerNetworkEvaluator(networkEvaluator,
-                EXTERNAL_SCORE_EVALUATOR_PRIORITY);
+        mNetworkSelector.registerNetworkEvaluator(recommendedNetworkEvaluator,
+                RECOMMENDED_NETWORK_EVALUATOR_PRIORITY);
 
         // Register for all single scan results
         mScanner.registerScanListener(mAllSingleScanListener);
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index b08404b..5fcfb5d 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -91,7 +91,6 @@
     private final WifiConfigManager mWifiConfigManager;
     private final WifiNetworkSelector mWifiNetworkSelector;
     private final SavedNetworkEvaluator mSavedNetworkEvaluator;
-    private final ExternalScoreEvaluator mExternalScoreEvaluator;
     private final RecommendedNetworkEvaluator mRecommendedNetworkEvaluator;
     private final WifiNetworkScoreCache mWifiNetworkScoreCache;
     private final NetworkScoreManager mNetworkScoreManager;
@@ -163,10 +162,12 @@
         LocalLog localLog = mWifiNetworkSelector.getLocalLog();
         mSavedNetworkEvaluator = new SavedNetworkEvaluator(mContext,
                 mWifiConfigManager, mClock, localLog);
-        mExternalScoreEvaluator = new ExternalScoreEvaluator(
+        ExternalScoreEvaluator externalScoreEvaluator = new ExternalScoreEvaluator(
                 mContext, mWifiConfigManager, mWifiNetworkScoreCache, mClock, localLog);
-        mRecommendedNetworkEvaluator = new RecommendedNetworkEvaluator(
-                mWifiNetworkScoreCache, mNetworkScoreManager, mWifiConfigManager, localLog);
+        mRecommendedNetworkEvaluator = new RecommendedNetworkEvaluator(context,
+                context.getContentResolver(), mWifiStateMachineHandlerThread.getLooper(),
+                mFrameworkFacade, mWifiNetworkScoreCache, mNetworkScoreManager, mWifiConfigManager,
+                localLog, externalScoreEvaluator);
         mWifiStateMachine = new WifiStateMachine(mContext, mFrameworkFacade,
                 mWifiStateMachineHandlerThread.getLooper(), UserManager.get(mContext),
                 this, mBackupManagerProxy, mCountryCode, mWifiNative);
@@ -375,7 +376,7 @@
                 mWifiConfigManager, wifiInfo, mWifiNetworkSelector, mWifiLastResortWatchdog,
                 mWifiMetrics, mWifiStateMachineHandlerThread.getLooper(), mClock,
                 hasConnectionRequests, mFrameworkFacade, mSavedNetworkEvaluator,
-                mExternalScoreEvaluator, mRecommendedNetworkEvaluator);
+                mRecommendedNetworkEvaluator);
     }
 
     public WifiPermissionsUtil getWifiPermissionsUtil() {
diff --git a/tests/wifitests/src/com/android/server/wifi/RecommendedNetworkEvaluatorTest.java b/tests/wifitests/src/com/android/server/wifi/RecommendedNetworkEvaluatorTest.java
index b974470..c8915de 100644
--- a/tests/wifitests/src/com/android/server/wifi/RecommendedNetworkEvaluatorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/RecommendedNetworkEvaluatorTest.java
@@ -27,6 +27,8 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
+import android.content.ContentResolver;
+import android.content.Context;
 import android.net.NetworkKey;
 import android.net.NetworkScoreManager;
 import android.net.RecommendationRequest;
@@ -36,7 +38,9 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiNetworkScoreCache;
 import android.net.wifi.WifiSsid;
+import android.os.Looper;
 import android.os.Process;
+import android.provider.Settings;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.LocalLog;
 
@@ -73,10 +77,14 @@
         UNTRUSTED_WIFI_CONFIGURATION.BSSID = UNTRUSTED_SCAN_DETAIL.getBSSIDString();
     }
 
+    @Mock private Context mContext;
+    @Mock private ContentResolver mContentResolver;
+    @Mock private FrameworkFacade mFrameworkFacade;
     @Mock private NetworkScoreManager mNetworkScoreManager;
     @Mock private WifiConfigManager mWifiConfigManager;
     @Mock private NetworkScoreManager mScoreManager;
     @Mock private WifiNetworkScoreCache mNetworkScoreCache;
+    @Mock private ExternalScoreEvaluator mExternalScoreEvaluator;
 
     @Captor private ArgumentCaptor<NetworkKey[]> mNetworkKeyArrayCaptor;
     @Captor private ArgumentCaptor<RecommendationRequest> mRecommendationRequestCaptor;
@@ -86,8 +94,12 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mRecommendedNetworkEvaluator = new RecommendedNetworkEvaluator(
-                mNetworkScoreCache, mNetworkScoreManager, mWifiConfigManager, new LocalLog(0));
+        when(mFrameworkFacade.getIntegerSetting(mContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0))
+                .thenReturn(1);
+        mRecommendedNetworkEvaluator = new RecommendedNetworkEvaluator(mContext, mContentResolver,
+                Looper.getMainLooper(), mFrameworkFacade, mNetworkScoreCache, mNetworkScoreManager,
+                mWifiConfigManager, new LocalLog(0), mExternalScoreEvaluator);
 
         when(mWifiConfigManager.getSavedNetworkForScanDetailAndCache(TRUSTED_SCAN_DETAIL))
                 .thenReturn(TRUSTED_WIFI_CONFIGURATION);
@@ -98,6 +110,21 @@
     }
 
     @Test
+    public void testUpdate_recommendationsDisabled() {
+        ArrayList<ScanDetail> scanDetails = new ArrayList<>();
+        when(mFrameworkFacade.getIntegerSetting(mContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0))
+                .thenReturn(0);
+
+        mRecommendedNetworkEvaluator.mContentObserver.onChange(false /* unused */);
+
+        mRecommendedNetworkEvaluator.update(scanDetails);
+
+        verify(mExternalScoreEvaluator).update(scanDetails);
+        verifyZeroInteractions(mNetworkScoreManager, mNetworkScoreManager);
+    }
+
+    @Test
     public void testUpdate_emptyScanList() {
         mRecommendedNetworkEvaluator.update(new ArrayList<ScanDetail>());
 
@@ -136,6 +163,21 @@
     }
 
     @Test
+    public void testEvaluateNetworks_recommendationsDisabled() {
+        when(mFrameworkFacade.getIntegerSetting(mContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0))
+                .thenReturn(0);
+
+        mRecommendedNetworkEvaluator.mContentObserver.onChange(false /* unused */);
+
+        mRecommendedNetworkEvaluator.evaluateNetworks(null, null, null, false, false, null);
+
+        verify(mExternalScoreEvaluator).evaluateNetworks(null, null, null, false, false, null);
+
+        verifyZeroInteractions(mWifiConfigManager, mNetworkScoreManager);
+    }
+
+    @Test
     public void testEvaluateNetworks_emptyScanList() {
         WifiConfiguration result = mRecommendedNetworkEvaluator.evaluateNetworks(
                 new ArrayList<ScanDetail>(), null, null, false,
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
index 56af3fb..f3c0573 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
@@ -259,7 +259,7 @@
         return new WifiConnectivityManager(mContext, mWifiStateMachine, mWifiScanner,
                 mWifiConfigManager, mWifiInfo, mWifiNS,
                 mWifiLastResortWatchdog, mWifiMetrics, mLooper.getLooper(), mClock, true,
-                mFrameworkFacade, null, null, null);
+                mFrameworkFacade, null, null);
     }
 
     /**