Create NetworkProviderSettings for provider model

Provider model is a feature which improves networks
Settings UX.

NetworkProviderSettings is the fragment which allow
users to choose a mobile network or a Wi-Fi network
to connect.

At this change, NetworkProviderSettings is a clone
of WifiSettings, mobile networks will be integrated
at later CLs.

Bug: 167474581
Test: make RunSettingsRoboTests ROBOTEST_FILTER=com.android.settings.network.NetworkProviderSettingsTest
Change-Id: I185639a8f2469e9ec76ad18b6c2bc2e8a4d079e3
This commit is contained in:
Arc Wang
2020-09-02 17:35:56 +08:00
parent bcb6d4f444
commit 746176eb56
8 changed files with 1614 additions and 2 deletions

View File

@@ -279,6 +279,26 @@
android:value="true" />
</activity>
<activity
android:name="Settings$NetworkProviderSettingsActivity"
android:label="@string/network_dashboard_title"
android:icon="@drawable/ic_homepage_network"
android:exported="true"
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter android:priority="1">
<action android:name="android.settings.NETWORK_PROVIDER_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="1">
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.network.NetworkProviderSettings" />
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
<activity
android:name=".wifi.WifiPickerActivity"
android:exported="true">

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/network_dashboard_title"
settings:keywords="@string/keywords_wifi">
<com.android.settings.wifi.LinkablePreference
android:key="wifi_status_message"/>
<PreferenceCategory
android:key="connected_access_point"
android:layout="@layout/preference_category_no_label"/>
<PreferenceCategory
android:key="access_points"
android:layout="@layout/preference_category_no_label"/>
<Preference
android:key="configure_wifi_settings"
android:title="@string/wifi_configure_settings_preference_title"
settings:allowDividerAbove="true"
android:fragment="com.android.settings.wifi.ConfigureWifiSettings"/>
<Preference
android:key="saved_networks"
android:title="@string/wifi_saved_access_points_label"
android:fragment="com.android.settings.wifi.savedaccesspoints2.SavedAccessPointsWifiSettings2"/>
<com.android.settings.datausage.DataUsagePreference
android:key="wifi_data_usage"
android:title="@string/wifi_data_usage"/>
</PreferenceScreen>

View File

@@ -82,6 +82,7 @@ public class Settings extends SettingsActivity {
public static class PublicVolumeSettingsActivity extends SettingsActivity { /* empty */ }
public static class WifiSettingsActivity extends SettingsActivity { /* empty */ }
public static class WifiSettings2Activity extends SettingsActivity { /* empty */ }
public static class NetworkProviderSettingsActivity extends SettingsActivity { /* empty */ }
public static class WifiP2pSettingsActivity extends SettingsActivity { /* empty */ }
public static class AvailableVirtualKeyboardActivity extends SettingsActivity { /* empty */ }
public static class KeyboardLayoutPickerActivity extends SettingsActivity { /* empty */ }

View File

@@ -112,6 +112,7 @@ import com.android.settings.network.ApnEditor;
import com.android.settings.network.ApnSettings;
import com.android.settings.network.MobileNetworkListFragment;
import com.android.settings.network.NetworkDashboardFragment;
import com.android.settings.network.NetworkProviderSettings;
import com.android.settings.nfc.AndroidBeam;
import com.android.settings.nfc.PaymentSettings;
import com.android.settings.notification.ConfigureNotificationSettings;
@@ -303,7 +304,8 @@ public class SettingsGateway {
GestureNavigationSettingsFragment.class.getName(),
InteractAcrossProfilesSettings.class.getName(),
InteractAcrossProfilesDetails.class.getName(),
MediaControlsSettings.class.getName()
MediaControlsSettings.class.getName(),
NetworkProviderSettings.class.getName()
};
public static final String[] SETTINGS_FOR_RESTRICTED = {
@@ -324,6 +326,7 @@ public class SettingsGateway {
// Home page > Network & Internet
Settings.WifiSettingsActivity.class.getName(),
Settings.DataUsageSummaryActivity.class.getName(),
Settings.NetworkProviderSettingsActivity.class.getName(),
// Home page > Connected devices
Settings.BluetoothSettingsActivity.class.getName(),
Settings.WifiDisplaySettingsActivity.class.getName(),

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,7 @@ import com.android.settings.wifi.dpp.WifiDppUtils;
public class AddNetworkFragment extends InstrumentedFragment implements WifiConfigUiBase2,
View.OnClickListener {
final static String WIFI_CONFIG_KEY = "wifi_config_key";
public static final String WIFI_CONFIG_KEY = "wifi_config_key";
@VisibleForTesting
final static int SUBMIT_BUTTON_ID = android.R.id.button1;
@VisibleForTesting

View File

@@ -88,6 +88,9 @@ import java.util.Optional;
/**
* UI for Wi-Fi settings screen
*
* TODO(b/167474581): This file will be deprecated at Android S, please merge your WifiSettings
* in change in {@link NetworkProviderSettings}.
*/
@SearchIndexable
public class WifiSettings extends RestrictedSettingsFragment
@@ -228,6 +231,17 @@ public class WifiSettings extends RestrictedSettingsFragment
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlagUtils.SETTINGS_PROVIDER_MODEL)) {
final Intent intent = new Intent("android.settings.NETWORK_PROVIDER_SETTINGS");
final Bundle extras = getActivity().getIntent().getExtras();
if (extras != null) {
intent.putExtras(extras);
}
getContext().startActivity(intent);
finish();
return;
}
// TODO(b/37429702): Add animations and preference comparator back after initial screen is
// loaded (ODR).
setAnimationAllowed(false);

View File

@@ -0,0 +1,377 @@
/*
* Copyright (C) 2020 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.network;
import static com.android.settings.wifi.WifiConfigUiBase2.MODE_CONNECT;
import static com.android.settings.wifi.WifiConfigUiBase2.MODE_MODIFY;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.UserManager;
import android.provider.Settings;
import android.view.ContextMenu;
import android.view.View;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.R;
import com.android.settings.datausage.DataUsagePreference;
import com.android.settings.testutils.shadow.ShadowDataUsageUtils;
import com.android.settings.testutils.shadow.ShadowFragment;
import com.android.settings.wifi.AddWifiNetworkPreference;
import com.android.settings.wifi.WifiConfigController2;
import com.android.settings.wifi.WifiDialog2;
import com.android.settingslib.wifi.LongPressWifiEntryPreference;
import com.android.wifitrackerlib.WifiEntry;
import com.android.wifitrackerlib.WifiPickerTracker;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowToast;
@RunWith(RobolectricTestRunner.class)
public class NetworkProviderSettingsTest {
private static final int NUM_NETWORKS = 4;
private static final String FAKE_URI_STRING = "fakeuri";
@Mock
private PowerManager mPowerManager;
@Mock
private WifiManager mWifiManager;
@Mock
private DataUsagePreference mDataUsagePreference;
private Context mContext;
private NetworkProviderSettings mNetworkProviderSettings;
@Mock
private WifiPickerTracker mMockWifiPickerTracker;
@Mock
private PreferenceManager mPreferenceManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mNetworkProviderSettings = spy(new NetworkProviderSettings());
doReturn(mContext).when(mNetworkProviderSettings).getContext();
doReturn(mPreferenceManager).when(mNetworkProviderSettings).getPreferenceManager();
doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class);
doReturn(mContext).when(mPreferenceManager).getContext();
mNetworkProviderSettings.mAddWifiNetworkPreference = new AddWifiNetworkPreference(mContext);
mNetworkProviderSettings.mSavedNetworksPreference = new Preference(mContext);
mNetworkProviderSettings.mConfigureWifiSettingsPreference =
new Preference(mContext);
mNetworkProviderSettings.mWifiPickerTracker = mMockWifiPickerTracker;
mNetworkProviderSettings.mWifiManager = mWifiManager;
}
@Test
public void addNetworkFragmentSendResult_onActivityResult_shouldHandleEvent() {
final NetworkProviderSettings NetworkProviderSettings = spy(new NetworkProviderSettings());
final Intent intent = new Intent();
doNothing().when(NetworkProviderSettings).handleAddNetworkRequest(anyInt(),
any(Intent.class));
NetworkProviderSettings.onActivityResult(NetworkProviderSettings.ADD_NETWORK_REQUEST,
Activity.RESULT_OK, intent);
verify(NetworkProviderSettings).handleAddNetworkRequest(anyInt(), any(Intent.class));
}
@Test
public void setAdditionalSettingsSummaries_hasSavedNetwork_preferenceVisible() {
when(mMockWifiPickerTracker.getNumSavedNetworks()).thenReturn(NUM_NETWORKS);
when(mMockWifiPickerTracker.getNumSavedSubscriptions()).thenReturn(0 /* count */);
mNetworkProviderSettings.setAdditionalSettingsSummaries();
assertThat(mNetworkProviderSettings.mSavedNetworksPreference.isVisible()).isTrue();
assertThat(mNetworkProviderSettings.mSavedNetworksPreference.getSummary()).isEqualTo(
mContext.getResources().getQuantityString(
R.plurals.wifi_saved_access_points_summary,
NUM_NETWORKS, NUM_NETWORKS));
}
@Test
public void setAdditionalSettingsSummaries_hasSavedPasspointNetwork_preferenceVisible() {
when(mMockWifiPickerTracker.getNumSavedNetworks()).thenReturn(0 /* count */);
when(mMockWifiPickerTracker.getNumSavedSubscriptions()).thenReturn(NUM_NETWORKS);
mNetworkProviderSettings.setAdditionalSettingsSummaries();
assertThat(mNetworkProviderSettings.mSavedNetworksPreference.isVisible()).isTrue();
assertThat(mNetworkProviderSettings.mSavedNetworksPreference.getSummary()).isEqualTo(
mContext.getResources().getQuantityString(
R.plurals.wifi_saved_passpoint_access_points_summary,
NUM_NETWORKS, NUM_NETWORKS));
}
@Test
public void setAdditionalSettingsSummaries_hasTwoKindsSavedNetwork_preferenceVisible() {
when(mMockWifiPickerTracker.getNumSavedNetworks()).thenReturn(NUM_NETWORKS);
when(mMockWifiPickerTracker.getNumSavedSubscriptions()).thenReturn(NUM_NETWORKS);
mNetworkProviderSettings.setAdditionalSettingsSummaries();
assertThat(mNetworkProviderSettings.mSavedNetworksPreference.isVisible()).isTrue();
assertThat(mNetworkProviderSettings.mSavedNetworksPreference.getSummary()).isEqualTo(
mContext.getResources().getQuantityString(
R.plurals.wifi_saved_all_access_points_summary,
NUM_NETWORKS * 2, NUM_NETWORKS * 2));
}
@Test
public void setAdditionalSettingsSummaries_noSavedNetwork_preferenceInvisible() {
when(mMockWifiPickerTracker.getNumSavedNetworks()).thenReturn(0 /* count */);
when(mMockWifiPickerTracker.getNumSavedSubscriptions()).thenReturn(0 /* count */);
mNetworkProviderSettings.setAdditionalSettingsSummaries();
assertThat(mNetworkProviderSettings.mSavedNetworksPreference.isVisible()).isFalse();
}
@Test
public void setAdditionalSettingsSummaries_wifiWakeupEnabled_displayOn() {
final ContentResolver contentResolver = mContext.getContentResolver();
when(mWifiManager.isAutoWakeupEnabled()).thenReturn(true);
when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0);
when(mPowerManager.isPowerSaveMode()).thenReturn(false);
mNetworkProviderSettings.setAdditionalSettingsSummaries();
assertThat(mNetworkProviderSettings
.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_on));
}
@Test
public void setAdditionalSettingsSummaries_wifiWakeupDisabled_displayOff() {
final ContentResolver contentResolver = mContext.getContentResolver();
when(mWifiManager.isAutoWakeupEnabled()).thenReturn(false);
mNetworkProviderSettings.setAdditionalSettingsSummaries();
assertThat(mNetworkProviderSettings
.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_off));
}
@Test
public void checkAddWifiNetworkPreference_preferenceVisible() {
assertThat(mNetworkProviderSettings.mAddWifiNetworkPreference.isVisible()).isTrue();
assertThat(mNetworkProviderSettings.mAddWifiNetworkPreference.getTitle()).isEqualTo(
mContext.getString(R.string.wifi_add_network));
}
private void setUpForOnCreate() {
final FragmentActivity activity = mock(FragmentActivity.class);
when(mNetworkProviderSettings.getActivity()).thenReturn(activity);
final Resources.Theme theme = mContext.getTheme();
when(activity.getTheme()).thenReturn(theme);
UserManager userManager = mock(UserManager.class);
when(activity.getSystemService(Context.USER_SERVICE))
.thenReturn(userManager);
when(mNetworkProviderSettings.findPreference(NetworkProviderSettings.PREF_KEY_DATA_USAGE))
.thenReturn(mDataUsagePreference);
}
@Test
@Config(shadows = {ShadowDataUsageUtils.class, ShadowFragment.class})
public void checkDataUsagePreference_perferenceInvisibleIfWifiNotSupported() {
setUpForOnCreate();
ShadowDataUsageUtils.IS_WIFI_SUPPORTED = false;
mNetworkProviderSettings.onCreate(Bundle.EMPTY);
verify(mDataUsagePreference).setVisible(false);
}
@Test
@Config(shadows = {ShadowDataUsageUtils.class, ShadowFragment.class})
public void checkDataUsagePreference_perferenceVisibleIfWifiSupported() {
setUpForOnCreate();
ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
mNetworkProviderSettings.onCreate(Bundle.EMPTY);
verify(mDataUsagePreference).setVisible(true);
verify(mDataUsagePreference).setTemplate(any(), eq(0) /*subId*/, eq(null) /*service*/);
}
@Test
public void onCreateAdapter_hasStableIdsTrue() {
final PreferenceScreen preferenceScreen = mock(PreferenceScreen.class);
when(preferenceScreen.getContext()).thenReturn(mContext);
RecyclerView.Adapter adapter = mNetworkProviderSettings.onCreateAdapter(preferenceScreen);
assertThat(adapter.hasStableIds()).isTrue();
}
@Test
public void onCreateContextMenu_shouldHaveForgetAndDisconnectMenuForConnectedWifiEntry() {
final FragmentActivity activity = mock(FragmentActivity.class);
when(activity.getApplicationContext()).thenReturn(mContext);
when(mNetworkProviderSettings.getActivity()).thenReturn(activity);
final WifiEntry wifiEntry = mock(WifiEntry.class);
when(wifiEntry.canDisconnect()).thenReturn(true);
when(wifiEntry.canForget()).thenReturn(true);
when(wifiEntry.isSaved()).thenReturn(true);
when(wifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
final LongPressWifiEntryPreference connectedWifiEntryPreference =
mNetworkProviderSettings.createLongPressWifiEntryPreference(wifiEntry);
final View view = mock(View.class);
when(view.getTag()).thenReturn(connectedWifiEntryPreference);
final ContextMenu menu = mock(ContextMenu.class);
mNetworkProviderSettings.onCreateContextMenu(menu, view, null /* info */);
verify(menu).add(anyInt(), eq(NetworkProviderSettings.MENU_ID_FORGET), anyInt(), anyInt());
verify(menu).add(anyInt(), eq(NetworkProviderSettings.MENU_ID_DISCONNECT), anyInt(),
anyInt());
}
@Test
public void onWifiEntriesChanged_shouldChangeNextButtonState() {
mNetworkProviderSettings.onWifiEntriesChanged();
verify(mNetworkProviderSettings).changeNextButtonState(anyBoolean());
}
@Test
public void openSubscriptionHelpPage_shouldCallStartActivityForResult() {
doReturn(new Intent()).when(mNetworkProviderSettings).getHelpIntent(mContext,
FAKE_URI_STRING);
doNothing().when(mNetworkProviderSettings).startActivityForResult(any(Intent.class),
anyInt());
final WifiEntry mockWifiEntry = mock(WifiEntry.class);
when(mockWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING);
mNetworkProviderSettings.openSubscriptionHelpPage(mockWifiEntry);
verify(mNetworkProviderSettings, times(1)).startActivityForResult(any(), anyInt());
}
@Test
public void onNumSavedNetworksChanged_isFinishing_ShouldNotCrash() {
final FragmentActivity activity = mock(FragmentActivity.class);
when(activity.isFinishing()).thenReturn(true);
when(mNetworkProviderSettings.getActivity()).thenReturn(activity);
when(mNetworkProviderSettings.getContext()).thenReturn(null);
mNetworkProviderSettings.onNumSavedNetworksChanged();
}
@Test
public void onNumSavedSubscriptionsChanged_isFinishing_ShouldNotCrash() {
final FragmentActivity activity = mock(FragmentActivity.class);
when(activity.isFinishing()).thenReturn(true);
when(mNetworkProviderSettings.getActivity()).thenReturn(activity);
when(mNetworkProviderSettings.getContext()).thenReturn(null);
mNetworkProviderSettings.onNumSavedSubscriptionsChanged();
}
@Test
public void onSubmit_modeModifyNoConfig_toastErrorMessage() {
WifiDialog2 dialog = createWifiDialog2(MODE_MODIFY, null /* config */);
mNetworkProviderSettings.onSubmit(dialog);
assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
mContext.getString(R.string.wifi_failed_save_message));
}
@Test
public void onSubmit_modeModifyHasConfig_saveWifiManager() {
final WifiConfiguration config = mock(WifiConfiguration.class);
WifiDialog2 dialog = createWifiDialog2(MODE_MODIFY, config);
mNetworkProviderSettings.onSubmit(dialog);
verify(mWifiManager).save(eq(config), any());
}
@Test
public void onSubmit_modeConnectNoConfig_connectWifiEntry() {
WifiDialog2 dialog = createWifiDialog2(MODE_CONNECT, null /* config */);
final WifiEntry wifiEntry = dialog.getWifiEntry();
mNetworkProviderSettings.onAttach(mContext);
mNetworkProviderSettings.onSubmit(dialog);
verify(mNetworkProviderSettings).connect(wifiEntry, false /* editIfNoConfig */,
false /* fullScreenEdit*/);
}
@Test
public void onSubmit_modeConnectHasConfig_connectWifiManager() {
final WifiConfiguration config = mock(WifiConfiguration.class);
WifiDialog2 dialog = createWifiDialog2(MODE_CONNECT, config);
mNetworkProviderSettings.onSubmit(dialog);
verify(mWifiManager).connect(eq(config), any(WifiManager.ActionListener.class));
}
private WifiDialog2 createWifiDialog2(int mode, WifiConfiguration config) {
final WifiEntry wifiEntry = mock(WifiEntry.class);
when(wifiEntry.canConnect()).thenReturn(true);
final WifiConfigController2 controller = mock(WifiConfigController2.class);
when(controller.getConfig()).thenReturn(config);
final WifiDialog2 wifiDialog2 = spy(WifiDialog2.createModal(mContext, null /* listener */,
wifiEntry, mode));
when(wifiDialog2.getController()).thenReturn(controller);
return wifiDialog2;
}
}