Merge changes from topic 'allow_none_scorer' into oc-dev

* changes:
  Revert permission check on setActiveScorer.
  Allow the active scorer to be set to NULL.
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index 73e52c8..d163a44 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -45,7 +45,7 @@
      * Set the active scorer and clear existing scores.
      * @param packageName the package name of the new scorer to use.
      * @return true if the operation succeeded, or false if the new package is not a valid scorer.
-     * @throws SecurityException if the caller is not the system.
+     * @throws SecurityException if the caller is not the system or a network scorer.
      */
     boolean setActiveScorer(in String packageName);
 
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index eeb426a..9f6e45c 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -16,27 +16,20 @@
 
 package android.net;
 
-import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT;
-
+import android.Manifest.permission;
 import android.annotation.IntDef;
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.content.Context;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
-import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
-import java.util.concurrent.CompletableFuture;
 
 /**
  * Class that manages communication between network subsystems and a network scorer.
@@ -49,9 +42,9 @@
  *
  * <p>A network scorer is any application which:
  * <ul>
- * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
+ * <li>Declares the {@link permission#SCORE_NETWORKS} permission.
  * <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action
- *     protected by the {@link android.Manifest.permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
+ *     protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
  *     permission.
  * </ul>
  *
@@ -319,7 +312,7 @@
      *
      * @return true if the operation succeeded, or false if the new package is not a valid scorer.
      * @throws SecurityException if the caller is not a system process or does not hold the
-     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission
+     *         {@link permission#SCORE_NETWORKS} permission
      * @hide
      */
     @SystemApi
@@ -351,7 +344,7 @@
      *
      * @return true if the broadcast was sent, or false if there is no active scorer.
      * @throws SecurityException if the caller does not hold the
-     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
      * @hide
      */
     public boolean requestScores(NetworkKey[] networks) throws SecurityException {
@@ -368,7 +361,7 @@
      * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
      * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
      * @throws SecurityException if the caller does not hold the
-     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
      * @throws IllegalArgumentException if a score cache is already registered for this type.
      * @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE.
      * @hide
@@ -385,7 +378,7 @@
      * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
      * @param filterType the {@link CacheUpdateFilter} to apply
      * @throws SecurityException if the caller does not hold the
-     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
      * @throws IllegalArgumentException if a score cache is already registered for this type.
      * @hide
      */
@@ -404,7 +397,7 @@
      * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
      * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
      * @throws SecurityException if the caller does not hold the
-     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
+     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
      * @throws IllegalArgumentException if a score cache is already registered for this type.
      * @hide
      */
@@ -417,25 +410,6 @@
     }
 
     /**
-     * Request a recommendation for which network to connect to.
-     *
-     * <p>It is not safe to call this method from the main thread.
-     *
-     * @param request a {@link RecommendationRequest} instance containing additional
-     *                request details
-     * @return a {@link RecommendationResult} instance containing the recommended network
-     *         to connect to
-     * @throws SecurityException if the caller does not hold the
-     *         {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission.
-     * @hide
-     * @deprecated to be removed.
-     */
-    public RecommendationResult requestRecommendation(RecommendationRequest request)
-            throws SecurityException {
-        return null;
-    }
-
-    /**
      * Determine whether the application with the given UID is the enabled scorer.
      *
      * @param callingUid the UID to check
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 114d761..fdc0bba 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -631,6 +631,11 @@
                  PackageManager.PERMISSION_GRANTED;
     }
 
+    private boolean callerCanScoreNetworks() {
+        return mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS) ==
+                PackageManager.PERMISSION_GRANTED;
+    }
+
     @Override
     public boolean clearScores() {
         // Only the active scorer or the system should be allowed to flush all scores.
@@ -651,9 +656,9 @@
     @Override
     public boolean setActiveScorer(String packageName) {
         // Only the system can set the active scorer
-        if (!isCallerSystemProcess(getCallingUid()) && !callerCanRequestScores()) {
+        if (!isCallerSystemProcess(getCallingUid()) && !callerCanScoreNetworks()) {
             throw new SecurityException(
-                    "Caller is neither the system process nor a score requester.");
+                    "Caller is neither the system process or a network scorer.");
         }
 
         return mNetworkScorerAppManager.setActiveScorer(packageName);
diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java
index 8404025..42777bf 100644
--- a/services/core/java/com/android/server/NetworkScorerAppManager.java
+++ b/services/core/java/com/android/server/NetworkScorerAppManager.java
@@ -208,11 +208,11 @@
      *
      * <p>The caller must have permission to write to {@link Settings.Global}.
      *
-     * @param packageName the packageName of the new scorer to use. If null, the scoring app will
-     *                    revert back to the configured default. Otherwise, the scorer will only
-     *                    be set if it is a valid scorer application.
-     * @return true if the scorer was changed, or false if the package is not a valid scorer or
-     *         a valid network recommendation provider exists.
+     * @param packageName the packageName of the new scorer to use. If null, scoring will be forced
+     *                    off, otherwise the scorer will only be set if it is a valid scorer
+     *                    application.
+     * @return true if the package was a valid scorer (including <code>null</code>) and now
+     *         represents the active scorer, false otherwise.
      */
     @VisibleForTesting
     public boolean setActiveScorer(String packageName) {
@@ -223,16 +223,19 @@
             return true;
         }
 
-        if (packageName == null) {
-            // revert to the default setting.
-            packageName = getDefaultPackageSetting();
+        if (TextUtils.isEmpty(packageName)) {
+            Log.i(TAG, "Network scorer forced off, was: " + oldPackageName);
+            setNetworkRecommendationsPackage(null);
+            setNetworkRecommendationsEnabledSetting(
+                    NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
+            return true;
         }
 
-        Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
-
         // We only make the change if the new package is valid.
         if (getScorer(packageName) != null) {
+            Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
             setNetworkRecommendationsPackage(packageName);
+            setNetworkRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
             return true;
         } else {
             Log.w(TAG, "Requested network scorer is not valid: " + packageName);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index c78488f..bb7e20b 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -368,8 +368,8 @@
     }
 
     @Test
-    public void testSetActiveScorer_noRequestNetworkScoresPermission() {
-        when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
+    public void testSetActiveScorer_noScoreNetworksPermission() {
+        when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS))
                 .thenReturn(PackageManager.PERMISSION_DENIED);
 
         try {
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
index 0694eae..ceb92de 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
@@ -228,30 +228,23 @@
     }
 
     @Test
-    public void testSetActiveScorer_nullPackage_validDefault() throws Exception {
-        String packageName = "package";
-        String defaultPackage = "defaultPackage";
-        setNetworkRecoPackageSetting(packageName);
-        setDefaultNetworkRecommendationPackage(defaultPackage);
-        final ComponentName recoComponent = new ComponentName(defaultPackage, "class1");
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+    public void testSetActiveScorer_nullPackage_currentIsSet() throws Exception {
+        setNetworkRecoPackageSetting("package");
 
         assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
         verify(mSettingsFacade).putString(mMockContext,
-                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, null);
+        verify(mSettingsFacade).putInt(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+                NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
     }
 
     @Test
-    public void testSetActiveScorer_nullPackage_invalidDefault() throws Exception {
-        String packageName = "package";
-        String defaultPackage = "defaultPackage";
-        setNetworkRecoPackageSetting(packageName);
-        setDefaultNetworkRecommendationPackage(defaultPackage);
+    public void testSetActiveScorer_nullPackage_currentIsNull() throws Exception {
+        setNetworkRecoPackageSetting(null);
 
-        assertFalse(mNetworkScorerAppManager.setActiveScorer(null));
-        verify(mSettingsFacade, never()).putString(any(),
-                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
+        assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
+        verify(mSettingsFacade, never()).putString(any(), any(), any());
     }
 
     @Test
@@ -266,6 +259,9 @@
         assertTrue(mNetworkScorerAppManager.setActiveScorer(newPackage));
         verify(mSettingsFacade).putString(mMockContext,
                 Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, newPackage);
+        verify(mSettingsFacade).putInt(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+                NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
     }
 
     @Test
@@ -341,6 +337,32 @@
     }
 
     @Test
+    public void testUpdateState_currentPackageNull_defaultNull() throws Exception {
+        setDefaultNetworkRecommendationPackage(null);
+        setNetworkRecoPackageSetting(null);
+
+        mNetworkScorerAppManager.updateState();
+
+        verify(mSettingsFacade, never()).putString(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString());
+        verify(mSettingsFacade, never()).putInt(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt());
+    }
+
+    @Test
+    public void testUpdateState_currentPackageEmpty_defaultEmpty() throws Exception {
+        setDefaultNetworkRecommendationPackage("");
+        setNetworkRecoPackageSetting("");
+
+        mNetworkScorerAppManager.updateState();
+
+        verify(mSettingsFacade, never()).putString(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString());
+        verify(mSettingsFacade, never()).putInt(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt());
+    }
+
+    @Test
     public void testUpdateState_currentPackageNotValid_sameAsDefault() throws Exception {
         String defaultPackage = "defaultPackage";
         setDefaultNetworkRecommendationPackage(defaultPackage);