OSDN Git Service

Keep Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED updated.
authorJeremy Joslin <jjoslin@google.com>
Mon, 6 Mar 2017 18:39:35 +0000 (10:39 -0800)
committerJeremy Joslin <jjoslin@google.com>
Tue, 7 Mar 2017 18:13:41 +0000 (10:13 -0800)
Make sure Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED reflects
the current active scorer state. When valid the setting will have a
value of 1, when invalid it will be 0 (or more
accurately not 1, see below).

Introduced a new valid setting value, -1, which indicates the feature
has been forced off.

Test: runtest frameworks-services -c com.android.server.NetworkScorerAppManagerTest
Test: runtest frameworks-services -c com.android.server.NetworkScoreServiceTest
Bug: 35896421
Change-Id: I271725f798e5d0acc7c08c79678dba5115f8faad

core/java/android/net/NetworkScoreManager.java
core/java/android/provider/Settings.java
services/core/java/com/android/server/NetworkScoreService.java
services/core/java/com/android/server/NetworkScorerAppManager.java
services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java

index 7b7a21c..e6fe0d0 100644 (file)
@@ -171,6 +171,43 @@ public class NetworkScoreManager {
      */
     public static final int CACHE_FILTER_SCAN_RESULTS = 2;
 
+    /** @hide */
+    @IntDef({RECOMMENDATIONS_ENABLED_FORCED_OFF, RECOMMENDATIONS_ENABLED_OFF,
+            RECOMMENDATIONS_ENABLED_ON})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RecommendationsEnabledSetting {}
+
+    /**
+     * Recommendations have been forced off.
+     * <p>
+     * This value is never set by any of the NetworkScore classes, it must be set via other means.
+     * This state is also "sticky" and we won't transition out of this state once entered. To move
+     * to a different state this value has to be explicitly set to a different value via
+     * other means.
+     * @hide
+     */
+    public static final int RECOMMENDATIONS_ENABLED_FORCED_OFF = -1;
+
+    /**
+     * Recommendations are not enabled.
+     * <p>
+     * This is a transient state that can be entered when the default recommendation app is enabled
+     * but no longer valid. This state will transition to RECOMMENDATIONS_ENABLED_ON when a valid
+     * recommendation app is enabled.
+     * @hide
+     */
+    public static final int RECOMMENDATIONS_ENABLED_OFF = 0;
+
+    /**
+     * Recommendations are enabled.
+     * <p>
+     * This is a transient state that means a valid recommendation app is active. This state will
+     * transition to RECOMMENDATIONS_ENABLED_OFF if the current and default recommendation apps
+     * become invalid.
+     * @hide
+     */
+    public static final int RECOMMENDATIONS_ENABLED_ON = 1;
+
     private final Context mContext;
     private final INetworkScoreService mService;
 
index c4a5be7..a9282c1 100755 (executable)
@@ -8233,7 +8233,14 @@ public final class Settings {
          * Value to specify if network recommendations from
          * {@link com.android.server.NetworkScoreService} are enabled.
          *
-         * Type: int (0 for false, 1 for true)
+         * Type: int
+         * Valid values:
+         *   -1 = Forced off
+         *    0 = Disabled
+         *    1 = Enabled
+         *
+         * Most readers of this setting should simply check if value == 1 to determined the
+         * enabled state.
          * @hide
          */
         @SystemApi
index b83dbd6..46c9f25 100644 (file)
@@ -277,8 +277,8 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
 
     private void refreshBinding() {
         if (DBG) Log.d(TAG, "refreshBinding()");
-        // Apply the default package name if the Setting isn't set.
-        mNetworkScorerAppManager.revertToDefaultIfNoActive();
+        // Make sure the scorer is up-to-date
+        mNetworkScorerAppManager.updateState();
         registerPackageMonitorIfNeeded();
         bindToScoringServiceIfNeeded();
     }
@@ -291,6 +291,10 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
         final Uri timeoutUri = Global.getUriFor(Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS);
         mContentObserver.observe(timeoutUri,
                 ServiceHandler.MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED);
+
+        final Uri settingUri = Global.getUriFor(Global.NETWORK_RECOMMENDATIONS_ENABLED);
+        mContentObserver.observe(settingUri,
+                ServiceHandler.MSG_RECOMMENDATION_ENABLED_SETTING_CHANGED);
     }
 
     /**
@@ -1171,6 +1175,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
         public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT = 1;
         public static final int MSG_RECOMMENDATIONS_PACKAGE_CHANGED = 2;
         public static final int MSG_RECOMMENDATION_REQUEST_TIMEOUT_CHANGED = 3;
+        public static final int MSG_RECOMMENDATION_ENABLED_SETTING_CHANGED = 4;
 
         public ServiceHandler(Looper looper) {
             super(looper);
@@ -1192,6 +1197,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
                     break;
 
                 case MSG_RECOMMENDATIONS_PACKAGE_CHANGED:
+                case MSG_RECOMMENDATION_ENABLED_SETTING_CHANGED:
                     refreshBinding();
                     break;
 
index 90a33a4..5b627d9 100644 (file)
@@ -155,6 +155,11 @@ public class NetworkScorerAppManager {
     @Nullable
     @VisibleForTesting
     public NetworkScorerAppData getActiveScorer() {
+        final int enabledSetting = getNetworkRecommendationsEnabledSetting();
+        if (enabledSetting == NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF) {
+            return null;
+        }
+
         return getScorer(getNetworkRecommendationsPackage());
     }
 
@@ -194,39 +199,73 @@ public class NetworkScorerAppManager {
      */
     @VisibleForTesting
     public boolean setActiveScorer(String packageName) {
-        String oldPackageName = getNetworkRecommendationsPackage();
+        final String oldPackageName = getNetworkRecommendationsPackage();
+
         if (TextUtils.equals(oldPackageName, packageName)) {
             // No change.
             return true;
         }
 
-        Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
-
         if (packageName == null) {
             // revert to the default setting.
-            setNetworkRecommendationsPackage(getDefaultPackageSetting());
+            packageName = getDefaultPackageSetting();
+        }
+
+        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) {
+            setNetworkRecommendationsPackage(packageName);
             return true;
         } else {
-            // We only make the change if the new package is valid.
-            if (getScorer(packageName) != null) {
-                setNetworkRecommendationsPackage(packageName);
-                return true;
-            } else {
-                Log.w(TAG, "Requested network scorer is not valid: " + packageName);
-                return false;
-            }
+            Log.w(TAG, "Requested network scorer is not valid: " + packageName);
+            return false;
         }
     }
 
     /**
-     * If the active scorer is null then revert to the default scorer.
+     * Ensures the {@link Settings.Global#NETWORK_RECOMMENDATIONS_PACKAGE} setting points to a valid
+     * package and {@link Settings.Global#NETWORK_RECOMMENDATIONS_ENABLED} is consistent.
+     *
+     * If {@link Settings.Global#NETWORK_RECOMMENDATIONS_PACKAGE} doesn't point to a valid package
+     * then it will be reverted to the default package specified by
+     * {@link R.string#config_defaultNetworkRecommendationProviderPackage}. If the default package
+     * is no longer valid then {@link Settings.Global#NETWORK_RECOMMENDATIONS_ENABLED} will be set
+     * to <code>0</code> (disabled).
      */
     @VisibleForTesting
-    public void revertToDefaultIfNoActive() {
-        if (getActiveScorer() == null) {
-            final String defaultPackage = getDefaultPackageSetting();
-            setNetworkRecommendationsPackage(defaultPackage);
-            Log.i(TAG, "Defaulted the network recommendations app to: " + defaultPackage);
+    public void updateState() {
+        final int enabledSetting = getNetworkRecommendationsEnabledSetting();
+        if (enabledSetting == NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF) {
+            // Don't change anything if it's forced off.
+            if (DEBUG) Log.d(TAG, "Recommendations forced off.");
+            return;
+        }
+
+        // First, see if the current package is still valid. If so, then we can exit early.
+        final String currentPackageName = getNetworkRecommendationsPackage();
+        if (getScorer(currentPackageName) != null) {
+            if (VERBOSE) Log.v(TAG, currentPackageName + " is the active scorer.");
+            setNetworkRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
+            return;
+        }
+
+        // the active scorer isn't valid, revert to the default if it's different
+        final String defaultPackageName = getDefaultPackageSetting();
+        if (!TextUtils.equals(currentPackageName, defaultPackageName)) {
+            setNetworkRecommendationsPackage(defaultPackageName);
+            if (DEBUG) {
+                Log.d(TAG, "Defaulted the network recommendations app to: " + defaultPackageName);
+            }
+            if (getScorer(defaultPackageName) != null) { // the default is valid
+                if (DEBUG) Log.d(TAG, defaultPackageName + " is now the active scorer.");
+                setNetworkRecommendationsEnabledSetting(
+                        NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
+            } else { // the default isn't valid either, we're disabled at this point
+                if (DEBUG) Log.d(TAG, defaultPackageName + " is not an active scorer.");
+                setNetworkRecommendationsEnabledSetting(
+                        NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
+            }
         }
     }
 
@@ -244,6 +283,15 @@ public class NetworkScorerAppManager {
                 Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, packageName);
     }
 
+    private int getNetworkRecommendationsEnabledSetting() {
+        return mSettingsFacade.getInt(mContext, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0);
+    }
+
+    private void setNetworkRecommendationsEnabledSetting(int value) {
+        mSettingsFacade.putInt(mContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, value);
+    }
+
     /**
      * Wrapper around Settings to make testing easier.
      */
@@ -255,5 +303,13 @@ public class NetworkScorerAppManager {
         public String getString(Context context, String name) {
             return Settings.Global.getString(context.getContentResolver(), name);
         }
+
+        public boolean putInt(Context context, String name, int value) {
+            return Settings.Global.putInt(context.getContentResolver(), name, value);
+        }
+
+        public int getInt(Context context, String name, int defaultValue) {
+            return Settings.Global.getInt(context.getContentResolver(), name, defaultValue);
+        }
     }
 }
index 502bf06..64f176a 100644 (file)
@@ -23,6 +23,7 @@ import static junit.framework.Assert.assertTrue;
 
 import static org.junit.Assert.assertFalse;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -206,11 +207,14 @@ public class NetworkScorerAppManagerTest {
     }
 
     @Test
-    public void testSetActiveScorer_nullPackage() throws Exception {
+    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);
 
         assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
         verify(mSettingsFacade).putString(mMockContext,
@@ -218,6 +222,18 @@ public class NetworkScorerAppManagerTest {
     }
 
     @Test
+    public void testSetActiveScorer_nullPackage_invalidDefault() throws Exception {
+        String packageName = "package";
+        String defaultPackage = "defaultPackage";
+        setNetworkRecoPackageSetting(packageName);
+        setDefaultNetworkRecommendationPackage(defaultPackage);
+
+        assertFalse(mNetworkScorerAppManager.setActiveScorer(null));
+        verify(mSettingsFacade, never()).putString(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
+    }
+
+    @Test
     public void testSetActiveScorer_validPackage() throws Exception {
         String packageName = "package";
         String newPackage = "newPackage";
@@ -242,29 +258,82 @@ public class NetworkScorerAppManagerTest {
         verify(mSettingsFacade, never()).putString(any(), any(), any());
     }
 
-
     @Test
-    public void testRevertToDefaultIfNoActive_notActive() throws Exception {
-        String defaultPackage = "defaultPackage";
-        setDefaultNetworkRecommendationPackage(defaultPackage);
+    public void testUpdateState_recommendationsForcedOff() throws Exception {
+        setRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
 
-        mNetworkScorerAppManager.revertToDefaultIfNoActive();
+        mNetworkScorerAppManager.updateState();
 
-        verify(mSettingsFacade).putString(mMockContext,
-                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+        verify(mSettingsFacade, never()).getString(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE));
+        verify(mSettingsFacade, never()).putInt(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt());
     }
 
     @Test
-    public void testRevertToDefaultIfNoActive_active() throws Exception {
+    public void testUpdateState_currentPackageValid() throws Exception {
         String packageName = "package";
         setNetworkRecoPackageSetting(packageName);
         final ComponentName recoComponent = new ComponentName(packageName, "class1");
         mockScoreNetworksGranted(recoComponent.getPackageName());
         mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
 
-        mNetworkScorerAppManager.revertToDefaultIfNoActive();
+        mNetworkScorerAppManager.updateState();
 
-        verify(mSettingsFacade, never()).putString(any(), any(), any());
+        verify(mSettingsFacade, never()).putString(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
+        verify(mSettingsFacade).putInt(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+                NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
+    }
+
+    @Test
+    public void testUpdateState_currentPackageNotValid_validDefault() throws Exception {
+        String defaultPackage = "defaultPackage";
+        setDefaultNetworkRecommendationPackage(defaultPackage);
+        final ComponentName recoComponent = new ComponentName(defaultPackage, "class1");
+        mockScoreNetworksGranted(recoComponent.getPackageName());
+        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+
+        mNetworkScorerAppManager.updateState();
+
+        verify(mSettingsFacade).putString(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+        verify(mSettingsFacade).putInt(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+                NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
+    }
+
+    @Test
+    public void testUpdateState_currentPackageNotValid_invalidDefault() throws Exception {
+        String defaultPackage = "defaultPackage";
+        setDefaultNetworkRecommendationPackage(defaultPackage);
+        setNetworkRecoPackageSetting("currentPackage");
+
+        mNetworkScorerAppManager.updateState();
+
+        verify(mSettingsFacade).putString(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
+        verify(mSettingsFacade).putInt(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+                NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
+    }
+
+    @Test
+    public void testUpdateState_currentPackageNotValid_sameAsDefault() throws Exception {
+        String defaultPackage = "defaultPackage";
+        setDefaultNetworkRecommendationPackage(defaultPackage);
+        setNetworkRecoPackageSetting(defaultPackage);
+
+        mNetworkScorerAppManager.updateState();
+
+        verify(mSettingsFacade, never()).putString(any(),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
+    }
+
+    private void setRecommendationsEnabledSetting(int value) {
+        when(mSettingsFacade.getInt(eq(mMockContext),
+                eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt())).thenReturn(value);
     }
 
     private void setNetworkRecoPackageSetting(String packageName) {