From b061428938c512278259a4687ed25a51a5015cad Mon Sep 17 00:00:00 2001 From: Quang Luong Date: Thu, 25 Jul 2019 11:29:42 -0700 Subject: [PATCH] Copy WifiSettings base code into WifiSettings2 without WifiTracker Copied main logic from WifiSettings into WifiSettings2, removing all instances of WifiTracker in preparation of adding WifiTracker2. Removed: - WifiDialog (to be added back in) - Context Menu (to be added back in) - Leftover SUW code (Next button) WifiSettings2Test also copied directly from WifiSettingsTest, without context menu test. Bug: 70983952 Test: atest WifiSettings2Test Change-Id: Ie1ef5bf0ca14f5989f4add2165422609f12c2c84 --- .../android/settings/wifi/WifiSettings2.java | 612 +++++++++++++++++- .../settings/wifi/WifiSettings2Test.java | 291 +++++++++ 2 files changed, 902 insertions(+), 1 deletion(-) create mode 100644 tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java diff --git a/src/com/android/settings/wifi/WifiSettings2.java b/src/com/android/settings/wifi/WifiSettings2.java index 713679e7da1..a86d39a9442 100644 --- a/src/com/android/settings/wifi/WifiSettings2.java +++ b/src/com/android/settings/wifi/WifiSettings2.java @@ -18,18 +18,628 @@ package com.android.settings.wifi; import static android.os.UserManager.DISALLOW_CONFIG_WIFI; +import android.app.Activity; import android.app.settings.SettingsEnums; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.net.NetworkTemplate; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.PowerManager; +import android.provider.Settings; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.MenuItem; +import android.view.View; +import android.widget.Toast; +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.PreferenceCategory; + +import com.android.settings.LinkifyUtils; +import com.android.settings.R; import com.android.settings.RestrictedSettingsFragment; +import com.android.settings.SettingsActivity; +import com.android.settings.core.SubSettingLauncher; +import com.android.settings.dashboard.SummaryLoader; +import com.android.settings.datausage.DataUsageUtils; +import com.android.settings.datausage.DataUsagePreference; +import com.android.settings.location.ScanningSettings; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.search.Indexable; +import com.android.settings.search.SearchIndexableRaw; +import com.android.settings.widget.SummaryUpdater.OnSummaryChangeListener; +import com.android.settings.widget.SwitchBarController; +import com.android.settingslib.search.SearchIndexable; +import com.android.settingslib.wifi.AccessPoint; +import com.android.settingslib.wifi.WifiSavedConfigUtils; -public class WifiSettings2 extends RestrictedSettingsFragment { +import java.util.ArrayList; +import java.util.List; + +/** + * Two types of UI are provided here. + * + * The first is for "usual Settings", appearing as any other Setup fragment. + * + * The second is for Setup Wizard, with a simplified interface that hides the action bar + * and menus. + */ +@SearchIndexable +public class WifiSettings2 extends RestrictedSettingsFragment + implements Indexable { + + private static final String TAG = "WifiSettings2"; + + @VisibleForTesting + static final int ADD_NETWORK_REQUEST = 2; + + private static final String PREF_KEY_EMPTY_WIFI_LIST = "wifi_empty_list"; + // TODO(b/70983952): Rename these to use WifiEntry instead of AccessPoint. + private static final String PREF_KEY_CONNECTED_ACCESS_POINTS = "connected_access_point"; + private static final String PREF_KEY_ACCESS_POINTS = "access_points"; + private static final String PREF_KEY_CONFIGURE_WIFI_SETTINGS = "configure_settings"; + private static final String PREF_KEY_SAVED_NETWORKS = "saved_networks"; + private static final String PREF_KEY_STATUS_MESSAGE = "wifi_status_message"; + @VisibleForTesting + static final String PREF_KEY_DATA_USAGE = "wifi_data_usage"; + + private static final int REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER = 0; + + private final Runnable mUpdateWifiEntryPreferencesRunnable = () -> { + updateWifiEntryPreferences(); + }; + private final Runnable mHideProgressBarRunnable = () -> { + setProgressBarVisible(false); + }; + + protected WifiManager mWifiManager; + private WifiManager.ActionListener mConnectListener; + private WifiManager.ActionListener mSaveListener; + private WifiManager.ActionListener mForgetListener; + + /** + * The state of {@link #isUiRestricted()} at {@link #onCreate(Bundle)}}. This is neccesary to + * ensure that behavior is consistent if {@link #isUiRestricted()} changes. It could be changed + * by the Test DPC tool in AFW mode. + */ + private boolean mIsRestricted; + + private WifiEnabler mWifiEnabler; + + private WifiDialog mDialog; + + private View mProgressHeader; + + private PreferenceCategory mConnectedWifiEntryPreferenceCategory; + private PreferenceCategory mWifiEntryPreferenceCategory; + @VisibleForTesting + AddWifiNetworkPreference mAddWifiNetworkPreference; + @VisibleForTesting + Preference mConfigureWifiSettingsPreference; + @VisibleForTesting + Preference mSavedNetworksPreference; + @VisibleForTesting + DataUsagePreference mDataUsagePreference; + private LinkablePreference mStatusMessagePreference; + + // For Search + public static final String DATA_KEY_REFERENCE = "main_toggle_wifi"; + + /** + * Tracks whether the user initiated a connection via clicking in order to autoscroll to the + * network once connected. + */ + private boolean mClickedConnect; + + /* End of "used in Wifi Setup context" */ public WifiSettings2() { super(DISALLOW_CONFIG_WIFI); } + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + final Activity activity = getActivity(); + if (activity != null) { + mProgressHeader = setPinnedHeaderView(R.layout.progress_header) + .findViewById(R.id.progress_bar_animation); + setProgressBarVisible(false); + } + ((SettingsActivity) activity).getSwitchBar().setSwitchBarText( + R.string.wifi_settings_master_switch_title, + R.string.wifi_settings_master_switch_title); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + // TODO(b/37429702): Add animations and preference comparator back after initial screen is + // loaded (ODR). + setAnimationAllowed(false); + + addPreferences(); + + mIsRestricted = isUiRestricted(); + } + + private void addPreferences() { + addPreferencesFromResource(R.xml.wifi_settings); + + mConnectedWifiEntryPreferenceCategory = findPreference(PREF_KEY_CONNECTED_ACCESS_POINTS); + mWifiEntryPreferenceCategory = findPreference(PREF_KEY_ACCESS_POINTS); + mConfigureWifiSettingsPreference = findPreference(PREF_KEY_CONFIGURE_WIFI_SETTINGS); + mSavedNetworksPreference = findPreference(PREF_KEY_SAVED_NETWORKS); + mAddWifiNetworkPreference = new AddWifiNetworkPreference(getPrefContext()); + mStatusMessagePreference = findPreference(PREF_KEY_STATUS_MESSAGE); + mDataUsagePreference = findPreference(PREF_KEY_DATA_USAGE); + mDataUsagePreference.setVisible(DataUsageUtils.hasWifiRadio(getContext())); + mDataUsagePreference.setTemplate(NetworkTemplate.buildTemplateWifiWildcard(), + 0 /*subId*/, + null /*service*/); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + final Activity activity = getActivity(); + if (activity != null) { + mWifiManager = getActivity().getSystemService(WifiManager.class); + } + + mConnectListener = new WifiConnectListener(getActivity()); + + mSaveListener = new WifiManager.ActionListener() { + @Override + public void onSuccess() { + } + + @Override + public void onFailure(int reason) { + Activity activity = getActivity(); + if (activity != null) { + Toast.makeText(activity, + R.string.wifi_failed_save_message, + Toast.LENGTH_SHORT).show(); + } + } + }; + + mForgetListener = new WifiManager.ActionListener() { + @Override + public void onSuccess() { + } + + @Override + public void onFailure(int reason) { + Activity activity = getActivity(); + if (activity != null) { + Toast.makeText(activity, + R.string.wifi_failed_forget_message, + Toast.LENGTH_SHORT).show(); + } + } + }; + registerForContextMenu(getListView()); + setHasOptionsMenu(true); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + + if (mWifiEnabler != null) { + mWifiEnabler.teardownSwitchController(); + } + } + + @Override + public void onStart() { + super.onStart(); + + // On/off switch is hidden for Setup Wizard (returns null) + mWifiEnabler = createWifiEnabler(); + + if (mIsRestricted) { + restrictUi(); + return; + } + + onWifiStateChanged(mWifiManager.getWifiState()); + } + + private void restrictUi() { + if (!isUiRestrictedByOnlyAdmin()) { + getEmptyTextView().setText(R.string.wifi_empty_list_user_restricted); + } + getPreferenceScreen().removeAll(); + } + + /** + * @return new WifiEnabler or null (as overridden by WifiSettingsForSetupWizard) + */ + private WifiEnabler createWifiEnabler() { + final SettingsActivity activity = (SettingsActivity) getActivity(); + return new WifiEnabler(activity, new SwitchBarController(activity.getSwitchBar()), + mMetricsFeatureProvider); + } + + @Override + public void onResume() { + final Activity activity = getActivity(); + super.onResume(); + + // Because RestrictedSettingsFragment's onResume potentially requests authorization, + // which changes the restriction state, recalculate it. + final boolean alreadyImmutablyRestricted = mIsRestricted; + mIsRestricted = isUiRestricted(); + if (!alreadyImmutablyRestricted && mIsRestricted) { + restrictUi(); + } + + if (mWifiEnabler != null) { + mWifiEnabler.resume(activity); + } + } + + @Override + public void onPause() { + super.onPause(); + if (mWifiEnabler != null) { + mWifiEnabler.pause(); + } + } + + @Override + public void onStop() { + getView().removeCallbacks(mUpdateWifiEntryPreferencesRunnable); + getView().removeCallbacks(mHideProgressBarRunnable); + super.onStop(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == ADD_NETWORK_REQUEST) { + handleAddNetworkRequest(resultCode, data); + return; + } else if (requestCode == REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER) { + if (resultCode == Activity.RESULT_OK) { + if (mDialog != null) { + mDialog.dismiss(); + } + } + return; + } + + final boolean formerlyRestricted = mIsRestricted; + mIsRestricted = isUiRestricted(); + if (formerlyRestricted && !mIsRestricted + && getPreferenceScreen().getPreferenceCount() == 0) { + // De-restrict the ui + addPreferences(); + } + } + @Override public int getMetricsCategory() { return SettingsEnums.WIFI; } + + @Override + public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) { + // TODO(b/70983952): Add context menu options here. This should be driven by the appropriate + // "can do action" APIs from WifiEntry. + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + // TODO(b/70983952): Add context menu selection logic here. This should simply call the + // appropriate WifiEntry action APIs (connect, forget, disconnect, etc). + return false; + } + + @Override + public boolean onPreferenceTreeClick(Preference preference) { + // If the preference has a fragment set, open that + if (preference.getFragment() != null) { + preference.setOnPreferenceClickListener(null); + return super.onPreferenceTreeClick(preference); + } + + // TODO(b/70983952) Add WifiEntry click logic. This should be as simple as calling + // WifiEntry.connect(). + + if (preference == mAddWifiNetworkPreference) { + onAddNetworkPressed(); + } else { + return super.onPreferenceTreeClick(preference); + } + return true; + } + + /** + * Updates WifiEntries from {@link WifiManager#getScanResults()}. Adds a delay to have + * progress bar displayed before starting to modify entries. + */ + private void updateWifiEntryPreferencesDelayed(long delayMillis) { + // Safeguard from some delayed event handling + if (getActivity() != null && !mIsRestricted && mWifiManager.isWifiEnabled()) { + final View view = getView(); + final Handler handler = view.getHandler(); + if (handler != null && handler.hasCallbacks(mUpdateWifiEntryPreferencesRunnable)) { + return; + } + setProgressBarVisible(true); + view.postDelayed(mUpdateWifiEntryPreferencesRunnable, delayMillis); + } + } + + /** Called when the state of Wifi has changed. */ + // TODO(b/70983952): Drive this using WifiTracker2 wifi state callback. + public void onWifiStateChanged(int state) { + if (mIsRestricted) { + return; + } + + final int wifiState = mWifiManager.getWifiState(); + switch (wifiState) { + case WifiManager.WIFI_STATE_ENABLED: + updateWifiEntryPreferences(); + break; + + case WifiManager.WIFI_STATE_ENABLING: + removeConnectedWifiEntryPreference(); + removeWifiEntryPreference(); + addMessagePreference(R.string.wifi_starting); + setProgressBarVisible(true); + break; + + case WifiManager.WIFI_STATE_DISABLING: + removeConnectedWifiEntryPreference(); + removeWifiEntryPreference(); + addMessagePreference(R.string.wifi_stopping); + break; + + case WifiManager.WIFI_STATE_DISABLED: + setOffMessage(); + setAdditionalSettingsSummaries(); + setProgressBarVisible(false); + break; + } + } + + private void updateWifiEntryPreferences() { + // in case state has changed + if (!mWifiManager.isWifiEnabled()) { + return; + } + + boolean hasAvailableWifiEntries = false; + mStatusMessagePreference.setVisible(false); + mConnectedWifiEntryPreferenceCategory.setVisible(true); + mWifiEntryPreferenceCategory.setVisible(true); + + int index = 0; + cacheRemoveAllPrefs(mWifiEntryPreferenceCategory); + // TODO(b/70983952) Add WifiEntryPreference update logic here. + removeCachedPrefs(mWifiEntryPreferenceCategory); + + mAddWifiNetworkPreference.setOrder(index); + mWifiEntryPreferenceCategory.addPreference(mAddWifiNetworkPreference); + setAdditionalSettingsSummaries(); + + if (!hasAvailableWifiEntries) { + setProgressBarVisible(true); + Preference pref = new Preference(getPrefContext()); + pref.setSelectable(false); + pref.setSummary(R.string.wifi_empty_list_wifi_on); + pref.setOrder(index++); + pref.setKey(PREF_KEY_EMPTY_WIFI_LIST); + mWifiEntryPreferenceCategory.addPreference(pref); + } else { + // Continuing showing progress bar for an additional delay to overlap with animation + getView().postDelayed(mHideProgressBarRunnable, 1700 /* delay millis */); + } + } + + private void launchAddNetworkFragment() { + new SubSettingLauncher(getContext()) + .setTitleRes(R.string.wifi_add_network) + .setDestination(AddNetworkFragment.class.getName()) + .setSourceMetricsCategory(getMetricsCategory()) + .setResultListener(this, ADD_NETWORK_REQUEST) + .launch(); + } + + /** Removes all preferences and hide the {@link #mConnectedWifiEntryPreferenceCategory}. */ + private void removeConnectedWifiEntryPreference() { + mConnectedWifiEntryPreferenceCategory.removeAll(); + mConnectedWifiEntryPreferenceCategory.setVisible(false); + } + + private void removeWifiEntryPreference() { + mWifiEntryPreferenceCategory.removeAll(); + mWifiEntryPreferenceCategory.setVisible(false); + } + + @VisibleForTesting + void setAdditionalSettingsSummaries() { + mConfigureWifiSettingsPreference.setSummary(getString( + isWifiWakeupEnabled() + ? R.string.wifi_configure_settings_preference_summary_wakeup_on + : R.string.wifi_configure_settings_preference_summary_wakeup_off)); + + final List savedNetworks = + WifiSavedConfigUtils.getAllConfigs(getContext(), mWifiManager); + final int numSavedNetworks = (savedNetworks != null) ? savedNetworks.size() : 0; + mSavedNetworksPreference.setVisible(numSavedNetworks > 0); + if (numSavedNetworks > 0) { + mSavedNetworksPreference.setSummary( + getSavedNetworkSettingsSummaryText(savedNetworks, numSavedNetworks)); + } + } + + private String getSavedNetworkSettingsSummaryText( + List savedNetworks, int numSavedNetworks) { + int numSavedPasspointNetworks = 0; + for (AccessPoint savedNetwork : savedNetworks) { + if (savedNetwork.isPasspointConfig() || savedNetwork.isPasspoint()) { + numSavedPasspointNetworks++; + } + } + final int numSavedNormalNetworks = numSavedNetworks - numSavedPasspointNetworks; + + if (numSavedNetworks == numSavedNormalNetworks) { + return getResources().getQuantityString(R.plurals.wifi_saved_access_points_summary, + numSavedNormalNetworks, numSavedNormalNetworks); + } else if (numSavedNetworks == numSavedPasspointNetworks) { + return getResources().getQuantityString( + R.plurals.wifi_saved_passpoint_access_points_summary, + numSavedPasspointNetworks, numSavedPasspointNetworks); + } else { + return getResources().getQuantityString(R.plurals.wifi_saved_all_access_points_summary, + numSavedNetworks, numSavedNetworks); + } + } + + private boolean isWifiWakeupEnabled() { + final Context context = getContext(); + final PowerManager powerManager = context.getSystemService(PowerManager.class); + final ContentResolver contentResolver = context.getContentResolver(); + return Settings.Global.getInt(contentResolver, + Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1 + && Settings.Global.getInt(contentResolver, + Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1 + && Settings.Global.getInt(contentResolver, + Settings.Global.AIRPLANE_MODE_ON, 0) == 0 + && !powerManager.isPowerSaveMode(); + } + + private void setOffMessage() { + final CharSequence title = getText(R.string.wifi_empty_list_wifi_off); + // Don't use WifiManager.isScanAlwaysAvailable() to check the Wi-Fi scanning mode. Instead, + // read the system settings directly. Because when the device is in Airplane mode, even if + // Wi-Fi scanning mode is on, WifiManager.isScanAlwaysAvailable() still returns "off". + final boolean wifiScanningMode = Settings.Global.getInt(getActivity().getContentResolver(), + Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1; + final CharSequence description = wifiScanningMode ? getText(R.string.wifi_scan_notify_text) + : getText(R.string.wifi_scan_notify_text_scanning_off); + final LinkifyUtils.OnClickListener clickListener = + () -> new SubSettingLauncher(getContext()) + .setDestination(ScanningSettings.class.getName()) + .setTitleRes(R.string.location_scanning_screen_title) + .setSourceMetricsCategory(getMetricsCategory()) + .launch(); + mStatusMessagePreference.setText(title, description, clickListener); + removeConnectedWifiEntryPreference(); + removeWifiEntryPreference(); + mStatusMessagePreference.setVisible(true); + } + + private void addMessagePreference(int messageId) { + mStatusMessagePreference.setTitle(messageId); + mStatusMessagePreference.setVisible(true); + + } + + protected void setProgressBarVisible(boolean visible) { + if (mProgressHeader != null) { + mProgressHeader.setVisibility(visible ? View.VISIBLE : View.GONE); + } + } + + @VisibleForTesting + void handleAddNetworkRequest(int result, Intent data) { + if (result == Activity.RESULT_OK) { + handleAddNetworkSubmitEvent(data); + } + } + + private void handleAddNetworkSubmitEvent(Intent data) { + final WifiConfiguration wifiConfiguration = data.getParcelableExtra( + AddNetworkFragment.WIFI_CONFIG_KEY); + if (wifiConfiguration != null) { + mWifiManager.save(wifiConfiguration, mSaveListener); + } + } + + /** + * Called when "add network" button is pressed. + */ + private void onAddNetworkPressed() { + launchAddNetworkFragment(); + } + + @Override + public int getHelpResource() { + return R.string.help_url_wifi; + } + + public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List getRawDataToIndex(Context context, + boolean enabled) { + final List result = new ArrayList<>(); + final Resources res = context.getResources(); + + // Add fragment title if we are showing this fragment + if (res.getBoolean(R.bool.config_show_wifi_settings)) { + SearchIndexableRaw data = new SearchIndexableRaw(context); + data.title = res.getString(R.string.wifi_settings); + data.screenTitle = res.getString(R.string.wifi_settings); + data.keywords = res.getString(R.string.keywords_wifi); + data.key = DATA_KEY_REFERENCE; + result.add(data); + } + + return result; + } + }; + + private static class SummaryProvider + implements SummaryLoader.SummaryProvider, OnSummaryChangeListener { + + private final Context mContext; + private final SummaryLoader mSummaryLoader; + + @VisibleForTesting + WifiSummaryUpdater mSummaryHelper; + + public SummaryProvider(Context context, SummaryLoader summaryLoader) { + mContext = context; + mSummaryLoader = summaryLoader; + mSummaryHelper = new WifiSummaryUpdater(mContext, this); + } + + + @Override + public void setListening(boolean listening) { + mSummaryHelper.register(listening); + } + + @Override + public void onSummaryChanged(String summary) { + mSummaryLoader.setSummary(this, summary); + } + } + + public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY + = new SummaryLoader.SummaryProviderFactory() { + @Override + public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, + SummaryLoader summaryLoader) { + return new SummaryProvider(activity, summaryLoader); + } + }; } diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java b/tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java new file mode 100644 index 00000000000..7ce05e137ed --- /dev/null +++ b/tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2019 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 com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +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.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.net.wifi.hotspot2.PasspointConfiguration; +import android.net.wifi.hotspot2.pps.HomeSp; +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 com.android.settings.R; +import com.android.settings.datausage.DataUsagePreference; +import com.android.settings.search.SearchIndexableRaw; +import com.android.settings.testutils.shadow.ShadowDataUsageUtils; +import com.android.settings.testutils.shadow.ShadowFragment; +import com.android.settingslib.wifi.AccessPoint; + +import java.util.ArrayList; +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 java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class WifiSettings2Test { + + private static final int NUM_NETWORKS = 4; + + @Mock + private PowerManager mPowerManager; + @Mock + private DataUsagePreference mDataUsagePreference; + @Mock + private WifiManager mWifiManager; + private Context mContext; + private WifiSettings2 mWifiSettings2; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + + mWifiSettings2 = spy(new WifiSettings2()); + doReturn(mContext).when(mWifiSettings2).getContext(); + doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class); + mWifiSettings2.mAddWifiNetworkPreference = new AddWifiNetworkPreference(mContext); + mWifiSettings2.mSavedNetworksPreference = new Preference(mContext); + mWifiSettings2.mConfigureWifiSettingsPreference = new Preference(mContext); + mWifiSettings2.mWifiManager = mWifiManager; + } + + @Test + public void testSearchIndexProvider_shouldIndexFragmentTitle() { + final List indexRes = + WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, + true /* enabled */); + + assertThat(indexRes).isNotNull(); + assertThat(indexRes.get(0).key).isEqualTo(WifiSettings.DATA_KEY_REFERENCE); + } + + @Test + @Config(qualifiers = "mcc999") + public void testSearchIndexProvider_ifWifiSettingsNotVisible_shouldNotIndexFragmentTitle() { + final List indexRes = + WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, + true /* enabled */); + + assertThat(indexRes).isEmpty(); + } + + @Test + public void addNetworkFragmentSendResult_onActivityResult_shouldHandleEvent() { + final WifiSettings wifiSettings = spy(new WifiSettings()); + final Intent intent = new Intent(); + doNothing().when(wifiSettings).handleAddNetworkRequest(anyInt(), any(Intent.class)); + + wifiSettings.onActivityResult(WifiSettings.ADD_NETWORK_REQUEST, Activity.RESULT_OK, intent); + + verify(wifiSettings).handleAddNetworkRequest(anyInt(), any(Intent.class)); + } + + private List createMockWifiConfigurations(int count) { + final List mockConfigs = new ArrayList<>(); + for (int i = 0; i < count; i++) { + mockConfigs.add(new WifiConfiguration()); + } + return mockConfigs; + } + + private List createMockPasspointConfigurations(int count) { + final List mockConfigs = new ArrayList<>(); + for (int i = 0; i < count; i++) { + final HomeSp sp = new HomeSp(); + sp.setFqdn("fqdn"); + final PasspointConfiguration config = new PasspointConfiguration(); + config.setHomeSp(sp); + mockConfigs.add(config); + } + return mockConfigs; + } + + @Test + public void setAdditionalSettingsSummaries_hasSavedNetwork_preferenceVisible() { + when(mWifiManager.getConfiguredNetworks()) + .thenReturn(createMockWifiConfigurations(NUM_NETWORKS)); + + mWifiSettings2.setAdditionalSettingsSummaries(); + + assertThat(mWifiSettings2.mSavedNetworksPreference.isVisible()).isTrue(); + assertThat(mWifiSettings2.mSavedNetworksPreference.getSummary()).isEqualTo( + mContext.getResources().getQuantityString( + R.plurals.wifi_saved_access_points_summary, + NUM_NETWORKS, NUM_NETWORKS)); + } + + @Test + public void setAdditionalSettingsSummaries_hasSavedPasspointNetwork_preferenceVisible() { + when(mWifiManager.getPasspointConfigurations()) + .thenReturn(createMockPasspointConfigurations(NUM_NETWORKS)); + + mWifiSettings2.setAdditionalSettingsSummaries(); + + assertThat(mWifiSettings2.mSavedNetworksPreference.isVisible()).isTrue(); + assertThat(mWifiSettings2.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(mWifiManager.getConfiguredNetworks()) + .thenReturn(createMockWifiConfigurations(NUM_NETWORKS)); + when(mWifiManager.getPasspointConfigurations()) + .thenReturn(createMockPasspointConfigurations(NUM_NETWORKS)); + + mWifiSettings2.setAdditionalSettingsSummaries(); + + assertThat(mWifiSettings2.mSavedNetworksPreference.isVisible()).isTrue(); + assertThat(mWifiSettings2.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(mWifiManager.getConfiguredNetworks()) + .thenReturn(createMockWifiConfigurations(0 /* count */)); + + mWifiSettings2.setAdditionalSettingsSummaries(); + + assertThat(mWifiSettings2.mSavedNetworksPreference.isVisible()).isFalse(); + } + + @Test + public void setAdditionalSettingsSummaries_wifiWakeupEnabled_displayOn() { + final ContentResolver contentResolver = mContext.getContentResolver(); + Settings.Global.putInt(contentResolver, Settings.Global.WIFI_WAKEUP_ENABLED, 1); + Settings.Global.putInt(contentResolver, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 1); + Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0); + when(mPowerManager.isPowerSaveMode()).thenReturn(false); + + mWifiSettings2.setAdditionalSettingsSummaries(); + + assertThat(mWifiSettings2.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(); + Settings.Global.putInt(contentResolver, Settings.Global.WIFI_WAKEUP_ENABLED, 0); + + mWifiSettings2.setAdditionalSettingsSummaries(); + + assertThat(mWifiSettings2.mConfigureWifiSettingsPreference.getSummary()).isEqualTo( + mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_off)); + } + + @Test + public void checkAddWifiNetworkPrefernce_preferenceVisible() { + assertThat(mWifiSettings2.mAddWifiNetworkPreference.isVisible()).isTrue(); + assertThat(mWifiSettings2.mAddWifiNetworkPreference.getTitle()).isEqualTo( + mContext.getString(R.string.wifi_add_network)); + } + + private void setUpForOnCreate() { + final FragmentActivity activity = mock(FragmentActivity.class); + when(mWifiSettings2.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(mWifiSettings2.findPreference(WifiSettings.PREF_KEY_DATA_USAGE)) + .thenReturn(mDataUsagePreference); + } + + @Test + @Config(shadows = {ShadowDataUsageUtils.class, ShadowFragment.class}) + public void checkDataUsagePreference_perferenceInvisibleIfWifiNotSupported() { + setUpForOnCreate(); + ShadowDataUsageUtils.IS_WIFI_SUPPORTED = false; + + mWifiSettings2.onCreate(Bundle.EMPTY); + + verify(mDataUsagePreference).setVisible(false); + } + + @Test + @Config(shadows = {ShadowDataUsageUtils.class, ShadowFragment.class}) + public void checkDataUsagePreference_perferenceVisibleIfWifiSupported() { + setUpForOnCreate(); + ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true; + + mWifiSettings2.onCreate(Bundle.EMPTY); + + verify(mDataUsagePreference).setVisible(true); + verify(mDataUsagePreference).setTemplate(any(), eq(0) /*subId*/, eq(null) /*service*/); + } + +// TODO(b/70983952): Add test for context menu +// @Test +// public void onCreateContextMenu_shouldHaveForgetMenuForConnectedAccessPreference() { +// final FragmentActivity mockActivity = mock(FragmentActivity.class); +// when(mockActivity.getApplicationContext()).thenReturn(mContext); +// when(mWifiSettings2.getActivity()).thenReturn(mockActivity); +// +// final AccessPoint accessPoint = mock(AccessPoint.class); +// when(accessPoint.isConnectable()).thenReturn(false); +// when(accessPoint.isSaved()).thenReturn(true); +// when(accessPoint.isActive()).thenReturn(true); +// +// final ConnectedAccessPointPreference connectedPreference = +// mWifiSettings2.createConnectedAccessPointPreference(accessPoint, mContext); +// final View view = mock(View.class); +// when(view.getTag()).thenReturn(connectedPreference); +// +// final ContextMenu menu = mock(ContextMenu.class); +// mWifiSettings2.onCreateContextMenu(menu, view, null /* info */); +// +// verify(menu).add(anyInt(), eq(WifiSettings.MENU_ID_FORGET), anyInt(), anyInt()); +// } +}