diff options
| author | 2017-03-06 10:39:35 -0800 | |
|---|---|---|
| committer | 2017-03-07 10:13:41 -0800 | |
| commit | 9925c6a7e703a1267aef47d4b17c494d1fedb162 (patch) | |
| tree | 68c22e64acab044fc2bc3b1cd102d3140ad48cb4 | |
| parent | 8aa30c04b89292328177c02ffd37469de699f1ad (diff) | |
Keep Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED updated.
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
5 files changed, 207 insertions, 32 deletions
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index 7b7a21cdae4c..e6fe0d0df76a 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -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; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index c4a5be7f1ea6..a9282c1e748e 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -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 diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java index b83dbd686ae5..46c9f25dbccf 100644 --- a/services/core/java/com/android/server/NetworkScoreService.java +++ b/services/core/java/com/android/server/NetworkScoreService.java @@ -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; diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java index 90a33a4a217a..5b627d934209 100644 --- a/services/core/java/com/android/server/NetworkScorerAppManager.java +++ b/services/core/java/com/android/server/NetworkScorerAppManager.java @@ -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); + } } } diff --git a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java index 502bf06dd6d6..64f176a41ba8 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java @@ -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) { |