Merge "Get enrollment animation from overlay"
diff --git a/Android.mk b/Android.mk
index 7eb9b6a..0fbaacf 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,6 +15,7 @@
 LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
+LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.settings
 LOCAL_MODULE_TAGS := optional
 LOCAL_USE_AAPT2 := true
 
@@ -70,4 +71,4 @@
 # Use the following include to make our test apk.
 ifeq (,$(ONE_SHOT_MAKEFILE))
 include $(call all-makefiles-under,$(LOCAL_PATH))
-endif
\ No newline at end of file
+endif
diff --git a/res/layout/homepage_condition_half_tile.xml b/res/layout/homepage_condition_half_tile.xml
index eff167a..895183f 100644
--- a/res/layout/homepage_condition_half_tile.xml
+++ b/res/layout/homepage_condition_half_tile.xml
@@ -25,38 +25,44 @@
         android:id="@+id/content"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingStart="@dimen/homepage_card_padding_start"
-        android:paddingEnd="@dimen/homepage_card_padding_end"
         android:paddingTop="@dimen/homepage_condition_half_card_padding_top"
         android:orientation="vertical">
 
-        <ImageView
-            android:id="@android:id/icon"
-            android:layout_width="@dimen/homepage_card_icon_size"
-            android:layout_height="@dimen/homepage_card_icon_size"
-            android:tint="?android:attr/colorAccent"/>
-
-        <TextView
-            android:id="@android:id/title"
+        <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:maxLines="1"
-            android:ellipsize="end"
-            android:layout_marginTop="@dimen/homepage_condition_half_card_title_margin_top"
-            android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
-            style="@style/TextAppearance.ConditionCardTitle"/>
+            android:paddingStart="@dimen/homepage_card_padding_start"
+            android:paddingEnd="@dimen/homepage_card_padding_end"
+            android:orientation="vertical">
 
-        <TextView
-            android:id="@android:id/summary"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:maxLines="1"
-            android:ellipsize="end"
-            android:layout_marginBottom="@dimen/homepage_condition_half_card_summary_margin_bottom"
-            style="@style/TextAppearance.ConditionCardSummary"/>
+            <ImageView
+                android:id="@android:id/icon"
+                android:layout_width="@dimen/homepage_card_icon_size"
+                android:layout_height="@dimen/homepage_card_icon_size"
+                android:tint="?android:attr/colorAccent"/>
 
-        <include layout="@layout/horizontal_divider"/>
+            <TextView
+                android:id="@android:id/title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:maxLines="1"
+                android:ellipsize="end"
+                android:layout_marginTop="@dimen/homepage_condition_half_card_title_margin_top"
+                android:layout_marginBottom="@dimen/homepage_condition_card_title_margin_bottom"
+                style="@style/TextAppearance.ConditionCardTitle"/>
 
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:maxLines="1"
+                android:ellipsize="end"
+                android:layout_marginBottom="@dimen/homepage_condition_half_card_summary_margin_bottom"
+                style="@style/TextAppearance.ConditionCardSummary"/>
+
+            <include layout="@layout/horizontal_divider"/>
+
+        </LinearLayout>
         <Button
             android:id="@+id/first_action"
             android:layout_width="match_parent"
diff --git a/res/layout/preference_app_restrictions.xml b/res/layout/preference_app_restrictions.xml
index 4bb6fe2..65fd06c 100644
--- a/res/layout/preference_app_restrictions.xml
+++ b/res/layout/preference_app_restrictions.xml
@@ -39,11 +39,11 @@
             android:orientation="horizontal">
             <ImageView
                 android:id="@android:id/icon"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
+                android:layout_width="@dimen/secondary_app_icon_size"
+                android:layout_height="@dimen/secondary_app_icon_size"
                 android:layout_gravity="center"
-                android:minWidth="48dp"
-                android:scaleType="centerInside"
+                android:minWidth="@dimen/secondary_app_icon_size"
+                android:scaleType="fitCenter"
                 android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"
                  />
         </LinearLayout>
diff --git a/res/layout/search_bar.xml b/res/layout/search_bar.xml
index be8aa3b..fe2f270 100644
--- a/res/layout/search_bar.xml
+++ b/res/layout/search_bar.xml
@@ -43,5 +43,6 @@
         android:layout_marginEnd="@dimen/search_bar_avatar_end_margin"
         android:layout_width="@dimen/search_bar_avatar_size"
         android:layout_height="@dimen/search_bar_avatar_size"
-        android:layout_gravity="end|center_vertical"/>
+        android:layout_gravity="end|center_vertical"
+        android:contentDescription="@string/search_bar_account_avatar_content_description"/>
 </com.google.android.material.card.MaterialCardView>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 188ba6e..d042ebc 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -10343,4 +10343,11 @@
     <string name="contextual_card_feedback_send">Send feedback</string>
     <!-- String for contextual card feedback dialog [CHAR LIMIT=NONE] -->
     <string name="contextual_card_feedback_confirm_message">Would you like to give us feedback on this suggestion?</string>
+
+    <!-- Toast message for copy action of Copyable Slice [CHAR LIMIT=NONE] -->
+    <string name="copyable_slice_toast"><xliff:g id="copy_content" example="Phone number">%1$s</xliff:g> copied to clipboard.</string>
+
+    <!-- String for talkback on the account avatar of the search bar.  [CHAR LIMIT=NONE] -->
+    <string name="search_bar_account_avatar_content_description"></string>
+
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 19ce333..48cd876 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -476,6 +476,7 @@
     <style name="ConditionHalfCardBorderlessButton"
            parent="@style/ConditionCardBorderlessButton">
         <item name="android:textAlignment">viewStart</item>
+        <item name="android:layout_marginStart">4dp</item>
     </style>
 
     <style name="ConditionFullCardBorderlessButton"
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 9a05bfc..390be584 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -202,10 +202,12 @@
         <item name="android:windowLightNavigationBar">true</item>
     </style>
 
+    <!-- Note that Dialog themes do not set list dividers -->
     <style name="Theme.BottomDialog" parent="@*android:style/Theme.DeviceDefault.Settings.Dialog">
         <item name="android:windowBackground">@drawable/settings_panel_background</item>
         <item name="android:dividerHorizontal">@*android:drawable/list_divider_material</item>
         <item name="android:windowNoTitle">true</item>
+        <item name="android:listDivider">@*android:drawable/list_divider_material</item>
         <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
     </style>
 
diff --git a/src/com/android/settings/DateTimeSettings.java b/src/com/android/settings/DateTimeSettings.java
index 149deb1..05dd265 100644
--- a/src/com/android/settings/DateTimeSettings.java
+++ b/src/com/android/settings/DateTimeSettings.java
@@ -20,7 +20,6 @@
 import android.app.Dialog;
 import android.content.Context;
 import android.content.Intent;
-import android.os.UserManager;
 import android.provider.SearchIndexableResource;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index 18c83f4..2791efa 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -1194,12 +1194,10 @@
             int state = mTelephonyManager.getDataState();
             switch (state) {
                 case TelephonyManager.DATA_CONNECTED:
-                    //FIXME: Replace with a TelephonyManager call
-                    phone.setUserDataEnabled(false);
+                    mTelephonyManager.setDataEnabled(false);
                     break;
                 case TelephonyManager.DATA_DISCONNECTED:
-                    //FIXME: Replace with a TelephonyManager call
-                    phone.setUserDataEnabled(true);
+                    mTelephonyManager.setDataEnabled(true);
                     break;
                 default:
                     // do nothing
diff --git a/src/com/android/settings/applications/AppLaunchSettings.java b/src/com/android/settings/applications/AppLaunchSettings.java
index 0e2e3c7..3ccc36f 100644
--- a/src/com/android/settings/applications/AppLaunchSettings.java
+++ b/src/com/android/settings/applications/AppLaunchSettings.java
@@ -124,6 +124,8 @@
             // * always
             // * ask
             // * never
+            //
+            // Make sure to update linkStateToIndex() if this presentation order is changed.
             mAppLinkState.setEntries(new CharSequence[] {
                     getString(R.string.app_link_open_always),
                     getString(R.string.app_link_open_ask),
@@ -141,10 +143,7 @@
                 // purposes of the UI (and does the right thing around pending domain
                 // verifications that might arrive after the user chooses 'ask' in this UI).
                 final int state = mPm.getIntentVerificationStatusAsUser(mPackageName, UserHandle.myUserId());
-                mAppLinkState.setValue(
-                        Integer.toString((state == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED)
-                                ? INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK
-                                        : state));
+                mAppLinkState.setValueIndex(linkStateToIndex(state));
 
                 // Set the callback only after setting the initial selected item
                 mAppLinkState.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@@ -157,6 +156,17 @@
         }
     }
 
+    private int linkStateToIndex(final int state) {
+        switch (state) {
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
+                return 0; // Always
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER:
+                return 2; // Never
+            default:
+                return 1; // Ask
+        }
+    }
+
     private boolean updateAppLinkState(final int newState) {
         if (mIsBrowser) {
             // We shouldn't get into this state, but if we do make sure
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
index c246c58..4bda99e 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
@@ -25,6 +25,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.location.LocationManager;
 import android.os.RemoteException;
 import android.os.UserManager;
 import android.telecom.DefaultDialerManager;
@@ -142,6 +143,12 @@
         // Keep Settings intelligence enabled, otherwise search feature will be disabled.
         keepEnabledPackages.add(
                 mContext.getString(R.string.config_settingsintelligence_package_name));
+        final LocationManager locationManager =
+                (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
+        final String locationHistoryPackage = locationManager.getLocationControllerExtraPackage();
+        if (locationHistoryPackage != null) {
+            keepEnabledPackages.add(locationHistoryPackage);
+        }
         return keepEnabledPackages;
     }
 
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index d7dc9f8..8eabf00 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -59,6 +59,10 @@
     private byte[] mToken;
     private FaceSettingsAttentionPreferenceController mAttentionController;
 
+    private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {
+        getActivity().finish();
+    };
+
     public static boolean isAvailable(Context context) {
         FaceManager manager = Utils.getFaceManagerOrNull(context);
         return manager != null && manager.isHardwareDetected();
@@ -146,10 +150,13 @@
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         final List<AbstractPreferenceController> controllers =
                 buildPreferenceControllers(context, getSettingsLifecycle());
+        // There's no great way of doing this right now :/
         for (AbstractPreferenceController controller : controllers) {
             if (controller instanceof FaceSettingsAttentionPreferenceController) {
                 mAttentionController = (FaceSettingsAttentionPreferenceController) controller;
-                break;
+            } else if (controller instanceof FaceSettingsRemoveButtonPreferenceController) {
+                ((FaceSettingsRemoveButtonPreferenceController) controller)
+                        .setListener(mRemovalListener);
             }
         }
 
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
index 8e41eff..baab391 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
@@ -17,8 +17,13 @@
 package com.android.settings.biometrics.face;
 
 import android.content.Context;
+import android.hardware.face.Face;
+import android.hardware.face.FaceManager;
+import android.os.UserHandle;
+import android.util.Log;
 import android.view.View;
 import android.widget.Button;
+import android.widget.Toast;
 
 import androidx.preference.Preference;
 
@@ -26,18 +31,61 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settingslib.widget.LayoutPreference;
 
+import java.util.List;
+
 /**
- * Controller for the remove button.
+ * Controller for the remove button. This assumes that there is only a single face enrolled. The UI
+ * will likely change if multiple enrollments are allowed/supported.
  */
 public class FaceSettingsRemoveButtonPreferenceController extends BasePreferenceController
         implements View.OnClickListener {
 
+    private static final String TAG = "FaceSettings/Remove";
     private static final String KEY = "security_settings_face_delete_faces_container";
 
+    interface Listener {
+        void onRemoved();
+    }
+
     private Button mButton;
+    private List<Face> mFaces;
+    private Listener mListener;
+
+    private final Context mContext;
+    private final int mUserId;
+    private final FaceManager mFaceManager;
+    private final FaceManager.RemovalCallback mRemovalCallback = new FaceManager.RemovalCallback() {
+        @Override
+        public void onRemovalError(Face face, int errMsgId, CharSequence errString) {
+            Log.e(TAG, "Unable to remove face: " + face.getBiometricId()
+                    + " error: " + errMsgId + " " + errString);
+            Toast.makeText(mContext, errString, Toast.LENGTH_SHORT).show();
+        }
+
+        @Override
+        public void onRemovalSucceeded(Face face, int remaining) {
+            if (remaining == 0) {
+                mFaces = mFaceManager.getEnrolledFaces(mUserId);
+                if (!mFaces.isEmpty()) {
+                    mButton.setEnabled(true);
+                } else {
+                    mListener.onRemoved();
+                }
+            } else {
+                Log.v(TAG, "Remaining: " + remaining);
+            }
+        }
+    };
 
     public FaceSettingsRemoveButtonPreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
+        mContext = context;
+        mFaceManager = context.getSystemService(FaceManager.class);
+        // TODO: Use the profile-specific userId instead
+        mUserId = UserHandle.myUserId();
+        if (mFaceManager != null) {
+            mFaces = mFaceManager.getEnrolledFaces(mUserId);
+        }
     }
 
     public FaceSettingsRemoveButtonPreferenceController(Context context) {
@@ -66,7 +114,21 @@
     @Override
     public void onClick(View v) {
         if (v == mButton) {
+            mButton.setEnabled(false);
+            if (mFaces.isEmpty()) {
+                Log.e(TAG, "No faces");
+                return;
+            }
+            if (mFaces.size() > 1) {
+                Log.e(TAG, "Multiple enrollments: " + mFaces.size());
+            }
 
+            // Remove the first/only face
+            mFaceManager.remove(mFaces.get(0), mUserId, mRemovalCallback);
         }
     }
+
+    public void setListener(Listener listener) {
+        mListener = listener;
+    }
 }
diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
index 6f5f346..462f6d9 100644
--- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
@@ -16,6 +16,10 @@
 
 package com.android.settings.deviceinfo;
 
+import static android.content.Context.CLIPBOARD_SERVICE;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
 import android.content.Context;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -23,6 +27,7 @@
 import android.text.BidiFormatter;
 import android.text.TextDirectionHeuristics;
 import android.text.TextUtils;
+import android.widget.Toast;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -30,12 +35,14 @@
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.slices.Copyable;
 import com.android.settingslib.DeviceInfoUtils;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class PhoneNumberPreferenceController extends BasePreferenceController {
+public class PhoneNumberPreferenceController extends BasePreferenceController implements
+        Copyable {
 
     private final static String KEY_PHONE_NUMBER = "phone_number";
 
@@ -46,7 +53,7 @@
     public PhoneNumberPreferenceController(Context context, String key) {
         super(context, key);
         mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
-        mSubscriptionManager =  mContext.getSystemService(SubscriptionManager.class);
+        mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
     }
 
     @Override
@@ -91,6 +98,17 @@
         return true;
     }
 
+    @Override
+    public void copy() {
+        final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
+                CLIPBOARD_SERVICE);
+        clipboard.setPrimaryClip(ClipData.newPlainText("text", getFirstPhoneNumber()));
+
+        final String toast = mContext.getString(R.string.copyable_slice_toast,
+                mContext.getText(R.string.status_number));
+        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
+    }
+
     private CharSequence getFirstPhoneNumber() {
         final List<SubscriptionInfo> subscriptionInfoList =
                 mSubscriptionManager.getActiveSubscriptionInfoList();
diff --git a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
index 164afdd..b9bab21 100644
--- a/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
+++ b/src/com/android/settings/homepage/contextualcards/CardDatabaseHelper.java
@@ -197,12 +197,11 @@
     }
 
     Cursor getContextualCards() {
-        final SQLiteDatabase db = this.getReadableDatabase();
+        final SQLiteDatabase db = getReadableDatabase();
         final String selection = CardColumns.CARD_DISMISSED + "=0";
-        Cursor cursor = db.query(CARD_TABLE, null /* columns */, selection,
+        return db.query(CARD_TABLE, null /* columns */, selection,
                 null /* selectionArgs */, null /* groupBy */, null /* having */,
                 CardColumns.SCORE + " DESC" /* orderBy */);
-        return cursor;
     }
 
     /**
diff --git a/src/com/android/settings/slices/CopyableSlice.java b/src/com/android/settings/slices/Copyable.java
similarity index 96%
rename from src/com/android/settings/slices/CopyableSlice.java
rename to src/com/android/settings/slices/Copyable.java
index 31fc151..12159d1 100644
--- a/src/com/android/settings/slices/CopyableSlice.java
+++ b/src/com/android/settings/slices/Copyable.java
@@ -19,7 +19,7 @@
 /**
  * Provide the copy ability for preference controller to copy the data to the clipboard.
  */
-public interface CopyableSlice {
+public interface Copyable {
     /**
      * Copy the key slice information to the clipboard.
      * It is highly recommended to show the toast to notify users when implemented this function.
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index 823c729..28b2f81 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -185,7 +185,7 @@
 
         final BasePreferenceController controller = getPreferenceController(context, key);
 
-        if (!(controller instanceof CopyableSlice)) {
+        if (!(controller instanceof Copyable)) {
             throw new IllegalArgumentException(
                     "Copyable action passed for a non-copyable key:" + key);
         }
@@ -198,7 +198,7 @@
             return;
         }
 
-        ((CopyableSlice) controller).copy();
+        ((Copyable) controller).copy();
     }
 
     /**
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index d75eaa2..b2b8310 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -94,7 +94,7 @@
             return buildUnavailableSlice(context, sliceData);
         }
 
-        if (controller instanceof CopyableSlice) {
+        if (controller instanceof Copyable) {
             return buildCopyableSlice(context, sliceData, controller);
         }
 
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index efb3f8c..c627a2e 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -129,8 +129,16 @@
         }
 
         if (which < accessPointList.size()) {
-            WifiConfiguration wifiConfig = accessPointList.get(which).getConfig();
-            mUserSelectionCallback.select(wifiConfig);
+            final AccessPoint selectedAccessPoint = accessPointList.get(which);
+            WifiConfiguration wifiConfig = selectedAccessPoint.getConfig();
+            if (wifiConfig == null) {
+                wifiConfig = WifiUtils.getWifiConfig(selectedAccessPoint, /* scanResult */
+                        null, /* password */ null);
+            }
+
+            if (wifiConfig != null) {
+                mUserSelectionCallback.select(wifiConfig);
+            }
         }
     }
 
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 2e3b76a..67f59ea 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -279,7 +279,7 @@
                 mHiddenSettingsSpinner.setSelection(config.hiddenSSID
                         ? HIDDEN_NETWORK
                         : NOT_HIDDEN_NETWORK);
-                //TODO(b/117957974): set MAC randomization value to mPrivacySettingsSpinner
+                mPrivacySettingsSpinner.setSelection(config.macRandomizationSetting);
                 if (config.getIpAssignment() == IpAssignment.STATIC) {
                     mIpSettingsSpinner.setSelection(STATIC_IP);
                     showAdvancedFields = true;
@@ -759,7 +759,7 @@
         }
 
         if (mPrivacySettingsSpinner != null) {
-            //TODO(b/117957974): set MAC randomization value to WifiConfiguration
+            config.macRandomizationSetting = mPrivacySettingsSpinner.getSelectedItemPosition();
         }
 
         return config;
diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java
index ff8570e..7970b2a 100644
--- a/src/com/android/settings/wifi/WifiUtils.java
+++ b/src/com/android/settings/wifi/WifiUtils.java
@@ -22,10 +22,13 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.net.NetworkCapabilities;
+import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
 import android.provider.Settings;
 import android.text.TextUtils;
 
+import com.android.settingslib.wifi.AccessPoint;
+
 import java.nio.charset.StandardCharsets;
 
 public class WifiUtils {
@@ -110,4 +113,144 @@
         return (capabilities != null
                 && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL));
     }
+
+    /**
+     * Provides a simple way to generate a new {@link WifiConfiguration} obj from
+     * {@link ScanResult} or {@link AccessPoint}. Either {@code accessPoint} or {@code scanResult
+     * } input should be not null for retrieving information, otherwise will throw
+     * IllegalArgumentException.
+     * This method prefers to take {@link AccessPoint} input in priority. Therefore this method
+     * will take {@link AccessPoint} input as preferred data extraction source when you input
+     * both {@link AccessPoint} and {@link ScanResult}, and ignore {@link ScanResult} input.
+     *
+     * Duplicated and simplified method from {@link WifiConfigController#getConfig()}.
+     * TODO(b/120827021): Should be removed if the there is have a common one in shared place (e.g.
+     * SettingsLib).
+     *
+     * @param accessPoint Input data for retrieving WifiConfiguration.
+     * @param scanResult  Input data for retrieving WifiConfiguration.
+     * @return WifiConfiguration obj based on input.
+     */
+    public static WifiConfiguration getWifiConfig(AccessPoint accessPoint, ScanResult scanResult,
+            String password) {
+        if (accessPoint == null && scanResult == null) {
+            throw new IllegalArgumentException(
+                    "At least one of AccessPoint and ScanResult input is required.");
+        }
+
+        final WifiConfiguration config = new WifiConfiguration();
+        final int security;
+
+        if (accessPoint == null) {
+            config.SSID = AccessPoint.convertToQuotedString(scanResult.SSID);
+            security = getAccessPointSecurity(scanResult);
+        } else {
+            if (!accessPoint.isSaved()) {
+                config.SSID = AccessPoint.convertToQuotedString(
+                        accessPoint.getSsidStr());
+            } else {
+                config.networkId = accessPoint.getConfig().networkId;
+                config.hiddenSSID = accessPoint.getConfig().hiddenSSID;
+            }
+            security = accessPoint.getSecurity();
+        }
+
+        switch (security) {
+            case AccessPoint.SECURITY_NONE:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+                break;
+
+            case AccessPoint.SECURITY_WEP:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+                config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+                config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
+                if (!TextUtils.isEmpty(password)) {
+                    int length = password.length();
+                    // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
+                    if ((length == 10 || length == 26 || length == 58)
+                            && password.matches("[0-9A-Fa-f]*")) {
+                        config.wepKeys[0] = password;
+                    } else {
+                        config.wepKeys[0] = '"' + password + '"';
+                    }
+                }
+                break;
+
+            case AccessPoint.SECURITY_PSK:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+                if (!TextUtils.isEmpty(password)) {
+                    if (password.matches("[0-9A-Fa-f]{64}")) {
+                        config.preSharedKey = password;
+                    } else {
+                        config.preSharedKey = '"' + password + '"';
+                    }
+                }
+                break;
+
+            case AccessPoint.SECURITY_EAP:
+            case AccessPoint.SECURITY_EAP_SUITE_B:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+                if (security == AccessPoint.SECURITY_EAP_SUITE_B) {
+                    config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
+                    config.requirePMF = true;
+                    config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
+                    config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
+                    config.allowedGroupMgmtCiphers.set(WifiConfiguration.GroupMgmtCipher
+                            .BIP_GMAC_256);
+                    config.allowedSuiteBCiphers.set(WifiConfiguration.SuiteBCipher.ECDHE_RSA);
+                }
+
+                if (!TextUtils.isEmpty(password)) {
+                    config.enterpriseConfig.setPassword(password);
+                }
+                break;
+            case AccessPoint.SECURITY_SAE:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
+                config.requirePMF = true;
+                if (!TextUtils.isEmpty(password)) {
+                    config.preSharedKey = '"' + password + '"';
+                }
+                break;
+
+            case AccessPoint.SECURITY_OWE:
+                config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
+                config.requirePMF = true;
+                break;
+
+            default:
+                break;
+        }
+
+        return config;
+    }
+
+
+    /**
+     * Gets security value from ScanResult.
+     *
+     * Duplicated method from {@link AccessPoint#getSecurity(ScanResult)}.
+     * TODO(b/120827021): Should be removed if the there is have a common one in shared place (e.g.
+     * SettingsLib).
+     *
+     * @param result ScanResult
+     * @return Related security value based on {@link AccessPoint}.
+     */
+    public static int getAccessPointSecurity(ScanResult result) {
+        if (result.capabilities.contains("WEP")) {
+            return AccessPoint.SECURITY_WEP;
+        } else if (result.capabilities.contains("SAE")) {
+            return AccessPoint.SECURITY_SAE;
+        } else if (result.capabilities.contains("PSK")) {
+            return AccessPoint.SECURITY_PSK;
+        } else if (result.capabilities.contains("EAP_SUITE_B_192")) {
+            return AccessPoint.SECURITY_EAP_SUITE_B;
+        } else if (result.capabilities.contains("EAP")) {
+            return AccessPoint.SECURITY_EAP;
+        } else if (result.capabilities.contains("OWE")) {
+            return AccessPoint.SECURITY_OWE;
+        }
+
+        return AccessPoint.SECURITY_NONE;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java
index 9cfdf98..ebbf5e0 100644
--- a/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/applications/ApplicationFeatureProviderImplTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.app.admin.DevicePolicyManager;
@@ -30,6 +31,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.location.LocationManager;
 import android.os.Build;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -83,6 +85,8 @@
     private IPackageManager mPackageManagerService;
     @Mock
     private DevicePolicyManager mDevicePolicyManager;
+    @Mock
+    private LocationManager mLocationManager;
 
     private ApplicationFeatureProvider mProvider;
 
@@ -95,6 +99,7 @@
 
         when(mContext.getApplicationContext()).thenReturn(mContext);
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager);
 
         mProvider = new ApplicationFeatureProviderImpl(mContext, mPackageManager,
                 mPackageManagerService, mDevicePolicyManager);
@@ -255,19 +260,27 @@
 
     @Test
     @Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class})
-    public void getKeepEnabledPackages_shouldContainDefaultPhoneAndSms() {
+    public void getKeepEnabledPackages_shouldContainDefaultPhoneAndSmsAndLocationHistory() {
         final String testDialer = "com.android.test.defaultdialer";
         final String testSms = "com.android.test.defaultsms";
+        final String testLocationHistory = "com.android.test.location.history";
+
         final String settingsIntelligence = RuntimeEnvironment.application.getString(
                 R.string.config_settingsintelligence_package_name);
         ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver"));
         ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer);
-        ReflectionHelpers.setField(mProvider, "mContext", RuntimeEnvironment.application);
+
+        // Spy the real context to mock LocationManager.
+        Context spyContext = spy(RuntimeEnvironment.application);
+        when(mLocationManager.getLocationControllerExtraPackage()).thenReturn(testLocationHistory);
+        when(spyContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager);
+
+        ReflectionHelpers.setField(mProvider, "mContext", spyContext);
 
         final Set<String> keepEnabledPackages = mProvider.getKeepEnabledPackages();
 
         final List<String> expectedPackages = Arrays.asList(testDialer, testSms,
-                settingsIntelligence);
+                settingsIntelligence, testLocationHistory);
         assertThat(keepEnabledPackages).containsExactlyElementsIn(expectedPackages);
     }
 
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java
index 8470ef9..c4b5901 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/AvailableMediaDeviceGroupControllerTest.java
@@ -119,7 +119,8 @@
         mAvailableMediaDeviceGroupController.onDeviceAdded(mPreference);
 
         assertThat(mPreferenceGroup.isVisible()).isTrue();
-        assertThat(mPreferenceGroup.findPreference(PREFERENCE_KEY_1)).isEqualTo(mPreference);
+        assertThat((Preference) mPreferenceGroup.findPreference(PREFERENCE_KEY_1))
+                .isEqualTo(mPreference);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
index c9e2644..23754a0 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
@@ -100,7 +100,8 @@
         mConnectedDeviceGroupController.onDeviceAdded(mPreference);
 
         assertThat(mPreferenceGroup.isVisible()).isTrue();
-        assertThat(mPreferenceGroup.findPreference(PREFERENCE_KEY_1)).isEqualTo(mPreference);
+        assertThat((Preference) mPreferenceGroup.findPreference(PREFERENCE_KEY_1))
+                .isEqualTo(mPreference);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java
index 38c92c3..b16a453 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java
@@ -29,6 +29,7 @@
 import android.os.Handler;
 
 import androidx.fragment.app.FragmentActivity;
+import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
@@ -122,8 +123,8 @@
                 UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
 
         assertThat(mPreference.isEnabled()).isFalse();
-        assertThat(mScreen.findPreference(mDetailsPowerRoleController.getPreferenceKey()))
-                .isEqualTo(mPreference);
+        assertThat((Preference) mScreen.findPreference(
+                mDetailsPowerRoleController.getPreferenceKey())).isEqualTo(mPreference);
     }
 
     @Test
@@ -134,7 +135,8 @@
         mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
                 UsbPort.DATA_ROLE_DEVICE);
 
-        assertThat(mScreen.findPreference(mDetailsPowerRoleController.getPreferenceKey())).isNull();
+        assertThat((Preference) mScreen.findPreference(
+                mDetailsPowerRoleController.getPreferenceKey())).isNull();
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
index fb674ab..5fb1747 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
@@ -105,7 +105,7 @@
     public void displayPref_shouldAlwaysDisplay() {
         mController.displayPreference(mScreen);
 
-        verify(mScreen.findPreference(mController.getPreferenceKey()))
+        verify((Preference) mScreen.findPreference(mController.getPreferenceKey()))
                 .setSummary(BidiFormatter.getInstance().unicodeWrap(Build.DISPLAY));
         verify(mScreen, never()).removePreference(any(Preference.class));
     }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
index 8e9a48f..d090097 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.deviceinfo;
 
+import static android.content.Context.CLIPBOARD_SERVICE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -24,6 +26,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.ClipboardManager;
 import android.content.Context;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -43,6 +46,9 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(RobolectricTestRunner.class)
 public class PhoneNumberPreferenceControllerTest {
 
@@ -146,4 +152,20 @@
     public void isSliceable_shouldBeTrue() {
         assertThat(mController.isSliceable()).isTrue();
     }
+
+    @Test
+    public void copy_shouldCopyPhoneNumberToClipboard() {
+        final List<SubscriptionInfo> list = new ArrayList<>();
+        list.add(mSubscriptionInfo);
+        when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(list);
+        final String phoneNumber = "1111111111";
+        doReturn(phoneNumber).when(mController).getFormattedPhoneNumber(mSubscriptionInfo);
+
+        mController.copy();
+
+        final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
+                CLIPBOARD_SERVICE);
+        final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
+        assertThat(phoneNumber.contentEquals(data)).isTrue();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
index d86b9a3..101ca75 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -28,33 +28,27 @@
 import android.net.Uri;
 
 import com.android.settings.slices.CustomSliceRegistry;
-import com.android.settings.slices.SettingsSliceProvider;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowContentResolver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
 
 @RunWith(RobolectricTestRunner.class)
 public class ContextualCardLoaderTest {
 
     private Context mContext;
     private ContextualCardLoader mContextualCardLoader;
-    private SettingsSliceProvider mProvider;
 
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
         mContextualCardLoader = spy(new ContextualCardLoader(mContext));
-        mProvider = new SettingsSliceProvider();
-        ShadowContentResolver.registerProviderInternal(SettingsSliceProvider.SLICE_AUTHORITY,
-                mProvider);
     }
 
     @Test
@@ -210,4 +204,4 @@
                 .build());
         return cards;
     }
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
index d6a594a..fb4747c 100644
--- a/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
@@ -218,7 +218,8 @@
         mController.displayPreference(mScreen);
         mController.onResume();
 
-        verify(mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE)).setVisible(false);
+        verify((Preference) mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE))
+                .setVisible(false);
     }
 
     @Test
@@ -242,11 +243,11 @@
         verify(mWorkCategory, times(2)).setVisible(true);
 
         // Sound preferences should explain that the profile isn't available yet.
-        verify(mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE))
+        verify((Preference) mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE))
                 .setSummary(eq(notAvailable));
-        verify(mWorkCategory.findPreference(KEY_WORK_NOTIFICATION_RINGTONE))
+        verify((Preference) mWorkCategory.findPreference(KEY_WORK_NOTIFICATION_RINGTONE))
                 .setSummary(eq(notAvailable));
-        verify(mWorkCategory.findPreference(KEY_WORK_ALARM_RINGTONE))
+        verify((Preference) mWorkCategory.findPreference(KEY_WORK_ALARM_RINGTONE))
                 .setSummary(eq(notAvailable));
     }
 
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java b/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java
index ac19dd0..31e955c 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeCopyableController.java
@@ -19,9 +19,9 @@
 import android.content.Context;
 
 import com.android.settings.core.BasePreferenceController;
-import com.android.settings.slices.CopyableSlice;
+import com.android.settings.slices.Copyable;
 
-public class FakeCopyableController extends BasePreferenceController implements CopyableSlice {
+public class FakeCopyableController extends BasePreferenceController implements Copyable {
 
     public FakeCopyableController(Context context, String preferenceKey) {
         super(context, preferenceKey);
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
index c9cdc15..343d170 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
@@ -197,9 +197,12 @@
         accessPointList.add(new AccessPoint(mContext, bundle));
         bundle.putString(KEY_SSID, "Test AP 2");
         accessPointList.add(new AccessPoint(mContext, bundle));
+
         bundle.putString(KEY_SSID, "Test AP 3");
         AccessPoint clickedAccessPoint = new AccessPoint(mContext, bundle);
+        clickedAccessPoint.generateOpenNetworkConfig();
         accessPointList.add(clickedAccessPoint);
+
         bundle.putString(KEY_SSID, "Test AP 4");
         accessPointList.add(new AccessPoint(mContext, bundle));
         when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiUtilsTest.java b/tests/robotests/src/com/android/settings/wifi/WifiUtilsTest.java
index a95624b..9de095d 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiUtilsTest.java
@@ -22,6 +22,16 @@
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
+import android.os.Bundle;
+
+import com.android.settingslib.wifi.AccessPoint;
+
+import org.robolectric.RuntimeEnvironment;
+
 @RunWith(RobolectricTestRunner.class)
 public class WifiUtilsTest {
 
@@ -44,4 +54,23 @@
         assertThat(WifiUtils.isHotspotPasswordValid(longPassword)).isFalse();
         assertThat(WifiUtils.isHotspotPasswordValid("")).isFalse();
     }
-}
+
+    @Test
+    public void getWifiConfigByAccessPoint_shouldReturnCorrectConfig() {
+        String testSSID = "WifiUtilsTest";
+        Bundle bundle = new Bundle();
+        bundle.putString("key_ssid", testSSID);
+        Context context = spy(RuntimeEnvironment.application);
+        AccessPoint accessPoint = new AccessPoint(context, bundle);
+
+        WifiConfiguration config = WifiUtils.getWifiConfig(accessPoint, null, null);
+
+        assertThat(config).isNotNull();
+        assertThat(config.SSID).isEqualTo(AccessPoint.convertToQuotedString(testSSID));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void getWifiConfigWithNullInput_ThrowIllegalArgumentException() {
+        WifiConfiguration config = WifiUtils.getWifiConfig(null, null, null);
+    }
+}
\ No newline at end of file