<!-- Checkbox title for option to notify user when open networks are nearby -->
<string name="wifi_notify_open_networks">Open network notification</string>
<!-- Checkbox summary for option to notify user when open networks are nearby-->
- <string name="wifi_notify_open_networks_summary">Notify whenever a high quality open network is available</string>
+ <string name="wifi_notify_open_networks_summary">Notify when a high\u2011quality open network is available that may require sign\u2011in</string>
<!-- Checkbox title for option to enable Wi-Fi when saved networks are nearby -->
<string name="wifi_wakeup">Turn Wi\u2011Fi back on</string>
- <!-- Checkbox summary for option to enable Wi-Fi when saved networks are nearby-->
- <string name="wifi_wakeup_summary">Automatically turn on Wi\u2011Fi near saved networks</string>
+ <!-- Checkbox summary for option to enable Wi-Fi when high quality saved networks are nearby-->
+ <string name="wifi_wakeup_summary">Automatically turn on Wi\u2011Fi near high\u2011quality saved networks</string>
<!-- Checkbox title for option to toggle poor network detection -->
<string name="wifi_poor_network_detection">Avoid poor connections</string>
<!-- Checkbox summary for option to toggle poor network detection -->
<string name="wifi_poor_network_detection_summary">Don\u2019t use a Wi\u2011Fi network unless it has a good Internet connection</string>
<!-- Checkbox summary for option to toggle poor network detection [CHAR LIMIT=60] -->
<string name="wifi_avoid_poor_network_detection_summary">Only use networks that have a good Internet connection</string>
-
+ <!-- Checkbox title for option to connect to open Wi-Fi automatically [CHAR LIMIT=40] -->
+ <string name="use_open_wifi_automatically_title">Connect to open networks</string>
+ <!-- Checkbox summary for option to connect to open Wi-Fi automatically [CHAR LIMIT=100] -->
+ <string name="use_open_wifi_automatically_summary">Automatically connect to high\u2011quality open networks </string>
<!-- Preference title for option to install certificates -->
<string name="wifi_install_credentials">Install certificates</string>
<!-- Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off. The
android:summary="@string/wifi_wakeup_summary" />
<SwitchPreference
+ android:key="use_open_wifi_automatically"
+ android:icon="@drawable/ic_vpn_key"
+ android:title="@string/use_open_wifi_automatically_title"
+ android:summary="@string/use_open_wifi_automatically_summary" />
+
+ <SwitchPreference
android:key="notify_open_networks"
android:title="@string/wifi_notify_open_networks"
android:icon="@drawable/ic_settings_notifications"
android:summary="@string/wifi_notify_open_networks_summary" />
<SwitchPreference
- android:key="wifi_cellular_data_fallback"
- android:title="@string/wifi_cellular_data_fallback_title"
- android:summary="@string/wifi_cellular_data_fallback_summary"/>
+ android:key="wifi_cellular_data_fallback"
+ android:title="@string/wifi_cellular_data_fallback_title"
+ android:summary="@string/wifi_cellular_data_fallback_summary"/>
<ListPreference
android:key="sleep_policy"
import static android.content.Context.WIFI_SERVICE;
import android.content.Context;
+import android.content.Intent;
import android.net.NetworkScoreManager;
import android.net.wifi.WifiManager;
import android.provider.SearchIndexableResource;
private static final String TAG = "ConfigureWifiSettings";
- private WifiManager mWifiManager;
+ private UseOpenWifiPreferenceController mUseOpenWifiPreferenceController;
@Override
public int getMetricsCategory() {
@Override
public void onAttach(Context context) {
super.onAttach(context);
- mProgressiveDisclosureMixin.setTileLimit(2);
+ mProgressiveDisclosureMixin.setTileLimit(
+ mUseOpenWifiPreferenceController.isAvailable() ? 3 : 2);
((SettingsActivity) getActivity()).setDisplaySearchMenu(true);
}
@Override
protected List<PreferenceController> getPreferenceControllers(Context context) {
- mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
+ final NetworkScoreManagerWrapper networkScoreManagerWrapper =
+ new NetworkScoreManagerWrapper(context.getSystemService(NetworkScoreManager.class));
+ mUseOpenWifiPreferenceController = new UseOpenWifiPreferenceController(context, this,
+ networkScoreManagerWrapper, getLifecycle());
+ final WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
final List<PreferenceController> controllers = new ArrayList<>();
- controllers.add(new WifiInfoPreferenceController(context, getLifecycle(), mWifiManager));
- controllers.add(new CellularFallbackPreferenceController(context));
- controllers.add(new NotifyOpenNetworksPreferenceController(context, getLifecycle()));
controllers.add(new WifiWakeupPreferenceController(context, getLifecycle()));
controllers.add(new NetworkScorerPickerPreferenceController(context,
- new NetworkScoreManagerWrapper(
- (NetworkScoreManager) getSystemService(NETWORK_SCORE_SERVICE))));
+ networkScoreManagerWrapper));
+ controllers.add(new NotifyOpenNetworksPreferenceController(context, getLifecycle()));
+ controllers.add(mUseOpenWifiPreferenceController);
controllers.add(new WifiSleepPolicyPreferenceController(context));
- controllers.add(new WifiP2pPreferenceController(context, getLifecycle(), mWifiManager));
+ controllers.add(new WifiInfoPreferenceController(context, getLifecycle(), wifiManager));
+ controllers.add(new CellularFallbackPreferenceController(context));
+ controllers.add(new WifiP2pPreferenceController(context, getLifecycle(), wifiManager));
controllers.add(new WifiCallingPreferenceController(context));
controllers.add(new WpsPreferenceController(
- context, getLifecycle(), mWifiManager, getFragmentManager()));
+ context, getLifecycle(), wifiManager, getFragmentManager()));
return controllers;
}
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (mUseOpenWifiPreferenceController == null ||
+ !mUseOpenWifiPreferenceController.onActivityResult(requestCode, resultCode)) {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
--- /dev/null
+package com.android.settings.wifi;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.net.NetworkScoreManager;
+
+import android.net.NetworkScorerAppData;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+
+import com.android.settings.network.NetworkScoreManagerWrapper;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.Lifecycle;
+import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnPause;
+import com.android.settings.core.lifecycle.events.OnResume;
+
+/**
+ * {@link PreferenceController} that controls whether a user wants to enable the "use open networks
+ * automatically" feature provider by the current network recommendation provider.
+ */
+public class UseOpenWifiPreferenceController extends PreferenceController
+ implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
+ private static final String KEY_USE_OPEN_WIFI_AUTOMATICALLY = "use_open_wifi_automatically";
+ @VisibleForTesting static final int REQUEST_CODE_OPEN_WIFI_AUTOMATICALLY = 400;
+
+ private final ContentResolver mContentResolver;
+ private final Fragment mFragment;
+ private final NetworkScoreManagerWrapper mNetworkScoreManagerWrapper;
+ private final SettingObserver mSettingObserver;
+
+ private Preference mPreference;
+ private ComponentName mEnableUseWifiComponentName;
+
+ public UseOpenWifiPreferenceController(Context context, Fragment fragment,
+ NetworkScoreManagerWrapper networkScoreManagerWrapper, Lifecycle lifecycle) {
+ super(context);
+ mContentResolver = context.getContentResolver();
+ mFragment = fragment;
+ mNetworkScoreManagerWrapper = networkScoreManagerWrapper;
+ mSettingObserver = new SettingObserver();
+ updateEnableUseWifiComponentName();
+ lifecycle.addObserver(this);
+ }
+
+ private void updateEnableUseWifiComponentName() {
+ NetworkScorerAppData appData = mNetworkScoreManagerWrapper.getActiveScorer();
+ mEnableUseWifiComponentName =
+ appData == null ? null : appData.getEnableUseOpenWifiActivity();
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(KEY_USE_OPEN_WIFI_AUTOMATICALLY);
+ }
+
+ @Override
+ public void onResume() {
+ mSettingObserver.register(mContentResolver);
+ }
+
+ @Override
+ public void onPause() {
+ mSettingObserver.unregister(mContentResolver);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mEnableUseWifiComponentName != null;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_USE_OPEN_WIFI_AUTOMATICALLY;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ if (!(preference instanceof SwitchPreference)) {
+ return;
+ }
+ final SwitchPreference useOpenWifiPreference = (SwitchPreference) preference;
+ useOpenWifiPreference.setVisible(isAvailable());
+ useOpenWifiPreference.setChecked(isSettingEnabled());
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (!TextUtils.equals(preference.getKey(), KEY_USE_OPEN_WIFI_AUTOMATICALLY)
+ || !isAvailable()) {
+ return false;
+ }
+
+ if (isSettingEnabled()) {
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.USE_OPEN_WIFI_PACKAGE, "");
+ return true;
+ }
+
+ Intent intent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE);
+ intent.setComponent(mEnableUseWifiComponentName);
+ mFragment.startActivityForResult(intent, REQUEST_CODE_OPEN_WIFI_AUTOMATICALLY);
+ return false; // Updating state is done in onActivityResult.
+ }
+
+ private boolean isSettingEnabled() {
+ String enabledUseOpenWifiPackage = Settings.Global.getString(mContentResolver,
+ Settings.Global.USE_OPEN_WIFI_PACKAGE);
+ String currentUseOpenWifiPackage = mEnableUseWifiComponentName == null
+ ? null : mEnableUseWifiComponentName.getPackageName();
+ return TextUtils.equals(enabledUseOpenWifiPackage, currentUseOpenWifiPackage);
+ }
+
+ public boolean onActivityResult(int requestCode, int resultCode) {
+ if (requestCode != REQUEST_CODE_OPEN_WIFI_AUTOMATICALLY) {
+ return false;
+ }
+
+ if (resultCode == Activity.RESULT_OK) {
+ Settings.Global.putString(mContentResolver, Settings.Global.USE_OPEN_WIFI_PACKAGE,
+ mEnableUseWifiComponentName.getPackageName());
+ }
+ return true;
+ }
+
+ class SettingObserver extends ContentObserver {
+ private final Uri NETWORK_RECOMMENDATIONS_ENABLED_URI =
+ Settings.Global.getUriFor(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED);
+
+ public SettingObserver() {
+ super(new Handler(Looper.getMainLooper()));
+ }
+
+ public void register(ContentResolver cr) {
+ cr.registerContentObserver(NETWORK_RECOMMENDATIONS_ENABLED_URI, false, this);
+ onChange(true /* selfChange */, NETWORK_RECOMMENDATIONS_ENABLED_URI);
+ }
+
+ public void unregister(ContentResolver cr) {
+ cr.unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ if (NETWORK_RECOMMENDATIONS_ENABLED_URI.equals(uri)) {
+ updateEnableUseWifiComponentName();
+ updateState(mPreference);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi;
+
+import static android.provider.Settings.Global.USE_OPEN_WIFI_PACKAGE;
+import static com.android.settings.wifi.UseOpenWifiPreferenceController.REQUEST_CODE_OPEN_WIFI_AUTOMATICALLY;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppData;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.network.NetworkScoreManagerWrapper;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class UseOpenWifiPreferenceControllerTest {
+ private static ComponentName ENABLE_ACTIVITY_COMPONENT = new ComponentName("package", "activityClass");
+ private static NetworkScorerAppData APP_DATA =
+ new NetworkScorerAppData(0, null, null, ENABLE_ACTIVITY_COMPONENT);
+ private static NetworkScorerAppData APP_DATA_NO_ACTIVITY =
+ new NetworkScorerAppData(0, null, null, null);
+
+ @Mock private Lifecycle mLifecycle;
+ @Mock private Fragment mFragment;
+ @Mock private NetworkScoreManagerWrapper mNetworkScoreManagerWrapper;
+ @Captor private ArgumentCaptor<Intent> mIntentCaptor;
+ private Context mContext;
+ private UseOpenWifiPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application;
+ }
+
+ private void createController() {
+ mController = new UseOpenWifiPreferenceController(
+ mContext, mFragment, mNetworkScoreManagerWrapper, mLifecycle);
+ }
+
+ @Test
+ public void testIsAvailable_noScorer() {
+ when(mNetworkScoreManagerWrapper.getActiveScorer()).thenReturn(null);
+
+ createController();
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void testIsAvailable_noEnableActivity() {
+ when(mNetworkScoreManagerWrapper.getActiveScorer()).thenReturn(APP_DATA_NO_ACTIVITY);
+
+ createController();
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void testIsAvailable_enableActivityExists() {
+ when(mNetworkScoreManagerWrapper.getActiveScorer()).thenReturn(APP_DATA);
+
+ createController();
+
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void onPreferenceChange_nonMatchingKey_shouldDoNothing() {
+ createController();
+
+ final SwitchPreference pref = new SwitchPreference(mContext);
+
+ assertThat(mController.onPreferenceChange(pref, null)).isFalse();
+ }
+
+ @Test
+ public void onPreferenceChange_notAvailable_shouldDoNothing() {
+ when(mNetworkScoreManagerWrapper.getActiveScorer()).thenReturn(APP_DATA_NO_ACTIVITY);
+
+ createController();
+
+ final Preference pref = new Preference(mContext);
+ pref.setKey(mController.getPreferenceKey());
+
+ assertThat(mController.onPreferenceChange(pref, null)).isFalse();
+ }
+
+ @Test
+ public void onPreferenceChange_matchingKeyAndAvailable_enableShouldStartEnableActivity() {
+ when(mNetworkScoreManagerWrapper.getActiveScorer()).thenReturn(APP_DATA);
+ createController();
+
+ final SwitchPreference pref = new SwitchPreference(mContext);
+ pref.setKey(mController.getPreferenceKey());
+
+ assertThat(mController.onPreferenceChange(pref, null)).isFalse();
+ verify(mFragment).startActivityForResult(mIntentCaptor.capture(),
+ eq(REQUEST_CODE_OPEN_WIFI_AUTOMATICALLY));
+ Intent activityIntent = mIntentCaptor.getValue();
+ assertThat(activityIntent.getComponent()).isEqualTo(ENABLE_ACTIVITY_COMPONENT);
+ assertThat(activityIntent.getAction()).isEqualTo(NetworkScoreManager.ACTION_CUSTOM_ENABLE);
+ }
+
+ @Test
+ public void onPreferenceChange_matchingKeyAndAvailable_disableShouldUpdateSetting() {
+ when(mNetworkScoreManagerWrapper.getActiveScorer()).thenReturn(APP_DATA);
+ Settings.Global.putString(mContext.getContentResolver(), USE_OPEN_WIFI_PACKAGE,
+ ENABLE_ACTIVITY_COMPONENT.getPackageName());
+
+ createController();
+
+ final SwitchPreference pref = new SwitchPreference(mContext);
+ pref.setKey(mController.getPreferenceKey());
+
+ assertThat(mController.onPreferenceChange(pref, null)).isTrue();
+ assertThat(Settings.Global.getString(mContext.getContentResolver(), USE_OPEN_WIFI_PACKAGE))
+ .isEqualTo("");
+ }
+
+ @Test
+ public void onActivityResult_nonmatchingRequestCode_shouldDoNothing() {
+ createController();
+
+ assertThat(mController.onActivityResult(234 /* requestCode */ , Activity.RESULT_OK))
+ .isEqualTo(false);
+ assertThat(Settings.Global.getString(mContext.getContentResolver(), USE_OPEN_WIFI_PACKAGE))
+ .isNull();
+ }
+
+ @Test
+ public void onActivityResult_matchingRequestCode_nonOkResult_shouldDoNothing() {
+ createController();
+
+ assertThat(mController
+ .onActivityResult(REQUEST_CODE_OPEN_WIFI_AUTOMATICALLY, Activity.RESULT_CANCELED))
+ .isEqualTo(true);
+ assertThat(Settings.Global.getString(mContext.getContentResolver(), USE_OPEN_WIFI_PACKAGE))
+ .isNull();
+ }
+
+ @Test
+ public void onActivityResult_matchingRequestCode_okResult_updatesSetting() {
+ when(mNetworkScoreManagerWrapper.getActiveScorer()).thenReturn(APP_DATA);
+ createController();
+
+ assertThat(mController
+ .onActivityResult(REQUEST_CODE_OPEN_WIFI_AUTOMATICALLY, Activity.RESULT_OK))
+ .isEqualTo(true);
+ assertThat(Settings.Global.getString(mContext.getContentResolver(), USE_OPEN_WIFI_PACKAGE))
+ .isEqualTo(ENABLE_ACTIVITY_COMPONENT.getPackageName());
+ }
+
+ @Test
+ public void updateState_preferenceSetCheckedAndSetVisibleWhenSettingsAreEnabled() {
+ when(mNetworkScoreManagerWrapper.getActiveScorer()).thenReturn(APP_DATA);
+ createController();
+
+ final SwitchPreference preference = mock(SwitchPreference.class);
+ Settings.Global.putString(mContext.getContentResolver(), USE_OPEN_WIFI_PACKAGE,
+ ENABLE_ACTIVITY_COMPONENT.getPackageName());
+
+ mController.updateState(preference);
+
+ verify(preference).setVisible(true);
+ verify(preference).setChecked(true);
+ }
+
+ @Test
+ public void updateState_preferenceSetCheckedAndSetVisibleWhenSettingsAreDisabled() {
+ final SwitchPreference preference = mock(SwitchPreference.class);
+ Settings.Global.putString(mContext.getContentResolver(), USE_OPEN_WIFI_PACKAGE, "");
+ createController();
+
+ mController.updateState(preference);
+
+ verify(preference).setVisible(false);
+ verify(preference).setChecked(false);
+ }
+}