*/
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;
* 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
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();
}
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);
}
/**
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);
break;
case MSG_RECOMMENDATIONS_PACKAGE_CHANGED:
+ case MSG_RECOMMENDATION_ENABLED_SETTING_CHANGED:
refreshBinding();
break;
@Nullable
@VisibleForTesting
public NetworkScorerAppData getActiveScorer() {
+ final int enabledSetting = getNetworkRecommendationsEnabledSetting();
+ if (enabledSetting == NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF) {
+ return null;
+ }
+
return getScorer(getNetworkRecommendationsPackage());
}
*/
@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);
+ }
}
}
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.
*/
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);
+ }
}
}
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;
}
@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,
}
@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";
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) {