diff --git a/src/com/android/settings/wifi/WifiSettings2.java b/src/com/android/settings/wifi/WifiSettings2.java
index 713679e..a86d39a 100644
--- a/src/com/android/settings/wifi/WifiSettings2.java
+++ b/src/com/android/settings/wifi/WifiSettings2.java
@@ -18,18 +18,628 @@
 
 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<AccessPoint> 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<AccessPoint> 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<SearchIndexableRaw> getRawDataToIndex(Context context,
+                        boolean enabled) {
+                    final List<SearchIndexableRaw> 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 0000000..7ce05e1
--- /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<SearchIndexableRaw> 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<SearchIndexableRaw> 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<WifiConfiguration> createMockWifiConfigurations(int count) {
+        final List<WifiConfiguration> mockConfigs = new ArrayList<>();
+        for (int i = 0; i < count; i++) {
+            mockConfigs.add(new WifiConfiguration());
+        }
+        return mockConfigs;
+    }
+
+    private List<PasspointConfiguration> createMockPasspointConfigurations(int count) {
+        final List<PasspointConfiguration> 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());
+//    }
+}
