Merge "[Wi-Fi] Add one network request case for adding Wi-Fi for apps feature."
diff --git a/res/layout/wifi_add_app_networks.xml b/res/layout/wifi_add_app_networks.xml
index 2dc3993..8696e04 100644
--- a/res/layout/wifi_add_app_networks.xml
+++ b/res/layout/wifi_add_app_networks.xml
@@ -85,6 +85,42 @@
         <include layout="@layout/horizontal_divider"/>
 
         <LinearLayout
+            android:id="@+id/single_network"
+            android:layout_width="match_parent"
+            android:layout_height="144dp"
+            android:paddingTop="24dp"
+            android:paddingBottom="16dp"
+            android:orientation="vertical">
+
+            <ImageView
+                android:id="@+id/signal_strength"
+                android:layout_width="48dp"
+                android:layout_height="48dp"
+                android:layout_gravity="center_horizontal"/>
+
+            <TextView
+                android:id="@+id/single_ssid"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="8dp"
+                android:singleLine="true"
+                android:gravity="center"
+                android:textAppearance="?android:attr/textAppearanceListItem"
+                android:ellipsize="marquee"/>
+
+            <TextView
+                android:id="@+id/single_status"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="2dp"
+                android:gravity="center"
+                android:accessibilityLiveRegion="polite"
+                android:textColor="?android:attr/textColorSecondary"/>
+        </LinearLayout>
+
+        <include layout="@layout/horizontal_divider"/>
+
+        <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
@@ -113,4 +149,4 @@
                 android:text="@string/save"/>
         </LinearLayout>
     </LinearLayout>
-</FrameLayout>
\ No newline at end of file
+</FrameLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 69152dd..63dee46 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2336,10 +2336,16 @@
     <string name="wifi_hotspot_configure_ap_text_summary">AndroidAP WPA2 PSK hotspot</string>
     <!-- Default access point SSID used for tethering -->
     <string name="wifi_tether_configure_ssid_default">AndroidHotspot</string>
-    <!-- Title for the panel of add Wi-Fi network from APP [CHAR LIMIT=50]-->
+    <!-- Title for the panel of add Wi-Fi network from APP [CHAR LIMIT=50] -->
     <string name="wifi_add_app_single_network_title">Save this network?</string>
-    <!-- Summary for the panel of add Wi-Fi network from APP [CHAR LIMIT=NONE]-->
+    <!-- Summary for the panel of add Wi-Fi network from APP [CHAR LIMIT=NONE] -->
     <string name="wifi_add_app_single_network_summary"><xliff:g id="appName" example="ThirdPartyAppName">%1$s</xliff:g> would like to save a network to your phone</string>
+    <!-- Summary for saving status when saving single network [CHAR LIMIT=30] -->
+    <string name="wifi_add_app_single_network_saving_summary">Saving\u2026</string>
+    <!-- Summary for saved status when saving single network   [CHAR LIMIT=30] -->
+    <string name="wifi_add_app_single_network_saved_summary">Saved</string>
+    <!-- Summary for save failed status when saving single network [CHAR LIMIT=50] -->
+    <string name="wifi_add_app_single_network_save_failed_summary">Couldn\u2019t save. Try again.</string>
 
     <!-- Do not translate. Used for diagnostic screens, precise translation is not necessary
          Wi-Fi Testing on the diagnostic screen-->
diff --git a/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivity.java b/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivity.java
index 0810b54..298857e 100644
--- a/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivity.java
+++ b/src/com/android/settings/wifi/addappnetworks/AddAppNetworksActivity.java
@@ -18,6 +18,7 @@
 
 import android.content.Intent;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.view.Gravity;
 import android.view.Window;
 import android.view.WindowManager;
@@ -53,6 +54,12 @@
         setContentView(R.layout.settings_panel);
         showAddNetworksFragment();
         getLifecycle().addObserver(new HideNonSystemOverlayMixin(this));
+
+        // Move the window to the bottom of screen, and make it take up the entire screen width.
+        final Window window = getWindow();
+        window.setGravity(Gravity.BOTTOM);
+        window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.WRAP_CONTENT);
     }
 
     @Override
@@ -64,14 +71,11 @@
 
     @VisibleForTesting
     void showAddNetworksFragment() {
-        // Move the window to the bottom of screen, and make it take up the entire screen width.
-        final Window window = getWindow();
-        window.setGravity(Gravity.BOTTOM);
-        window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
-                WindowManager.LayoutParams.WRAP_CONTENT);
-
-        // TODO: check the new intent status
+        // TODO: Check the new intent status.
         mBundle.putString(KEY_CALLING_PACKAGE_NAME, getCallingPackage());
+        mBundle.putParcelableArrayList(Settings.EXTRA_WIFI_CONFIGURATION_LIST,
+                getIntent().getParcelableArrayListExtra(Settings.EXTRA_WIFI_CONFIGURATION_LIST));
+
         final FragmentManager fragmentManager = getSupportFragmentManager();
         if (fragmentManager.findFragmentByTag(TAG) == null) {
             final AddAppNetworksFragment fragment = new AddAppNetworksFragment();
diff --git a/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java b/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java
index 281ca57..eeec166 100644
--- a/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java
+++ b/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragment.java
@@ -16,13 +16,22 @@
 
 package com.android.settings.wifi.addappnetworks;
 
+import static android.app.Activity.RESULT_CANCELED;
+import static android.app.Activity.RESULT_OK;
+
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiManager;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -41,6 +50,7 @@
 import com.android.settings.core.InstrumentedFragment;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * The Fragment list those networks, which is proposed by other app, to user, and handle user's
@@ -49,10 +59,36 @@
 public class AddAppNetworksFragment extends InstrumentedFragment {
     public static final String TAG = "AddAppNetworksFragment";
 
-    private TextView mTitleView;
-    private TextView mSummaryView;
-    private ImageView mIconView;
+    // Security types of a requested or saved network.
+    private static final String SECURITY_NO_PASSWORD = "nopass";
+    private static final String SECURITY_WEP = "wep";
+    private static final String SECURITY_WPA_PSK = "wpa";
+    private static final String SECURITY_SAE = "sae";
 
+    // Possible result values in each item of the returned result list, which is used
+    // to inform the caller APP the processed result of each specified network.
+    private static final int RESULT_NETWORK_INITIAL = -1;  //initial value
+    private static final int RESULT_NETWORK_SUCCESS = 0;
+    private static final int RESULT_NETWORK_ADD_ERROR = 1;
+    private static final int RESULT_NETWORK_ALREADY_EXISTS = 2;
+
+    // Handler messages for controlling different state and delay showing the status message.
+    private static final int MESSAGE_START_SAVING_NETWORK = 1;
+    private static final int MESSAGE_SHOW_SAVED_AND_CONNECT_NETWORK = 2;
+    private static final int MESSAGE_SHOW_SAVE_FAILED = 3;
+    private static final int MESSAGE_FINISH = 4;
+
+    // Signal level for the constant signal icon.
+    private static final int MAX_RSSI_SIGNAL_LEVEL = 4;
+
+    // Duration for showing different status message.
+    private static final long SHOW_SAVING_INTERVAL_MILLIS = 500L;
+    private static final long SHOW_SAVED_INTERVAL_MILLIS = 1000L;
+
+    @VisibleForTesting
+    FragmentActivity mActivity;
+    @VisibleForTesting
+    View mLayoutView;
     @VisibleForTesting
     Button mCancelButton;
     @VisibleForTesting
@@ -60,45 +96,251 @@
     @VisibleForTesting
     String mCallingPackageName;
 
+    private TextView mSummaryView;
+    private TextView mSingleNetworkProcessingStatusView;
+    private int mSavingIndex;
+    private List<WifiConfiguration> mAllSpecifiedNetworksList;
+    private ArrayList<Integer> mResultCodeArrayList;
+    private WifiManager.ActionListener mSaveListener;
+    private WifiManager mWifiManager;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MESSAGE_START_SAVING_NETWORK:
+                    mSaveButton.setEnabled(false);
+                    // Set the initial text color for status message.
+                    mSingleNetworkProcessingStatusView.setTextColor(
+                            com.android.settingslib.Utils.getColorAttr(mActivity,
+                                    android.R.attr.textColorSecondary));
+                    mSingleNetworkProcessingStatusView.setText(
+                            getString(R.string.wifi_add_app_single_network_saving_summary));
+                    mSingleNetworkProcessingStatusView.setVisibility(View.VISIBLE);
+
+                    // Save the proposed network.
+                    saveNetworks();
+                    break;
+
+                case MESSAGE_SHOW_SAVED_AND_CONNECT_NETWORK:
+                    mSingleNetworkProcessingStatusView.setText(
+                            getString(R.string.wifi_add_app_single_network_saved_summary));
+
+                    // For the single network case, we need to call connection after saved.
+                    connectNetwork();
+
+                    sendEmptyMessageDelayed(MESSAGE_FINISH,
+                            SHOW_SAVED_INTERVAL_MILLIS);
+                    break;
+
+                case MESSAGE_SHOW_SAVE_FAILED:
+                    mSingleNetworkProcessingStatusView.setText(
+                            getString(R.string.wifi_add_app_single_network_save_failed_summary));
+                    // Error message need to use colorError attribute to show.
+                    mSingleNetworkProcessingStatusView.setTextColor(
+                            com.android.settingslib.Utils.getColorAttr(mActivity,
+                                    android.R.attr.colorError));
+                    mSaveButton.setEnabled(true);
+                    break;
+
+                case MESSAGE_FINISH:
+                    finishWithResult(RESULT_OK, mResultCodeArrayList);
+                    break;
+
+                default:
+                    // Do nothing.
+                    break;
+            }
+        }
+    };
+
     @Nullable
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
             @Nullable Bundle savedInstanceState) {
+        mActivity = getActivity();
+        mWifiManager = mActivity.getSystemService(WifiManager.class);
+
         return inflater.inflate(R.layout.wifi_add_app_networks, container, false);
     }
 
+    // TODO: Makesure function work correctly after rotate.
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
-        // init local variable.
-        mTitleView = view.findViewById(R.id.app_title);
-        mIconView = view.findViewById(R.id.app_icon);
+        // Initial UI variable.
+        mLayoutView = view;
         mCancelButton = view.findViewById(R.id.cancel);
         mSaveButton = view.findViewById(R.id.save);
         mSummaryView = view.findViewById(R.id.app_summary);
-
-        // Assigns button listeners.
+        mSingleNetworkProcessingStatusView = view.findViewById(R.id.single_status);
+        // Assigns button listeners and network save listener.
         mCancelButton.setOnClickListener(getCancelListener());
         mSaveButton.setOnClickListener(getSaveListener());
+        prepareSaveResultListener();
 
+        // Prepare the non-UI variables.
         final Bundle bundle = getArguments();
         createContent(bundle);
     }
 
     private void createContent(Bundle bundle) {
-        final FragmentActivity activity = getActivity();
+        mAllSpecifiedNetworksList =
+                bundle.getParcelableArrayList(Settings.EXTRA_WIFI_CONFIGURATION_LIST);
 
-        // Assigns caller app icon and summary.
+        // If there is no networks in the request intent, then just finish activity.
+        if (mAllSpecifiedNetworksList == null || mAllSpecifiedNetworksList.isEmpty()) {
+            finishWithResult(RESULT_CANCELED, null /* resultArrayList */);
+            return;
+        }
+
+        // Initial the result arry.
+        initializeResultCodeArray();
+
+        // Filter out the saved networks, don't show saved networks to user.
+        checkSavedNetworks();
+
+        if (mAllSpecifiedNetworksList.size() == 1) {
+            // If the only one requested network is already saved, just return with existence.
+            if (mResultCodeArrayList.get(0) == RESULT_NETWORK_ALREADY_EXISTS) {
+                finishWithResult(RESULT_OK, mResultCodeArrayList);
+                return;
+            }
+
+            // Show signal icon for single network case.
+            setSingleNetworkSignalIcon();
+            // Show the SSID of the proposed network.
+            ((TextView) mLayoutView.findViewById(R.id.single_ssid)).setText(
+                    mAllSpecifiedNetworksList.get(0).SSID);
+            // Set the status view as gone when UI is initialized.
+            mSingleNetworkProcessingStatusView.setVisibility(View.GONE);
+        } else {
+            // TODO: Add code for processing multiple networks case.
+        }
+
+        // Assigns caller app icon, title, and summary.
         mCallingPackageName =
                 bundle.getString(AddAppNetworksActivity.KEY_CALLING_PACKAGE_NAME);
-        assignAppIcon(activity, mCallingPackageName);
-        assignTitleAndSummary(activity, mCallingPackageName);
+        assignAppIcon(mActivity, mCallingPackageName);
+        assignTitleAndSummary(mActivity, mCallingPackageName);
+    }
+
+    private void initializeResultCodeArray() {
+        final int networksSize = mAllSpecifiedNetworksList.size();
+        mResultCodeArrayList = new ArrayList<>();
+
+        for (int i = 0; i < networksSize; i++) {
+            mResultCodeArrayList.add(RESULT_NETWORK_INITIAL);
+        }
+    }
+
+    /**
+     * Classify security type into following types:
+     * 1. {@Code SECURITY_NO_PASSWORD}: No password network or OWE network.
+     * 2. {@Code SECURITY_WEP}: Traditional WEP encryption network.
+     * 3. {@Code SECURITY_WPA_PSK}: WPA/WPA2 preshare key type.
+     * 4. {@Code SECURITY_SAE}: SAE type network.
+     */
+    private String getSecurityType(WifiConfiguration config) {
+        if (config.allowedKeyManagement.get(KeyMgmt.SAE)) {
+            return SECURITY_SAE;
+        }
+        if (config.allowedKeyManagement.get(KeyMgmt.OWE)) {
+            return SECURITY_NO_PASSWORD;
+        }
+        if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK) || config.allowedKeyManagement.get(
+                KeyMgmt.WPA2_PSK)) {
+            return SECURITY_WPA_PSK;
+        }
+        return (config.wepKeys[0] == null) ? SECURITY_NO_PASSWORD : SECURITY_WEP;
+    }
+
+    /**
+     * For the APP specified networks, need to filter out those saved ones and mark them as existed.
+     */
+    private void checkSavedNetworks() {
+        final List<WifiConfiguration> privilegedWifiConfigurations =
+                mWifiManager.getPrivilegedConfiguredNetworks();
+        boolean foundInSavedList;
+        int networkPositionInBundle = 0;
+        for (WifiConfiguration specifiecConfig : mAllSpecifiedNetworksList) {
+            foundInSavedList = false;
+            final String ssidWithQuotation = addQuotationIfNeeded(specifiecConfig.SSID);
+            final String securityType = getSecurityType(specifiecConfig);
+
+            for (WifiConfiguration privilegedWifiConfiguration : privilegedWifiConfigurations) {
+                final String savedSecurityType = getSecurityType(privilegedWifiConfiguration);
+
+                // If SSID or security type is different, should be new network or need to updated
+                // network.
+                if (!ssidWithQuotation.equals(privilegedWifiConfiguration.SSID)
+                        || !securityType.equals(savedSecurityType)) {
+                    continue;
+                }
+
+                //  If specified network and saved network have same security types, we'll check
+                //  more information according to their security type to judge if they are same.
+                switch (securityType) {
+                    case SECURITY_NO_PASSWORD:
+                        foundInSavedList = true;
+                        break;
+                    case SECURITY_WEP:
+                        if (specifiecConfig.wepKeys[0].equals(
+                                privilegedWifiConfiguration.wepKeys[0])) {
+                            foundInSavedList = true;
+                        }
+                        break;
+                    case SECURITY_WPA_PSK:
+                    case SECURITY_SAE:
+                        if (specifiecConfig.preSharedKey.equals(
+                                privilegedWifiConfiguration.preSharedKey)) {
+                            foundInSavedList = true;
+                        }
+                        break;
+                    default:
+                        break;
+                }
+            }
+
+            if (foundInSavedList) {
+                // If this requested network already in the saved networks, mark this item in the
+                // result code list as existed.
+                mResultCodeArrayList.set(networkPositionInBundle, RESULT_NETWORK_ALREADY_EXISTS);
+            } else {
+                // TODO: for multiple networks case, need to add to adapter for present list to user
+            }
+            networkPositionInBundle++;
+        }
+    }
+
+    private void setSingleNetworkSignalIcon() {
+        // TODO: Check level of the network to show signal icon.
+        final Drawable wifiIcon = mActivity.getDrawable(
+                Utils.getWifiIconResource(MAX_RSSI_SIGNAL_LEVEL)).mutate();
+        final Drawable wifiIconDark = wifiIcon.getConstantState().newDrawable().mutate();
+        wifiIconDark.setTintList(
+                Utils.getColorAttr(mActivity, android.R.attr.colorControlNormal));
+        ((ImageView) mLayoutView.findViewById(R.id.signal_strength)).setImageDrawable(wifiIconDark);
+    }
+
+    private String addQuotationIfNeeded(String input) {
+        if (TextUtils.isEmpty(input)) {
+            return "";
+        }
+
+        if (input.length() >= 2 && input.startsWith("\"") && input.endsWith("\"")) {
+            return input;
+        }
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("\"").append(input).append("\"");
+        return sb.toString();
     }
 
     private void assignAppIcon(Context context, String callingPackageName) {
         final Drawable drawable = loadPackageIconDrawable(context, callingPackageName);
-        mIconView.setImageDrawable(drawable);
+        ((ImageView) mLayoutView.findViewById(R.id.app_icon)).setImageDrawable(drawable);
     }
 
     private Drawable loadPackageIconDrawable(Context context, String callingPackageName) {
@@ -114,7 +356,7 @@
 
     private void assignTitleAndSummary(Context context, String callingPackageName) {
         // Assigns caller app name to title
-        mTitleView.setText(getTitle());
+        ((TextView) mLayoutView.findViewById(R.id.app_title)).setText(getTitle());
 
         // Set summary
         mSummaryView.setText(getAddNetworkRequesterSummary(
@@ -132,23 +374,60 @@
     View.OnClickListener getCancelListener() {
         return (v) -> {
             Log.d(TAG, "User rejected to add network");
+            finishWithResult(RESULT_CANCELED, null /* resultArrayList */);
         };
     }
 
     View.OnClickListener getSaveListener() {
         return (v) -> {
             Log.d(TAG, "User agree to add networks");
+            // Start to process saving networks.
+            final Message message = mHandler.obtainMessage(MESSAGE_START_SAVING_NETWORK);
+            message.sendToTarget();
         };
     }
 
+    private void prepareSaveResultListener() {
+        mSaveListener = new WifiManager.ActionListener() {
+            @Override
+            public void onSuccess() {
+                mResultCodeArrayList.set(mSavingIndex, RESULT_NETWORK_SUCCESS);
+                Message nextState_Message = mHandler.obtainMessage(
+                        MESSAGE_SHOW_SAVED_AND_CONNECT_NETWORK);
+                // Delay to change to next state for showing saving mesage for a period.
+                mHandler.sendMessageDelayed(nextState_Message, SHOW_SAVING_INTERVAL_MILLIS);
+            }
+
+            @Override
+            public void onFailure(int reason) {
+                mResultCodeArrayList.set(mSavingIndex, RESULT_NETWORK_ADD_ERROR);
+                Message nextState_Message = mHandler.obtainMessage(MESSAGE_SHOW_SAVE_FAILED);
+                // Delay to change to next state for showing saving mesage for a period.
+                mHandler.sendMessageDelayed(nextState_Message, SHOW_SAVING_INTERVAL_MILLIS);
+            }
+        };
+    }
+
+    private void saveNetworks() {
+        final WifiConfiguration wifiConfiguration = mAllSpecifiedNetworksList.get(0);
+        wifiConfiguration.SSID = addQuotationIfNeeded(wifiConfiguration.SSID);
+        mWifiManager.save(wifiConfiguration, mSaveListener);
+    }
+
+    private void connectNetwork() {
+        final WifiConfiguration wifiConfiguration = mAllSpecifiedNetworksList.get(0);
+        // Don't need to handle the connect result.
+        mWifiManager.connect(wifiConfiguration, null /* ActionListener */);
+    }
+
     private void finishWithResult(int resultCode, ArrayList<Integer> resultArrayList) {
         if (resultArrayList != null) {
             Intent intent = new Intent();
             intent.putIntegerArrayListExtra(Settings.EXTRA_WIFI_CONFIGURATION_RESULT_LIST,
                     resultArrayList);
-            getActivity().setResult(resultCode, intent);
+            mActivity.setResult(resultCode, intent);
         }
-        getActivity().finish();
+        mActivity.finish();
     }
 
     @Override
diff --git a/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
index 38ddf33..999d44e 100644
--- a/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
@@ -22,49 +22,112 @@
 import static org.mockito.Mockito.spy;
 
 import android.content.Context;
+import android.net.wifi.WifiConfiguration;
 import android.os.Bundle;
+import android.os.Parcelable;
+import android.provider.Settings;
+import android.widget.TextView;
 
-import androidx.fragment.app.FragmentActivity;
+import com.android.settings.R;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.shadows.androidx.fragment.FragmentController;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(RobolectricTestRunner.class)
 public class AddAppNetworksFragmentTest {
     private static final String FAKE_APP_NAME = "fake_app_name";
-    private FragmentActivity mActivity;
+    private static final String FAKE_SSID = "fake_ssid";
     private AddAppNetworksFragment mAddAppNetworksFragment;
     private Context mContext;
 
     @Before
     public void setUp() {
         mAddAppNetworksFragment = spy(new AddAppNetworksFragment());
-        MockitoAnnotations.initMocks(this);
-
-        // Set up bundle
-        final Bundle bundle = new Bundle();
-        bundle.putString(AddAppNetworksActivity.KEY_CALLING_PACKAGE_NAME, FAKE_APP_NAME);
-        doReturn(bundle).when(mAddAppNetworksFragment).getArguments();
-
-        FragmentController.setupFragment(mAddAppNetworksFragment);
     }
 
     @Test
     public void callingPackageName_onCreateView_shouldBeCorrect() {
+        setUpOneNetworkBundle();
+        setupFragment();
+
         assertThat(mAddAppNetworksFragment.mCallingPackageName).isEqualTo(FAKE_APP_NAME);
     }
 
     @Test
     public void launchFragment_shouldShowSaveButton() {
+        setUpOneNetworkBundle();
+        setupFragment();
+
         assertThat(mAddAppNetworksFragment.mSaveButton).isNotNull();
     }
 
     @Test
     public void launchFragment_shouldShowCancelButton() {
+        setUpOneNetworkBundle();
+        setupFragment();
+
         assertThat(mAddAppNetworksFragment.mCancelButton).isNotNull();
     }
+
+    @Test
+    public void requestOneNetwork_shouldShowCorrectSSID() {
+        setUpOneNetworkBundle();
+        setupFragment();
+        TextView ssidView = (TextView) mAddAppNetworksFragment.mLayoutView.findViewById(
+                R.id.single_ssid);
+
+        assertThat(ssidView.getText()).isEqualTo(FAKE_SSID);
+    }
+
+    @Test
+    public void withNoExtra_requestNetwork_shouldFinished() {
+        setUpNoNetworkBundle();
+        setupFragment();
+
+        assertThat(mAddAppNetworksFragment.mActivity.isFinishing()).isTrue();
+    }
+
+    private void setUpOneNetworkBundle() {
+        // Setup one network.
+        List<WifiConfiguration> wifiConfigurationList = new ArrayList<>();
+        wifiConfigurationList.add(
+                generateWifiConfig(FAKE_SSID, WifiConfiguration.KeyMgmt.WPA_PSK, "\"1234567890\""));
+        // Set up bundle.
+        final Bundle bundle = new Bundle();
+        bundle.putString(AddAppNetworksActivity.KEY_CALLING_PACKAGE_NAME, FAKE_APP_NAME);
+        bundle.putParcelableArrayList(Settings.EXTRA_WIFI_CONFIGURATION_LIST,
+                (ArrayList<? extends Parcelable>) wifiConfigurationList);
+        doReturn(bundle).when(mAddAppNetworksFragment).getArguments();
+    }
+
+    private void setUpNoNetworkBundle() {
+        // Set up bundle.
+        final Bundle bundle = new Bundle();
+        bundle.putString(AddAppNetworksActivity.KEY_CALLING_PACKAGE_NAME, FAKE_APP_NAME);
+        bundle.putParcelableArrayList(Settings.EXTRA_WIFI_CONFIGURATION_LIST, null);
+        doReturn(bundle).when(mAddAppNetworksFragment).getArguments();
+    }
+
+    private void setupFragment() {
+        FragmentController.setupFragment(mAddAppNetworksFragment);
+    }
+
+    private static WifiConfiguration generateWifiConfig(String ssid, int securityType,
+            String password) {
+        final WifiConfiguration config = new WifiConfiguration();
+        config.SSID = ssid;
+        config.allowedKeyManagement.set(securityType);
+
+        if (password != null) {
+            config.preSharedKey = password;
+        }
+        return config;
+    }
+
 }