Merge "Adjust UI of face and fingerprint enroll intro pages" into sc-dev am: 588c13555d am: 7bc93a4d5c

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/15175824

Change-Id: I21924526a85c7d9dae60f5267d1bfd0affd9cac1
diff --git a/Android.bp b/Android.bp
index bb9db22..24fc7e8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -73,6 +73,7 @@
         "android.hardware.dumpstate-V1.0-java",
         "android.hardware.dumpstate-V1.1-java",
         "lottie",
+        "WifiTrackerLib",
     ],
 
     libs: [
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 60dbb24..d40acb0 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -82,6 +82,7 @@
     <uses-permission android:name="android.permission.OEM_UNLOCK_STATE" />
     <uses-permission android:name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE" />
     <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
+    <uses-permission android:name="android.permission.RESTART_WIFI_SUBSYSTEM" />
     <uses-permission android:name="android.permission.MANAGE_FINGERPRINT" />
     <uses-permission android:name="android.permission.USE_BIOMETRIC" />
     <uses-permission android:name="android.permission.USE_BIOMETRIC_INTERNAL" />
diff --git a/res/values-night/themes.xml b/res/values-night/themes.xml
index b61a98d..946cd91 100644
--- a/res/values-night/themes.xml
+++ b/res/values-night/themes.xml
@@ -28,10 +28,6 @@
 
     <style name="Theme.SubSettings" parent="Theme.SubSettings.Base"/>
 
-    <style name="ThemeOverlay.SwitchBar.Settings" parent="ThemeOverlay.SwitchBar.Settings.Base">
-        <item name="android:textColorPrimaryInverse">@android:color/black</item>
-    </style>
-
     <style name="Theme.AlertDialog.Base" parent="@style/Theme.AppCompat.DayNight.Dialog.Alert">
         <item name="colorAccent">@*android:color/accent_device_default_dark</item>
         <item name="android:colorError">@color/settings_dialog_colorError</item>
diff --git a/src/com/android/settings/development/tare/OWNERS b/src/com/android/settings/development/tare/OWNERS
new file mode 100644
index 0000000..46d25c8
--- /dev/null
+++ b/src/com/android/settings/development/tare/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 330055
+
+include platform/frameworks/base:/apex/jobscheduler/service/java/com/android/server/tare/OWNERS
\ No newline at end of file
diff --git a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
index c09ea02..3653baf 100644
--- a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
@@ -17,6 +17,7 @@
 package com.android.settings.deviceinfo;
 
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.Context;
@@ -29,6 +30,7 @@
 import android.text.TextUtils;
 import android.widget.Toast;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -112,7 +114,7 @@
         if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
             return false;
         }
-        if (Utils.isMonkeyRunning()) {
+        if (isUserAMonkey()) {
             return false;
         }
         // Don't enable developer options for secondary non-demo users.
@@ -245,4 +247,9 @@
                 Toast.LENGTH_LONG);
         mDevHitToast.show();
     }
+
+    @VisibleForTesting
+    protected boolean isUserAMonkey() {
+        return ActivityManager.isUserAMonkey();
+    }
 }
diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
index abf58d8..292196e 100644
--- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
@@ -133,7 +133,7 @@
     }
 
     @VisibleForTesting
-    SubscriptionInfo getSubscriptionInfo(int simSlot) {
+    protected SubscriptionInfo getSubscriptionInfo(int simSlot) {
         final List<SubscriptionInfo> subscriptionInfoList =
                 mSubscriptionManager.getActiveSubscriptionInfoList();
         if (subscriptionInfoList != null) {
@@ -147,7 +147,7 @@
     }
 
     @VisibleForTesting
-    CharSequence getFormattedPhoneNumber(SubscriptionInfo subscriptionInfo) {
+    protected CharSequence getFormattedPhoneNumber(SubscriptionInfo subscriptionInfo) {
         final String phoneNumber = DeviceInfoUtils.getBidiFormattedPhoneNumber(mContext,
                 subscriptionInfo);
         return TextUtils.isEmpty(phoneNumber) ? mContext.getString(R.string.device_info_default)
@@ -155,7 +155,7 @@
     }
 
     @VisibleForTesting
-    Preference createNewPreference(Context context) {
+    protected Preference createNewPreference(Context context) {
         return new Preference(context);
     }
 }
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index f6e7917..12497ed 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -66,6 +66,7 @@
 import com.android.settings.wifi.AddWifiNetworkPreference;
 import com.android.settings.wifi.ConfigureWifiEntryFragment;
 import com.android.settings.wifi.ConnectedWifiEntryPreference;
+import com.android.settings.wifi.LongPressWifiEntryPreference;
 import com.android.settings.wifi.WifiConfigUiBase2;
 import com.android.settings.wifi.WifiConnectListener;
 import com.android.settings.wifi.WifiDialog2;
@@ -80,7 +81,6 @@
 import com.android.settingslib.search.SearchIndexable;
 import com.android.settingslib.utils.ThreadUtils;
 import com.android.settingslib.widget.LayoutPreference;
-import com.android.settingslib.wifi.LongPressWifiEntryPreference;
 import com.android.settingslib.wifi.WifiSavedConfigUtils;
 import com.android.wifitrackerlib.WifiEntry;
 import com.android.wifitrackerlib.WifiEntry.ConnectCallback;
diff --git a/src/com/android/settings/network/PrivateDnsModeDialogPreference.java b/src/com/android/settings/network/PrivateDnsModeDialogPreference.java
index 1c3fc76..442af38 100644
--- a/src/com/android/settings/network/PrivateDnsModeDialogPreference.java
+++ b/src/com/android/settings/network/PrivateDnsModeDialogPreference.java
@@ -189,6 +189,8 @@
         if (linkInfo.isActionable()) {
             helpTextView.setText(AnnotationSpan.linkify(
                     context.getText(R.string.private_dns_help_message), linkInfo));
+        } else {
+            helpTextView.setText("");
         }
     }
 
diff --git a/src/com/android/settings/network/telephony/CellInfoUtil.java b/src/com/android/settings/network/telephony/CellInfoUtil.java
index d7d2b18..63ef159 100644
--- a/src/com/android/settings/network/telephony/CellInfoUtil.java
+++ b/src/com/android/settings/network/telephony/CellInfoUtil.java
@@ -145,6 +145,8 @@
         final CellIdentity cid = getCellIdentity(cellInfo);
         String mcc = null;
         String mnc = null;
+        CharSequence alphaLong = null;
+        CharSequence alphaShort = null;
         if (cid != null) {
             if (cid instanceof CellIdentityGsm) {
                 mcc = ((CellIdentityGsm) cid).getMccString();
@@ -162,10 +164,13 @@
                 mcc = ((CellIdentityNr) cid).getMccString();
                 mnc = ((CellIdentityNr) cid).getMncString();
             }
+
+            alphaLong = cid.getOperatorAlphaLong();
+            alphaShort = cid.getOperatorAlphaShort();
         }
         return String.format(
                 "{CellType = %s, isRegistered = %b, mcc = %s, mnc = %s, alphaL = %s, alphaS = %s}",
                 cellType, cellInfo.isRegistered(), mcc, mnc,
-                cid.getOperatorAlphaLong(), cid.getOperatorAlphaShort());
+                alphaLong, alphaShort);
     }
 }
diff --git a/src/com/android/settings/network/telephony/MobileNetworkActivity.java b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
index 20b37c1..f2be37f 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkActivity.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
@@ -36,6 +36,7 @@
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentTransaction;
+import androidx.lifecycle.Lifecycle;
 
 import com.android.internal.util.CollectionUtils;
 import com.android.settings.R;
@@ -68,6 +69,7 @@
     // Set initial value to true allows subscription information fragment to be re-created when
     // Activity re-create occur.
     private boolean mFragmentForceReload = true;
+    private boolean mPendingSubscriptionChange = false;
 
     @Override
     protected void onNewIntent(Intent intent) {
@@ -155,6 +157,10 @@
      * Implementation of ProxySubscriptionManager.OnActiveSubscriptionChangedListener
      */
     public void onChanged() {
+        if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
+            mPendingSubscriptionChange = true;
+            return;
+        }
         SubscriptionInfo info = getSubscription();
         int oldSubIndex = mCurSubscriptionId;
         updateSubscriptions(info, null);
@@ -180,6 +186,10 @@
         super.onStart();
         // updateSubscriptions doesn't need to be called, onChanged will always be called after we
         // register a listener.
+        if (mPendingSubscriptionChange) {
+            mPendingSubscriptionChange = false;
+            onChanged();
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/network/telephony/NetworkOperatorPreference.java b/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
index 3a7dc31..397bf36 100644
--- a/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
+++ b/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
@@ -36,6 +36,7 @@
 import android.telephony.CellSignalStrength;
 import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 
 import com.android.internal.telephony.OperatorInfo;
@@ -89,7 +90,8 @@
         updateCell(cellinfo, CellInfoUtil.getCellIdentity(cellinfo));
     }
 
-    private void updateCell(CellInfo cellinfo, CellIdentity cellId) {
+    @VisibleForTesting
+    protected void updateCell(CellInfo cellinfo, CellIdentity cellId) {
         mCellInfo = cellinfo;
         mCellId = cellId;
         refresh();
diff --git a/src/com/android/settings/network/telephony/NetworkSelectSettings.java b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
index 6f315be..76b6cbd 100644
--- a/src/com/android/settings/network/telephony/NetworkSelectSettings.java
+++ b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
@@ -36,6 +36,7 @@
 import android.util.Log;
 import android.view.View;
 
+import androidx.annotation.Keep;
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
@@ -56,6 +57,7 @@
 /**
  * "Choose network" settings UI for the Settings app.
  */
+@Keep
 public class NetworkSelectSettings extends DashboardFragment {
 
     private static final String TAG = "NetworkSelectSettings";
@@ -67,8 +69,7 @@
 
     private static final String PREF_KEY_NETWORK_OPERATORS = "network_operators_preference";
 
-    @VisibleForTesting
-    PreferenceCategory mPreferenceCategory;
+    private PreferenceCategory mPreferenceCategory;
     @VisibleForTesting
     NetworkOperatorPreference mSelectedPreference;
     private View mProgressHeader;
@@ -76,8 +77,7 @@
     @VisibleForTesting
     List<CellInfo> mCellInfoList;
     private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-    @VisibleForTesting
-    TelephonyManager mTelephonyManager;
+    private TelephonyManager mTelephonyManager;
     private List<String> mForbiddenPlmns;
     private boolean mShow4GForLTE = false;
     private NetworkScanHelper mNetworkScanHelper;
@@ -93,28 +93,74 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
+        onCreateInitialization();
+    }
 
-        mUseNewApi = getContext().getResources().getBoolean(
-                com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI);
+    @Keep
+    @VisibleForTesting
+    protected void onCreateInitialization() {
+        mUseNewApi = enableNewAutoSelectNetworkUI(getContext());
         mSubId = getArguments().getInt(Settings.EXTRA_SUB_ID);
 
-        mPreferenceCategory = findPreference(PREF_KEY_NETWORK_OPERATORS);
+        mPreferenceCategory = getPreferenceCategory(PREF_KEY_NETWORK_OPERATORS);
         mStatusMessagePreference = new Preference(getContext());
         mStatusMessagePreference.setSelectable(false);
         mSelectedPreference = null;
-        mTelephonyManager = getContext().getSystemService(TelephonyManager.class)
-                .createForSubscriptionId(mSubId);
+        mTelephonyManager = getTelephonyManager(getContext(), mSubId);
         mNetworkScanHelper = new NetworkScanHelper(
                 mTelephonyManager, mCallback, mNetworkScanExecutor);
-        PersistableBundle bundle = ((CarrierConfigManager) getContext().getSystemService(
-                Context.CARRIER_CONFIG_SERVICE)).getConfigForSubId(mSubId);
+        PersistableBundle bundle = getCarrierConfigManager(getContext())
+                .getConfigForSubId(mSubId);
         if (bundle != null) {
             mShow4GForLTE = bundle.getBoolean(
                     CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
         }
 
-        mMetricsFeatureProvider = FeatureFactory
-                .getFactory(getContext()).getMetricsFeatureProvider();
+        mMetricsFeatureProvider = getMetricsFeatureProvider(getContext());
+    }
+
+    @Keep
+    @VisibleForTesting
+    protected boolean enableNewAutoSelectNetworkUI(Context context) {
+        return context.getResources().getBoolean(
+                com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI);
+    }
+
+    @Keep
+    @VisibleForTesting
+    protected PreferenceCategory getPreferenceCategory(String preferenceKey) {
+        return findPreference(preferenceKey);
+    }
+
+    @Keep
+    @VisibleForTesting
+    protected TelephonyManager getTelephonyManager(Context context, int subscriptionId) {
+        return context.getSystemService(TelephonyManager.class)
+                .createForSubscriptionId(subscriptionId);
+    }
+
+    @Keep
+    @VisibleForTesting
+    protected CarrierConfigManager getCarrierConfigManager(Context context) {
+        return context.getSystemService(CarrierConfigManager.class);
+    }
+
+    @Keep
+    @VisibleForTesting
+    protected MetricsFeatureProvider getMetricsFeatureProvider(Context context) {
+        return FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+    }
+
+    @Keep
+    @VisibleForTesting
+    protected boolean isPreferenceScreenEnabled() {
+        return getPreferenceScreen().isEnabled();
+    }
+
+    @Keep
+    @VisibleForTesting
+    protected void enablePreferenceScreen(boolean enable) {
+        getPreferenceScreen().setEnabled(enable);
     }
 
     @Override
@@ -146,8 +192,9 @@
     /**
      * Update forbidden PLMNs from the USIM App
      */
+    @Keep
     @VisibleForTesting
-    void updateForbiddenPlmns() {
+    protected void updateForbiddenPlmns() {
         final String[] forbiddenPlmns = mTelephonyManager.getForbiddenPlmns();
         mForbiddenPlmns = forbiddenPlmns != null
                 ? Arrays.asList(forbiddenPlmns)
@@ -182,7 +229,7 @@
 
             setProgressBarVisible(true);
             // Disable the screen until network is manually set
-            getPreferenceScreen().setEnabled(false);
+            enablePreferenceScreen(false);
 
             mRequestIdManualNetworkSelect = getNewRequestId();
             mWaitingForNumberOfScanResults = MIN_NUMBER_OF_SCAN_REQUIRED;
@@ -222,7 +269,7 @@
                     final boolean isSucceed = (boolean) msg.obj;
                     stopNetworkQuery();
                     setProgressBarVisible(false);
-                    getPreferenceScreen().setEnabled(true);
+                    enablePreferenceScreen(true);
 
                     if (mSelectedPreference != null) {
                         mSelectedPreference.setSummary(isSucceed
@@ -233,38 +280,7 @@
                     }
                     break;
                 case EVENT_NETWORK_SCAN_RESULTS:
-                    final List<CellInfo> results = (List<CellInfo>) msg.obj;
-                    if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) {
-                        Log.d(TAG, "CellInfoList (drop): "
-                                + CellInfoUtil.cellInfoListToString(new ArrayList<>(results)));
-                        break;
-                    }
-                    mWaitingForNumberOfScanResults--;
-                    if ((mWaitingForNumberOfScanResults <= 0) && (!isResumed())) {
-                        stopNetworkQuery();
-                    }
-
-                    mCellInfoList = new ArrayList<>(results);
-                    Log.d(TAG, "CellInfoList: " + CellInfoUtil.cellInfoListToString(mCellInfoList));
-                    if (mCellInfoList != null && mCellInfoList.size() != 0) {
-                        final NetworkOperatorPreference connectedPref =
-                                updateAllPreferenceCategory();
-                        if (connectedPref != null) {
-                            // update selected preference instance into connected preference
-                            if (mSelectedPreference != null) {
-                                mSelectedPreference = connectedPref;
-                            }
-                        } else if (!getPreferenceScreen().isEnabled()) {
-                            if (connectedPref == null) {
-                                mSelectedPreference.setSummary(R.string.network_connecting);
-                            }
-                        }
-                        getPreferenceScreen().setEnabled(true);
-                    } else if (getPreferenceScreen().isEnabled()) {
-                        addMessagePreference(R.string.empty_networks_list);
-                        // keep showing progress bar, it will be stopped when error or completed
-                        setProgressBarVisible(true);
-                    }
+                    scanResultHandler((List<CellInfo>) msg.obj);
                     break;
 
                 case EVENT_NETWORK_SCAN_ERROR:
@@ -277,9 +293,9 @@
                     if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) {
                         break;
                     }
-                    if (!getPreferenceScreen().isEnabled()) {
+                    if (!isPreferenceScreenEnabled()) {
                         clearPreferenceSummary();
-                        getPreferenceScreen().setEnabled(true);
+                        enablePreferenceScreen(true);
                     } else {
                         addMessagePreference(R.string.network_query_error);
                     }
@@ -295,9 +311,9 @@
                     if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) {
                         break;
                     }
-                    if (!getPreferenceScreen().isEnabled()) {
+                    if (!isPreferenceScreenEnabled()) {
                         clearPreferenceSummary();
-                        getPreferenceScreen().setEnabled(true);
+                        enablePreferenceScreen(true);
                     } else if (mCellInfoList == null) {
                         // In case the scan timeout before getting any results
                         addMessagePreference(R.string.empty_networks_list);
@@ -327,13 +343,55 @@
                 }
             };
 
+    @Keep
+    @VisibleForTesting
+    protected void scanResultHandler(List<CellInfo> results) {
+        if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) {
+            Log.d(TAG, "CellInfoList (drop): "
+                    + CellInfoUtil.cellInfoListToString(new ArrayList<>(results)));
+            return;
+        }
+        mWaitingForNumberOfScanResults--;
+        if ((mWaitingForNumberOfScanResults <= 0) && (!isResumed())) {
+            stopNetworkQuery();
+        }
+
+        mCellInfoList = new ArrayList<>(results);
+        Log.d(TAG, "CellInfoList: " + CellInfoUtil.cellInfoListToString(mCellInfoList));
+        if (mCellInfoList != null && mCellInfoList.size() != 0) {
+            final NetworkOperatorPreference connectedPref =
+                    updateAllPreferenceCategory();
+            if (connectedPref != null) {
+                // update selected preference instance into connected preference
+                if (mSelectedPreference != null) {
+                    mSelectedPreference = connectedPref;
+                }
+            } else if (!isPreferenceScreenEnabled()) {
+                if (connectedPref == null) {
+                    mSelectedPreference.setSummary(R.string.network_connecting);
+                }
+            }
+            enablePreferenceScreen(true);
+        } else if (isPreferenceScreenEnabled()) {
+            addMessagePreference(R.string.empty_networks_list);
+            // keep showing progress bar, it will be stopped when error or completed
+            setProgressBarVisible(true);
+        }
+    }
+
+    @Keep
+    @VisibleForTesting
+    protected NetworkOperatorPreference createNetworkOperatorPreference(CellInfo cellInfo) {
+        return new NetworkOperatorPreference(getPrefContext(),
+                cellInfo, mForbiddenPlmns, mShow4GForLTE);
+    }
+
     /**
      * Update the content of network operators list.
      *
      * @return preference which shows connected
      */
-    @VisibleForTesting
-    NetworkOperatorPreference updateAllPreferenceCategory() {
+    private NetworkOperatorPreference updateAllPreferenceCategory() {
         int numberOfPreferences = mPreferenceCategory.getPreferenceCount();
 
         // remove unused preferences
@@ -361,8 +419,7 @@
             }
             if (pref == null) {
                 // add new preference
-                pref = new NetworkOperatorPreference(getPrefContext(),
-                        cellInfo, mForbiddenPlmns, mShow4GForLTE);
+                pref = createNetworkOperatorPreference(cellInfo);
                 pref.setOrder(index);
                 mPreferenceCategory.addPreference(pref);
             }
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index ee23fc3..23cdaf9 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -809,51 +809,62 @@
 
         mUserCreatingDialog = new UserCreatingDialog(getActivity());
         mUserCreatingDialog.show();
-        ThreadUtils.postOnBackgroundThread(new Runnable() {
-            @Override
-            public void run() {
-                UserInfo user;
-                String username;
+        ThreadUtils.postOnBackgroundThread(new AddUserNowImpl(userType, mAddingUserName));
+    }
 
-                synchronized (mUserLock) {
-                    username = mAddingUserName;
-                }
+    @VisibleForTesting
+    class AddUserNowImpl implements Runnable{
+        int mUserType;
+        String mImplAddUserName;
 
-                // Could take a few seconds
-                if (userType == USER_TYPE_USER) {
-                    user = mUserManager.createUser(username, 0);
-                } else {
-                    user = mUserManager.createRestrictedProfile(username);
-                }
+        AddUserNowImpl(final int userType, final String addUserName) {
+            mUserType = userType;
+            mImplAddUserName = addUserName;
+        }
 
-                synchronized (mUserLock) {
-                    if (user == null) {
-                        mAddingUser = false;
-                        mPendingUserIcon = null;
-                        mPendingUserName = null;
-                        ThreadUtils.postOnMainThread(() -> onUserCreationFailed());
-                        return;
-                    }
+        @Override
+        public void run() {
+            UserInfo user;
+            String username;
 
-                    Drawable newUserIcon = mPendingUserIcon;
-                    if (newUserIcon == null) {
-                        newUserIcon = UserIcons.getDefaultUserIcon(getResources(), user.id, false);
-                    }
-                    mUserManager.setUserIcon(user.id, UserIcons.convertToBitmap(newUserIcon));
+            synchronized (mUserLock) {
+                username = mImplAddUserName;
+            }
 
-                    if (userType == USER_TYPE_USER) {
-                        mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
-                    }
+            // Could take a few seconds
+            if (mUserType == USER_TYPE_USER) {
+                user = mUserManager.createUser(username, 0);
+            } else {
+                user = mUserManager.createRestrictedProfile(username);
+            }
 
-                    mHandler.sendMessage(mHandler.obtainMessage(
-                            MESSAGE_USER_CREATED, user.id, user.serialNumber));
-
+            synchronized (mUserLock) {
+                if (user == null) {
+                    mAddingUser = false;
                     mPendingUserIcon = null;
                     mPendingUserName = null;
+                    ThreadUtils.postOnMainThread(() -> onUserCreationFailed());
+                    return;
                 }
+
+                Drawable newUserIcon = mPendingUserIcon;
+                if (newUserIcon == null) {
+                    newUserIcon = UserIcons.getDefaultUserIcon(getResources(), user.id, false);
+                }
+                mUserManager.setUserIcon(user.id, UserIcons.convertToBitmap(newUserIcon));
+
+                if (mUserType == USER_TYPE_USER) {
+                    mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
+                }
+
+                mHandler.sendMessage(mHandler.obtainMessage(
+                        MESSAGE_USER_CREATED, user.id, user.serialNumber));
+
+                mPendingUserIcon = null;
+                mPendingUserName = null;
             }
-        });
-    }
+        }
+    };
 
     /**
      * Erase the current user (guest) and switch to another user.
diff --git a/src/com/android/settings/wifi/ConnectedWifiEntryPreference.java b/src/com/android/settings/wifi/ConnectedWifiEntryPreference.java
index afba0d8..1c069246 100644
--- a/src/com/android/settings/wifi/ConnectedWifiEntryPreference.java
+++ b/src/com/android/settings/wifi/ConnectedWifiEntryPreference.java
@@ -22,7 +22,6 @@
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settingslib.R;
-import com.android.settingslib.wifi.LongPressWifiEntryPreference;
 import com.android.wifitrackerlib.WifiEntry;
 
 /**
diff --git a/src/com/android/settings/wifi/LongPressWifiEntryPreference.java b/src/com/android/settings/wifi/LongPressWifiEntryPreference.java
new file mode 100644
index 0000000..bee92cf
--- /dev/null
+++ b/src/com/android/settings/wifi/LongPressWifiEntryPreference.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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 android.content.Context;
+
+import androidx.fragment.app.Fragment;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.wifitrackerlib.WifiEntry;
+
+/**
+ * WifiEntryPreference that can be long pressed.
+ */
+public class LongPressWifiEntryPreference extends WifiEntryPreference {
+
+    private final Fragment mFragment;
+
+    public LongPressWifiEntryPreference(Context context, WifiEntry wifiEntry, Fragment fragment) {
+        super(context, wifiEntry);
+        mFragment = fragment;
+    }
+
+    @Override
+    public void onBindViewHolder(final PreferenceViewHolder view) {
+        super.onBindViewHolder(view);
+        if (mFragment != null) {
+            view.itemView.setOnCreateContextMenuListener(mFragment);
+            view.itemView.setTag(this);
+            view.itemView.setLongClickable(true);
+        }
+    }
+}
diff --git a/src/com/android/settings/wifi/WifiConnectionPreferenceController.java b/src/com/android/settings/wifi/WifiConnectionPreferenceController.java
index 3b2669c..47eb587 100644
--- a/src/com/android/settings/wifi/WifiConnectionPreferenceController.java
+++ b/src/com/android/settings/wifi/WifiConnectionPreferenceController.java
@@ -37,7 +37,6 @@
 import com.android.settings.wifi.details2.WifiNetworkDetailsFragment2;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.wifi.WifiEntryPreference;
 import com.android.wifitrackerlib.WifiEntry;
 import com.android.wifitrackerlib.WifiPickerTracker;
 
diff --git a/src/com/android/settings/wifi/WifiDialog2.java b/src/com/android/settings/wifi/WifiDialog2.java
index dc546f3..52f3e74 100644
--- a/src/com/android/settings/wifi/WifiDialog2.java
+++ b/src/com/android/settings/wifi/WifiDialog2.java
@@ -21,6 +21,9 @@
 import android.content.DialogInterface;
 import android.os.Bundle;
 import android.view.View;
+import android.view.Window;
+import android.view.WindowInsets;
+import android.view.WindowManager;
 import android.widget.Button;
 import android.widget.ImageButton;
 import android.widget.TextView;
@@ -108,6 +111,8 @@
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
+        setWindowsOverlay();
+
         mView = getLayoutInflater().inflate(R.layout.wifi_dialog, /* root */ null);
         setView(mView);
         mController = new WifiConfigController2(this, mView, mWifiEntry, mMode);
@@ -126,6 +131,16 @@
         }
     }
 
+    private void setWindowsOverlay() {
+        final Window window = getWindow();
+        final WindowManager.LayoutParams lp = window.getAttributes();
+        window.setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+        lp.setFitInsetsTypes(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
+        lp.setFitInsetsSides(WindowInsets.Side.all());
+        lp.setFitInsetsIgnoringVisibility(true);
+        window.setAttributes(lp);
+    }
+
     @Override
     protected void onStart() {
         final ImageButton ssidScannerButton = findViewById(R.id.ssid_scanner_button);
diff --git a/src/com/android/settings/wifi/WifiEntryPreference.java b/src/com/android/settings/wifi/WifiEntryPreference.java
new file mode 100644
index 0000000..3dfeada
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiEntryPreference.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2021 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 android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.StateListDrawable;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settingslib.R;
+import com.android.settingslib.Utils;
+import com.android.settingslib.wifi.WifiUtils;
+import com.android.wifitrackerlib.WifiEntry;
+
+/**
+ * Preference to display a WifiEntry in a wifi picker.
+ */
+public class WifiEntryPreference extends Preference implements WifiEntry.WifiEntryCallback,
+        View.OnClickListener {
+
+    private static final int[] STATE_SECURED = {
+            R.attr.state_encrypted
+    };
+
+    private static final int[] FRICTION_ATTRS = {
+            R.attr.wifi_friction
+    };
+
+    // These values must be kept within [WifiEntry.WIFI_LEVEL_MIN, WifiEntry.WIFI_LEVEL_MAX]
+    private static final int[] WIFI_CONNECTION_STRENGTH = {
+            R.string.accessibility_no_wifi,
+            R.string.accessibility_wifi_one_bar,
+            R.string.accessibility_wifi_two_bars,
+            R.string.accessibility_wifi_three_bars,
+            R.string.accessibility_wifi_signal_full
+    };
+
+    // StateListDrawable to display secured lock / metered "$" icon
+    @Nullable private final StateListDrawable mFrictionSld;
+    private final IconInjector mIconInjector;
+    private WifiEntry mWifiEntry;
+    private int mLevel = -1;
+    private boolean mShowX; // Shows the Wi-Fi signl icon of Pie+x when it's true.
+    private CharSequence mContentDescription;
+    private OnButtonClickListener mOnButtonClickListener;
+
+    public WifiEntryPreference(@NonNull Context context, @NonNull WifiEntry wifiEntry) {
+        this(context, wifiEntry, new IconInjector(context));
+    }
+
+    @VisibleForTesting
+    WifiEntryPreference(@NonNull Context context, @NonNull WifiEntry wifiEntry,
+            @NonNull IconInjector iconInjector) {
+        super(context);
+
+        setLayoutResource(R.layout.preference_access_point);
+        setWidgetLayoutResource(R.layout.access_point_friction_widget);
+        mFrictionSld = getFrictionStateListDrawable();
+        mWifiEntry = wifiEntry;
+        mWifiEntry.setListener(this);
+        mIconInjector = iconInjector;
+        refresh();
+    }
+
+    public WifiEntry getWifiEntry() {
+        return mWifiEntry;
+    }
+
+    @Override
+    public void onBindViewHolder(final PreferenceViewHolder view) {
+        super.onBindViewHolder(view);
+        final Drawable drawable = getIcon();
+        if (drawable != null) {
+            drawable.setLevel(mLevel);
+        }
+
+        view.itemView.setContentDescription(mContentDescription);
+
+        // Turn off divider
+        view.findViewById(R.id.two_target_divider).setVisibility(View.INVISIBLE);
+
+        // Enable the icon button when the help string in this WifiEntry is not null.
+        final ImageButton imageButton = (ImageButton) view.findViewById(R.id.icon_button);
+        final ImageView frictionImageView = (ImageView) view.findViewById(
+                R.id.friction_icon);
+        if (mWifiEntry.getHelpUriString() != null
+                && mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_DISCONNECTED) {
+            final Drawable drawablehelp = getDrawable(R.drawable.ic_help);
+            drawablehelp.setTintList(
+                    Utils.getColorAttr(getContext(), android.R.attr.colorControlNormal));
+            ((ImageView) imageButton).setImageDrawable(drawablehelp);
+            imageButton.setVisibility(View.VISIBLE);
+            imageButton.setOnClickListener(this);
+            imageButton.setContentDescription(
+                    getContext().getText(R.string.help_label));
+
+            if (frictionImageView != null) {
+                frictionImageView.setVisibility(View.GONE);
+            }
+        } else {
+            imageButton.setVisibility(View.GONE);
+
+            if (frictionImageView != null) {
+                frictionImageView.setVisibility(View.VISIBLE);
+                bindFrictionImage(frictionImageView);
+            }
+        }
+    }
+
+    /**
+     * Updates the title and summary; may indirectly call notifyChanged().
+     */
+    public void refresh() {
+        setTitle(mWifiEntry.getTitle());
+        final int level = mWifiEntry.getLevel();
+        final boolean showX = mWifiEntry.shouldShowXLevelIcon();
+        if (level != mLevel || showX != mShowX) {
+            mLevel = level;
+            mShowX = showX;
+            updateIcon(mShowX, mLevel);
+            notifyChanged();
+        }
+
+        setSummary(mWifiEntry.getSummary(false /* concise */));
+        mContentDescription = buildContentDescription();
+    }
+
+    /**
+     * Indicates the state of the WifiEntry has changed and clients may retrieve updates through
+     * the WifiEntry getter methods.
+     */
+    public void onUpdated() {
+        // TODO(b/70983952): Fill this method in
+        refresh();
+    }
+
+    /**
+     * Result of the connect request indicated by the WifiEntry.CONNECT_STATUS constants.
+     */
+    public void onConnectResult(int status) {
+        // TODO(b/70983952): Fill this method in
+    }
+
+    /**
+     * Result of the disconnect request indicated by the WifiEntry.DISCONNECT_STATUS constants.
+     */
+    public void onDisconnectResult(int status) {
+        // TODO(b/70983952): Fill this method in
+    }
+
+    /**
+     * Result of the forget request indicated by the WifiEntry.FORGET_STATUS constants.
+     */
+    public void onForgetResult(int status) {
+        // TODO(b/70983952): Fill this method in
+    }
+
+    /**
+     * Result of the sign-in request indecated by the WifiEntry.SIGNIN_STATUS constants
+     */
+    public void onSignInResult(int status) {
+        // TODO(b/70983952): Fill this method in
+    }
+
+    protected int getIconColorAttr() {
+        final boolean accent = (mWifiEntry.hasInternetAccess()
+                && mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED);
+        return accent ? android.R.attr.colorAccent : android.R.attr.colorControlNormal;
+    }
+
+    private void updateIcon(boolean showX, int level) {
+        if (level == -1) {
+            setIcon(null);
+            return;
+        }
+
+        final Drawable drawable = mIconInjector.getIcon(showX, level);
+        if (drawable != null) {
+            drawable.setTint(Utils.getColorAttrDefaultColor(getContext(), getIconColorAttr()));
+            setIcon(drawable);
+        } else {
+            setIcon(null);
+        }
+    }
+
+    @Nullable
+    private StateListDrawable getFrictionStateListDrawable() {
+        TypedArray frictionSld;
+        try {
+            frictionSld = getContext().getTheme().obtainStyledAttributes(FRICTION_ATTRS);
+        } catch (Resources.NotFoundException e) {
+            // Fallback for platforms that do not need friction icon resources.
+            frictionSld = null;
+        }
+        return frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null;
+    }
+
+    /**
+     * Binds the friction icon drawable using a StateListDrawable.
+     *
+     * <p>Friction icons will be rebound when notifyChange() is called, and therefore
+     * do not need to be managed in refresh()</p>.
+     */
+    private void bindFrictionImage(ImageView frictionImageView) {
+        if (frictionImageView == null || mFrictionSld == null) {
+            return;
+        }
+        if ((mWifiEntry.getSecurity() != WifiEntry.SECURITY_NONE)
+                && (mWifiEntry.getSecurity() != WifiEntry.SECURITY_OWE)) {
+            mFrictionSld.setState(STATE_SECURED);
+        }
+        frictionImageView.setImageDrawable(mFrictionSld.getCurrent());
+    }
+
+    /**
+     * Helper method to generate content description string.
+     */
+    @VisibleForTesting
+    CharSequence buildContentDescription() {
+        final Context context = getContext();
+
+        CharSequence contentDescription = getTitle();
+        final CharSequence summary = getSummary();
+        if (!TextUtils.isEmpty(summary)) {
+            contentDescription = TextUtils.concat(contentDescription, ",", summary);
+        }
+        int level = mWifiEntry.getLevel();
+        if (level >= 0 && level < WIFI_CONNECTION_STRENGTH.length) {
+            contentDescription = TextUtils.concat(contentDescription, ",",
+                    context.getString(WIFI_CONNECTION_STRENGTH[level]));
+        }
+        return TextUtils.concat(contentDescription, ",",
+                mWifiEntry.getSecurity() == WifiEntry.SECURITY_NONE
+                        ? context.getString(R.string.accessibility_wifi_security_type_none)
+                        : context.getString(R.string.accessibility_wifi_security_type_secured));
+    }
+
+
+    static class IconInjector {
+        private final Context mContext;
+
+        IconInjector(Context context) {
+            mContext = context;
+        }
+
+        public Drawable getIcon(boolean showX, int level) {
+            return mContext.getDrawable(WifiUtils.getInternetIconResource(level, showX));
+        }
+    }
+
+    /**
+     * Set listeners, who want to listen the button client event.
+     */
+    public void setOnButtonClickListener(OnButtonClickListener listener) {
+        mOnButtonClickListener = listener;
+        notifyChanged();
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (view.getId() == R.id.icon_button) {
+            if (mOnButtonClickListener != null) {
+                mOnButtonClickListener.onButtonClick(this);
+            }
+        }
+    }
+
+    /**
+     * Callback to inform the caller that the icon button is clicked.
+     */
+    public interface OnButtonClickListener {
+
+        /**
+         * Register to listen the button click event.
+         */
+        void onButtonClick(WifiEntryPreference preference);
+    }
+
+    private Drawable getDrawable(@DrawableRes int iconResId) {
+        Drawable buttonIcon = null;
+
+        try {
+            buttonIcon = getContext().getDrawable(iconResId);
+        } catch (Resources.NotFoundException exception) {
+            // Do nothing
+        }
+        return buttonIcon;
+    }
+
+}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 59f6504..0680b33 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -74,7 +74,6 @@
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.search.Indexable;
 import com.android.settingslib.search.SearchIndexable;
-import com.android.settingslib.wifi.LongPressWifiEntryPreference;
 import com.android.settingslib.wifi.WifiSavedConfigUtils;
 import com.android.wifitrackerlib.WifiEntry;
 import com.android.wifitrackerlib.WifiEntry.ConnectCallback;
diff --git a/src/com/android/settings/wifi/calling/WifiCallingSettings.java b/src/com/android/settings/wifi/calling/WifiCallingSettings.java
index 86e7e8d..783ad3e 100644
--- a/src/com/android/settings/wifi/calling/WifiCallingSettings.java
+++ b/src/com/android/settings/wifi/calling/WifiCallingSettings.java
@@ -17,6 +17,7 @@
 package com.android.settings.wifi.calling;
 
 import android.app.settings.SettingsEnums;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.provider.Settings;
@@ -29,12 +30,14 @@
 
 import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentPagerAdapter;
 
 import com.android.internal.util.CollectionUtils;
 import com.android.settings.R;
 import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.network.ActiveSubscriptionsListener;
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settings.network.ims.WifiCallingQueryImsState;
 import com.android.settings.search.actionbar.SearchMenuController;
@@ -42,6 +45,9 @@
 import com.android.settings.widget.RtlCompatibleViewPager;
 import com.android.settings.widget.SlidingTabLayout;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -50,7 +56,10 @@
  */
 public class WifiCallingSettings extends InstrumentedFragment implements HelpResourceProvider {
     private static final String TAG = "WifiCallingSettings";
+    private int mConstructionSubId;
     private List<SubscriptionInfo> mSil;
+    private ActiveSubscriptionsListener mSubscriptionChangeListener;
+    private static final int [] EMPTY_SUB_ID_LIST = new int[0];
 
     //UI objects
     private RtlCompatibleViewPager mViewPager;
@@ -95,16 +104,26 @@
         return view;
     }
 
+    private int getConstructionSubId(Bundle bundle) {
+        int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+        Intent intent = getActivity().getIntent();
+        if (intent != null) {
+            subId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
+                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        }
+        if ((subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) && (bundle != null)) {
+            subId = bundle.getInt(Settings.EXTRA_SUB_ID,
+                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        }
+        return subId;
+    }
+
     private void maybeSetViewForSubId() {
         if (mSil == null) {
             return;
         }
-        final Intent intent = getActivity().getIntent();
-        if (intent == null) {
-            return;
-        }
-        final int subId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
-                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        int subId = mConstructionSubId;
         if (SubscriptionManager.isValidSubscriptionId(subId)) {
             for (SubscriptionInfo subInfo : mSil) {
                 if (subId == subInfo.getSubscriptionId()) {
@@ -117,11 +136,15 @@
 
     @Override
     public void onCreate(Bundle icicle) {
+        mConstructionSubId = getConstructionSubId(icicle);
         super.onCreate(icicle);
+        Log.d(TAG, "SubId=" + mConstructionSubId);
 
-        // TODO: besides in onCreate, we should also update subList when SIM / Sub status
-        // changes.
-        updateSubList();
+        if (mConstructionSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            // Only config Wfc if it's enabled by platform.
+            mSubscriptionChangeListener = getSubscriptionChangeListener(getContext());
+        }
+        mSil = updateSubList();
     }
 
     @Override
@@ -135,6 +158,26 @@
         }
 
         updateTitleForCurrentSub();
+
+        if (mSubscriptionChangeListener != null) {
+            mSubscriptionChangeListener.start();
+        }
+    }
+
+    @Override
+    public void onStop() {
+        if (mSubscriptionChangeListener != null) {
+            mSubscriptionChangeListener.stop();
+        }
+
+        super.onStop();
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        // keep subscription ID for recreation
+        outState.putInt(Settings.EXTRA_SUB_ID, mConstructionSubId);
     }
 
     @Override
@@ -160,11 +203,11 @@
 
         @Override
         public Fragment getItem(int position) {
-            Log.d(TAG, "Adapter getItem " + position);
+            int subId = mSil.get(position).getSubscriptionId();
+            Log.d(TAG, "Adapter getItem " + position + " for subId=" + subId);
             final Bundle args = new Bundle();
             args.putBoolean(SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR, false);
-            args.putInt(WifiCallingSettingsForSub.FRAGMENT_BUNDLE_SUBID,
-                    mSil.get(position).getSubscriptionId());
+            args.putInt(WifiCallingSettingsForSub.FRAGMENT_BUNDLE_SUBID, subId);
             final WifiCallingSettingsForSub fragment = new WifiCallingSettingsForSub();
             fragment.setArguments(args);
 
@@ -190,22 +233,27 @@
         }
     }
 
-    private void updateSubList() {
-        mSil = SubscriptionUtil.getActiveSubscriptions(
-                getContext().getSystemService(SubscriptionManager.class));
+    @VisibleForTesting
+    protected List<SubscriptionInfo> getSelectableSubscriptions(Context context) {
+        return SubscriptionUtil.getSelectableSubscriptionInfoList(context);
+    }
 
-        // Only config Wfc if it's enabled by platform.
-        if (mSil == null) {
-            return;
+    private List<SubscriptionInfo> updateSubList() {
+        List<SubscriptionInfo> subInfoList = getSelectableSubscriptions(getContext());
+
+        if (subInfoList == null) {
+            return Collections.emptyList();
         }
-        for (int i = 0; i < mSil.size(); ) {
-            final SubscriptionInfo info = mSil.get(i);
-            if (!queryImsState(info.getSubscriptionId()).isWifiCallingProvisioned()) {
-                mSil.remove(i);
-            } else {
-                i++;
-            }
+        List<SubscriptionInfo> selectedList = new ArrayList<SubscriptionInfo>();
+        for (SubscriptionInfo subInfo : subInfoList) {
+            int subId = subInfo.getSubscriptionId();
+            try {
+                if (queryImsState(subId).isWifiCallingProvisioned()) {
+                    selectedList.add(subInfo);
+                }
+            } finally {}
         }
+        return selectedList;
     }
 
     private void updateTitleForCurrentSub() {
@@ -218,7 +266,78 @@
     }
 
     @VisibleForTesting
-    WifiCallingQueryImsState queryImsState(int subId) {
+    protected WifiCallingQueryImsState queryImsState(int subId) {
         return new WifiCallingQueryImsState(getContext(), subId);
     }
+
+    @VisibleForTesting
+    protected ActiveSubscriptionsListener getSubscriptionChangeListener(Context context) {
+        return new ActiveSubscriptionsListener(context.getMainLooper(), context) {
+            public void onChanged() {
+                onSubscriptionChange(context);
+            }
+        };
+    }
+
+    protected void onSubscriptionChange(Context context) {
+        if (mSubscriptionChangeListener == null) {
+            return;
+        }
+        int [] previousSubIdList = subscriptionIdList(mSil);
+        List<SubscriptionInfo> updateList = updateSubList();
+        int [] currentSubIdList = subscriptionIdList(updateList);
+
+        if (currentSubIdList.length > 0) {
+            // only keep fragment when any provisioned subscription is available
+            if (previousSubIdList.length == 0) {
+                // initial loading of list
+                mSil = updateList;
+                return;
+            }
+            if (previousSubIdList.length == currentSubIdList.length) {
+                // same number of subscriptions
+                if ( (!containsSubId(previousSubIdList, mConstructionSubId))
+                        // original request not yet appears in list
+                        || containsSubId(currentSubIdList, mConstructionSubId) )
+                        // original request appears in list
+                {
+                    mSil = updateList;
+                    return;
+                }
+            }
+        }
+        Log.d(TAG, "Closed subId=" + mConstructionSubId
+                + " due to subscription change: " + Arrays.toString(previousSubIdList)
+                + " -> " + Arrays.toString(currentSubIdList));
+
+        // close this fragment when no provisioned subscriptions available
+        if (mSubscriptionChangeListener != null) {
+            mSubscriptionChangeListener.stop();
+            mSubscriptionChangeListener = null;
+        }
+
+        // close this fragment
+        finish();
+    }
+
+    protected void finish() {
+        FragmentActivity activity = getActivity();
+        if (activity == null) return;
+        if (getFragmentManager().getBackStackEntryCount() > 0) {
+            getFragmentManager().popBackStack();
+        } else {
+            activity.finish();
+        }
+    }
+
+    protected int [] subscriptionIdList(List<SubscriptionInfo> subInfoList) {
+        return (subInfoList == null) ? EMPTY_SUB_ID_LIST :
+                subInfoList.stream().mapToInt(subInfo -> (subInfo == null) ?
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID : subInfo.getSubscriptionId())
+                .toArray();
+    }
+
+    protected boolean containsSubId(int [] subIdArray, int subIdLookUp) {
+        return Arrays.stream(subIdArray).anyMatch(subId -> (subId == subIdLookUp));
+    }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
index a017fac..61d2eb8 100644
--- a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
@@ -41,7 +41,7 @@
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.wifi.AddNetworkFragment;
-import com.android.settingslib.wifi.WifiEntryPreference;
+import com.android.settings.wifi.WifiEntryPreference;
 import com.android.wifitrackerlib.SavedNetworkTracker;
 import com.android.wifitrackerlib.WifiEntry;
 
diff --git a/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsPreferenceController2.java b/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsPreferenceController2.java
index 1d1c801..f0841f4 100644
--- a/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsPreferenceController2.java
+++ b/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsPreferenceController2.java
@@ -25,7 +25,7 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.core.BasePreferenceController;
-import com.android.settingslib.wifi.WifiEntryPreference;
+import com.android.settings.wifi.WifiEntryPreference;
 import com.android.wifitrackerlib.WifiEntry;
 
 import java.util.ArrayList;
diff --git a/tests/componenttests/src/com/android/settings/display/darkmode/DarkThemeScheduleComponentTest.java b/tests/componenttests/src/com/android/settings/display/darkmode/DarkThemeScheduleComponentTest.java
new file mode 100644
index 0000000..e21f37e
--- /dev/null
+++ b/tests/componenttests/src/com/android/settings/display/darkmode/DarkThemeScheduleComponentTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2021 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.display.darkmode;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Instrumentation;
+import android.app.TimePickerDialog;
+import android.app.UiModeManager;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.provider.Settings;
+import android.util.Log;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.lifecycle.Stage;
+
+import com.android.settings.testutils.CommonUtils;
+import com.android.settings.testutils.UiUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.LocalTime;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DarkThemeScheduleComponentTest {
+    private static final int DIALOG_START_TIME = 0;
+    private static final int DIALOG_END_TIME = 1;
+    /** The identifier for the positive button. */
+    private static final int BUTTON_POSITIVE = -1;
+    public final String TAG = this.getClass().getName();
+    private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
+
+    @Rule
+    public ActivityScenarioRule<com.android.settings.Settings.DarkThemeSettingsActivity> rule =
+            new ActivityScenarioRule<>(
+                    new Intent(
+                            Settings.ACTION_DARK_THEME_SETTINGS).setFlags(
+                            Intent.FLAG_ACTIVITY_NEW_TASK));
+    private UiModeManager mUiModeManager;
+
+    @Before
+    public void setUp() {
+        mUiModeManager = mInstrumentation.getTargetContext().getSystemService(UiModeManager.class);
+        if (mUiModeManager.getNightMode() != UiModeManager.MODE_NIGHT_NO) {
+            mUiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
+        }
+    }
+
+    private void test_step_for_custom_time(int startTimeDiff, int endTimeDiff) {
+
+        ActivityScenario scenario = rule.getScenario();
+        scenario.onActivity(activity -> {
+            mUiModeManager.setNightMode(UiModeManager.MODE_NIGHT_CUSTOM);
+            Fragment f =
+                    ((FragmentActivity) activity).getSupportFragmentManager().getFragments().get(0);
+            DarkModeSettingsFragment fragment = (DarkModeSettingsFragment) f;
+
+            setCustomTime(fragment, DIALOG_START_TIME, LocalTime.now().plusMinutes(startTimeDiff));
+            setCustomTime(fragment, DIALOG_END_TIME, LocalTime.now().plusMinutes(endTimeDiff));
+
+            // The night mode need to reopen the screen to trigger UI change after mode change.
+            CommonUtils.reopenScreen();
+        });
+
+        // Relaunch the scenario to make sure UI apply new mode.
+        scenario.onActivity(activity -> {
+            Log.d(TAG, "Activity Recreated!");
+            UiUtils.waitForActivitiesInStage(2000, Stage.RESUMED);
+        });
+    }
+
+    @Test
+    public void test_dark_mode_in_custom_time() {
+        test_step_for_custom_time(-1, 11);
+        assertThat(checkNightMode(true)).isTrue();
+    }
+
+    @Test
+    public void test_dark_mode_after_custom_time() {
+        test_step_for_custom_time(-11, -1);
+        assertThat(checkNightMode(false)).isTrue();
+    }
+
+    @Test
+    public void test_dark_mode_before_custom_time() {
+        test_step_for_custom_time(2, 20);
+        assertThat(checkNightMode(false)).isTrue();
+    }
+
+    /**
+     * Sets custom time for night mode.
+     *
+     * @param fragment The DarkModeSettingsFragment.
+     * @param dialogId Dialog id for start time or end time.
+     * @param time     The time to be set.
+     */
+    private void setCustomTime(DarkModeSettingsFragment fragment, int dialogId, LocalTime time) {
+        Log.d(TAG, "Start to set custom time " + (dialogId == DIALOG_START_TIME ? "StartTime"
+                : "EndTime") + " to " + time.getHour() + ":" + time.getMinute());
+        TimePickerDialog startTimeDialog = (TimePickerDialog) fragment.onCreateDialog(dialogId);
+        startTimeDialog.updateTime(time.getHour(), time.getMinute());
+        startTimeDialog.onClick(startTimeDialog, BUTTON_POSITIVE);
+    }
+
+    private boolean checkNightMode(boolean isNightMode) {
+        int mask = (isNightMode ? Configuration.UI_MODE_NIGHT_YES : Configuration.UI_MODE_NIGHT_NO);
+        int mode = mInstrumentation.getTargetContext().getResources().getConfiguration().uiMode;
+        return (mode & mask) != 0;
+    }
+
+    @After
+    public void tearDown() {
+        Log.d(TAG, "tearDown.");
+        if (mUiModeManager.getNightMode() != UiModeManager.MODE_NIGHT_NO) {
+            mUiModeManager.setNightMode(UiModeManager.MODE_NIGHT_NO);
+        }
+    }
+}
diff --git a/tests/componenttests/src/com/android/settings/homepage/HomepageComponentTest.java b/tests/componenttests/src/com/android/settings/homepage/HomepageComponentTest.java
new file mode 100644
index 0000000..cf64749
--- /dev/null
+++ b/tests/componenttests/src/com/android/settings/homepage/HomepageComponentTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2021 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.homepage;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assert_;
+
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.provider.Settings;
+import android.util.Log;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class HomepageComponentTest {
+    public final String TAG = this.getClass().getSimpleName();
+
+    private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
+
+    @Test
+    public void test_launch_all_settings_in_home()
+            throws ClassNotFoundException {
+
+        List<Intent> launchIntents = ImmutableList.of(
+
+                // Wifi
+                // Implemented in WifiSettings2ActivityTest
+
+                // Connected devices
+                new Intent(Settings.ACTION_BLUETOOTH_SETTINGS),
+
+                // Applications
+                new Intent(Settings.ACTION_AUTO_ROTATE_SETTINGS),
+
+                // Notifications
+                new Intent(Settings.ACTION_NOTIFICATION_SETTINGS),
+
+                // Display
+                new Intent(Settings.ACTION_DISPLAY_SETTINGS),
+
+                // Battery
+                // Implemented in fuelgauge.batterysaver
+
+                // Storage
+                new Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS),
+
+                // Sound
+                new Intent(Settings.ACTION_SOUND_SETTINGS),
+
+                // Display
+                new Intent(Settings.ACTION_DISPLAY_SETTINGS),
+
+                // Wallpaper
+                new Intent(mInstrumentation.getTargetContext(), Class.forName(
+                        "com.android.settings.wallpaper.WallpaperSuggestionActivity")),
+
+                // A11y
+                new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS),
+
+                // Security
+                new Intent(Settings.ACTION_SECURITY_SETTINGS),
+
+                // Privacy
+                new Intent(Settings.ACTION_PRIVACY_SETTINGS),
+
+                // Location
+                new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS),
+
+                // Emergency ? EmergencyDashboardFragment
+                // TODO: find out launch method
+
+                // Password & Account
+                new Intent(Settings.ACTION_SYNC_SETTINGS),
+
+                // Digital wellbeing
+                // Use IA link
+                new Intent().setComponent(
+                        new ComponentName(
+                                "com.google.android.apps.wellbeing",
+                                "com.google.android.apps.wellbeing.settings"
+                                        + ".TopLevelSettingsActivity")),
+
+                // Google
+                // Use IA link
+                new Intent().setComponent(
+                        new ComponentName(
+                                "com.google.android.gms",
+                                "com.google.android.gms.app.settings.GoogleSettingsIALink")),
+
+                // System ?
+                // TODO: find out launch method.
+
+                // About
+                new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS)
+
+        );
+
+        for (Intent intent : launchIntents) {
+            Log.d(TAG, "Start to launch intent " + intent.getAction());
+            try {
+                mInstrumentation.getTargetContext()
+                        .startActivity(intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+            } catch (Exception e) {
+                Log.e(TAG, "Launch with exception. " + e.toString());
+                assert_().fail();
+            }
+            // Launch success without exception.
+            assertThat(Boolean.TRUE).isTrue();
+        }
+    }
+}
diff --git a/tests/componenttests/src/com/android/settings/network/AirplaneModePreferenceControllerComponentTest.java b/tests/componenttests/src/com/android/settings/network/AirplaneModePreferenceControllerComponentTest.java
new file mode 100644
index 0000000..27e67e5
--- /dev/null
+++ b/tests/componenttests/src/com/android/settings/network/AirplaneModePreferenceControllerComponentTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Instrumentation;
+import android.provider.Settings;
+import android.provider.SettingsSlicesContract;
+import android.util.Log;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.settings.testutils.UiUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class AirplaneModePreferenceControllerComponentTest {
+    // Airplane on off status
+    private static final int ON = 1;
+    private static final int OFF = 0;
+    public final String TAG = this.getClass().getName();
+    private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
+    private boolean mOriginAirplaneModeIsOn;
+
+    @Before
+    public void setUp() {
+        // Make sure origin airplane mode is OFF.
+        mOriginAirplaneModeIsOn = is_airplane_mode_on();
+        if (mOriginAirplaneModeIsOn) {
+            Log.d(TAG, "Origin airplane mode is on, turn it off.");
+            Settings.Global.putInt(mInstrumentation.getTargetContext().getContentResolver(),
+                    Settings.Global.AIRPLANE_MODE_ON, OFF);
+        }
+    }
+
+    /**
+     * Tests on/off airplane mode repeatedly.
+     * Previously, a bug describe that crash issue if user on off airplane mode repeatedly.
+     * This case try to switch on & off airplane mode for 10 times to check crash issue.
+     */
+    @Test
+    public void test_on_off_airplane_mode_multiple_times() {
+        AirplaneModePreferenceController controller =
+                new AirplaneModePreferenceController(mInstrumentation.getTargetContext(),
+                        SettingsSlicesContract.KEY_AIRPLANE_MODE);
+
+        for (int i = 0; i < 10; ++i) {
+            Log.d(TAG, "Test #" + (i + 1));
+            controller.setChecked(true);
+            assertThat(UiUtils.waitUntilCondition(1000,
+                    () -> is_airplane_mode_on())).isTrue();
+
+            controller.setChecked(false);
+            assertThat(UiUtils.waitUntilCondition(1000,
+                    () -> !is_airplane_mode_on())).isTrue();
+        }
+
+    }
+
+    private boolean is_airplane_mode_on() {
+        return Settings.System.getInt(
+                mInstrumentation.getTargetContext().getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, OFF) != 0;
+    }
+
+    @After
+    public void tearDown() {
+        if (is_airplane_mode_on() != mOriginAirplaneModeIsOn) {
+            Settings.Global.putInt(mInstrumentation.getTargetContext().getContentResolver(),
+                    Settings.Global.AIRPLANE_MODE_ON, (
+                            mOriginAirplaneModeIsOn ? ON : OFF));
+        }
+    }
+}
diff --git a/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java b/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java
new file mode 100644
index 0000000..e35cd0c
--- /dev/null
+++ b/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import static com.android.settings.testutils.CommonUtils.set_wifi_enabled;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.net.wifi.WifiManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.settings.testutils.CommonUtils;
+import com.android.settings.testutils.UiUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.concurrent.ExecutionException;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class MobileDataPreferenceControllerComponentTest {
+    public static final int TIMEOUT = 2000;
+    private static final int SUBSCRIPTION_ID = 2;
+    public final String TAG = this.getClass().getName();
+    private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
+    private final WifiManager mWifiManager =
+            (WifiManager) mInstrumentation.getTargetContext().getSystemService(
+                    Context.WIFI_SERVICE);
+    private final TelephonyManager mTelephonyManager =
+            (TelephonyManager) mInstrumentation.getTargetContext().getSystemService(
+                    Context.TELEPHONY_SERVICE);
+
+    @Rule
+    public ActivityScenarioRule<com.android.settings.network.telephony.MobileNetworkActivity>
+            rule = new ActivityScenarioRule<>(
+            new Intent(android.provider.Settings.ACTION_DATA_ROAMING_SETTINGS)
+                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+    private boolean mOriginDataEnabled;
+    private boolean mOriginWifiEnabled;
+
+    @Before
+    public void setUp() {
+        mOriginWifiEnabled = mWifiManager.isWifiEnabled();
+        Log.d(TAG, "setup! mTelephonyManager = " + mTelephonyManager);
+        // Disable wifi
+        set_wifi_enabled(false);
+
+        // Enable mobile data
+        mOriginDataEnabled = mTelephonyManager.isDataEnabled();
+        if (!mOriginDataEnabled) {
+            mTelephonyManager.enableDataConnectivity();
+        }
+    }
+
+    /**
+     * Tests the mobile network is disabled.
+     * Precondition:
+     * Disabled wifi, and enabled mobile network.
+     * Steps:
+     * 1. Launch mobile data page.
+     * 2. Turn off mobile data from switch.
+     * [Check]
+     * - Mobile data is turned off via TelephonyManager.
+     * - Open socket connection https://www.google.net and check the connection failed.
+     */
+    @Test
+    public void test_disable_mobile_network() {
+        ActivityScenario scenario = rule.getScenario();
+        scenario.onActivity(activity -> {
+            try {
+                URL url = new URL("https://www.google.net");
+                MobileDataPreferenceController controller = new MobileDataPreferenceController(
+                        mInstrumentation.getTargetContext(), "mobile_data");
+                FragmentManager manager = ((FragmentActivity) activity).getSupportFragmentManager();
+                controller.init(manager, SUBSCRIPTION_ID);
+                Log.d(TAG, "Start to click ");
+                controller.setChecked(false);
+                Log.d(TAG, "Set Checked, wait for fully close.");
+
+                // Assert the configuration is set.
+                assertThat(UiUtils.waitUntilCondition(10000,
+                        () -> !mTelephonyManager.isDataEnabled())).isTrue();
+
+                // Assert the network is not connectable.
+                assertThat(UiUtils.waitUntilCondition(3000,
+                        () -> {
+                            try {
+                                return CommonUtils.connectToURL(url);
+                            } catch (ExecutionException e) {
+                                e.printStackTrace();
+                            } catch (InterruptedException e) {
+                                e.printStackTrace();
+                            }
+                            return false;
+                        })).isFalse();
+            } catch (IOException e) {
+
+            }
+        });
+    }
+
+    @After
+    public void tearDown() {
+        // Restore wifi status wifi
+        set_wifi_enabled(mOriginWifiEnabled);
+
+        // Restore mobile data status
+        if (mOriginDataEnabled != mTelephonyManager.isDataEnabled()) {
+            if (mOriginDataEnabled) {
+                mTelephonyManager.enableDataConnectivity();
+            } else {
+                mTelephonyManager.disableDataConnectivity();
+            }
+        }
+    }
+}
diff --git a/tests/componenttests/src/com/android/settings/testutils/AdbUtils.java b/tests/componenttests/src/com/android/settings/testutils/AdbUtils.java
index 08eb47a..b6e3c52 100644
--- a/tests/componenttests/src/com/android/settings/testutils/AdbUtils.java
+++ b/tests/componenttests/src/com/android/settings/testutils/AdbUtils.java
@@ -17,46 +17,63 @@
 package com.android.settings.testutils;
 
 import android.os.ParcelFileDescriptor;
-import android.text.TextUtils;
-import android.util.Log;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import java.io.BufferedReader;
+import java.io.IOException;
 import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
-import java.util.Optional;
+import java.util.stream.Collectors;
 
 public class AdbUtils {
+    public static String getCallerClassName() {
+        StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
+        for (int i = 1; i < stElements.length; i++) {
+            StackTraceElement ste = stElements[i];
+            if (!ste.getClassName().equals(new Object() {
+            }.getClass().getEnclosingClass().getName()) && ste.getClassName().indexOf(
+                    "java.lang.Thread") != 0) {
+                return ste.getClassName();
+            }
+        }
+        return null;
+    }
+
     public static boolean checkStringInAdbCommandOutput(String logTag, String command,
             String prefix, String target, int timeoutInMillis) throws Exception {
         long start = System.nanoTime();
+
         //Sometimes the change do no reflect in adn output immediately, so need a wait and poll here
         while (System.nanoTime() - start < (timeoutInMillis * 1000000)) {
-            try (ParcelFileDescriptor.AutoCloseInputStream in =
-                         new ParcelFileDescriptor.AutoCloseInputStream(
-                                 InstrumentationRegistry.getInstrumentation()
-                                         .getUiAutomation()
-                                         .executeShellCommand(command))) {
-                try (BufferedReader br =
-                             new BufferedReader(
-                                     new InputStreamReader(in, StandardCharsets.UTF_8))) {
-                    Optional<String> resultOptional = br.lines().filter(line -> {
-                        Log.d(logTag, line);
-                        return TextUtils.isEmpty(prefix) || line.contains(prefix);
-                    }).findFirst();
-                    String result = resultOptional.get();
-                    if (result.contains(target)) {
-                        return true;
-                    } else {
-                        Thread.sleep(100);
-                    }
-                }
-            } catch (Exception e) {
-                throw e;
+            String result = shell(command);
+            if (result.contains(prefix == null ? "" : prefix)
+                    && result.contains(target == null ? "" : target)) {
+                return true;
+            } else {
+                Thread.sleep(100);
             }
         }
 
         return false;
     }
+
+    public static String shell(String shellCommand) {
+        String returnValue = "";
+        try (ParcelFileDescriptor.AutoCloseInputStream in =
+                     new ParcelFileDescriptor.AutoCloseInputStream(
+                             InstrumentationRegistry.getInstrumentation()
+                                     .getUiAutomation()
+                                     .executeShellCommand(shellCommand))) {
+            try (BufferedReader br =
+                         new BufferedReader(
+                                 new InputStreamReader(in, StandardCharsets.UTF_8))) {
+                returnValue = br.lines().collect(Collectors.joining());
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return returnValue;
+    }
 }
diff --git a/tests/componenttests/src/com/android/settings/testutils/CommonUtils.java b/tests/componenttests/src/com/android/settings/testutils/CommonUtils.java
index 02a83fc..dce377d 100644
--- a/tests/componenttests/src/com/android/settings/testutils/CommonUtils.java
+++ b/tests/componenttests/src/com/android/settings/testutils/CommonUtils.java
@@ -17,8 +17,14 @@
 package com.android.settings.testutils;
 
 import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Context;
 import android.graphics.Bitmap;
+import android.net.wifi.WifiManager;
 import android.os.Environment;
+import android.os.PowerManager;
+import android.os.StrictMode;
+import android.os.SystemClock;
 import android.util.Log;
 import android.view.View;
 
@@ -31,11 +37,20 @@
 import java.io.InputStreamReader;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.util.concurrent.ExecutionException;
 
 import javax.net.ssl.HttpsURLConnection;
 
 public class CommonUtils {
     private static final String TAG = CommonUtils.class.getSimpleName();
+    private static final Instrumentation sInstrumentation =
+            InstrumentationRegistry.getInstrumentation();
+    private static final WifiManager sWifiManager =
+            (WifiManager) sInstrumentation.getTargetContext().getSystemService(
+                    Context.WIFI_SERVICE);
+    private static final PowerManager sPowerManager =
+            (PowerManager) sInstrumentation.getTargetContext().getSystemService(
+                    Context.POWER_SERVICE);
 
     public static void takeScreenshot(Activity activity) {
         long now = System.currentTimeMillis();
@@ -65,7 +80,9 @@
         }
     }
 
-    public static boolean connectToURL(URL url) {
+    public static boolean connectToURL(URL url) throws ExecutionException, InterruptedException {
+        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+        StrictMode.setThreadPolicy(policy);
         HttpURLConnection connection = null;
         try {
             connection = (HttpsURLConnection) url.openConnection();
@@ -81,17 +98,19 @@
                 while (null != (line = reader.readLine())) {
                     response.append(line);
                 }
+                Log.d(TAG, "Connection success! " + response.toString());
                 return true;
             }
         } catch (Exception e) {
-            Log.d(TAG, e.getMessage());
+            Log.e(TAG, e.toString());
+            e.printStackTrace();
             return false;
         } finally {
             if (null != connection) {
                 connection.disconnect();
             }
         }
-
+        Log.d(TAG, "End, return false.");
         return false;
     }
 
@@ -106,4 +125,42 @@
         return InstrumentationRegistry.getInstrumentation().getTargetContext().getResources()
                 .getIdentifier(name, "id", Constants.SETTINGS_PACKAGE_NAME);
     }
+
+    public static void reopenScreen() {
+        sPowerManager.goToSleep(SystemClock.uptimeMillis());
+        // According to local test, we need to sleep to wait it fully processed.
+        // 1000 ms is a good value to sleep, otherwise it might cause keyDispatchingTimedOut.
+        try {
+            Thread.sleep(1000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        UiUtils.waitUntilCondition(1000, () -> !sPowerManager.isInteractive());
+        sPowerManager.wakeUp(SystemClock.uptimeMillis());
+        UiUtils.waitUntilCondition(1000, () -> sPowerManager.isInteractive());
+
+        // After power on screen, need to unlock and goto home page.
+        AdbUtils.shell("input keyevent KEYCODE_MENU");
+    }
+
+    /**
+     * Sets wifi status to given enable / disable via ADB command.
+     */
+    public static void set_wifi_enabled(boolean enable) {
+        final int timeoutMsec = 10000;
+        Log.d(TAG, "Set wifi status to " + enable);
+        if (sWifiManager.isWifiEnabled() != enable) {
+            AdbUtils.shell("svc wifi " + (enable ? "enable" : "disable"));
+            if (!UiUtils.waitUntilCondition(timeoutMsec,
+                    () -> sWifiManager.isWifiEnabled() == enable)) {
+                Log.e(TAG, "Cannot set wifi to " + (enable ? "enabl" : "disable") + ", timeout "
+                        + timeoutMsec + " (ms).");
+                Log.e(TAG, "See logcat for more information.");
+            }
+            Log.d(TAG, "After configuration wifi status = " + sWifiManager.isWifiEnabled());
+        } else {
+            Log.d(TAG, "Wifi is enable is already " + enable + ", no need to change.");
+        }
+
+    }
 }
diff --git a/tests/componenttests/src/com/android/settings/testutils/UiUtils.java b/tests/componenttests/src/com/android/settings/testutils/UiUtils.java
index 481a7b2..d58dced 100644
--- a/tests/componenttests/src/com/android/settings/testutils/UiUtils.java
+++ b/tests/componenttests/src/com/android/settings/testutils/UiUtils.java
@@ -32,7 +32,7 @@
 public class UiUtils {
     private static final String TAG = "UI_UTILS";
 
-    public static void waitUntilCondition(long timeoutInMillis, Supplier<Boolean> condition) {
+    public static boolean waitUntilCondition(long timeoutInMillis, Supplier<Boolean> condition) {
         long start = System.nanoTime();
         while (System.nanoTime() - start < (timeoutInMillis * 1000000)) {
             try {
@@ -40,17 +40,14 @@
                 //findViewById when the view hierarchy is still rendering, it sometimes encounter
                 //null views that may exist few milliseconds before, and causes a NPE.
                 if (condition.get()) {
-                    return;
+                    return true;
                 }
             } catch (NullPointerException e) {
                 e.printStackTrace();
             }
         }
-        if (System.nanoTime() - start >= (timeoutInMillis * 1000000)) {
-            Log.w(TAG, "Condition not match and timeout for waiting " + timeoutInMillis + "(ms).");
-        } else {
-            Log.d(TAG, "Condition matched.");
-        }
+        Log.w(TAG, "Condition not match and timeout for waiting " + timeoutInMillis + "(ms).");
+        return false;
     }
 
     public static boolean waitForActivitiesInStage(long timeoutInMillis, Stage stage) {
diff --git a/tests/componenttests/src/com/android/settings/users/UserSettingsComponentTest.java b/tests/componenttests/src/com/android/settings/users/UserSettingsComponentTest.java
new file mode 100644
index 0000000..b0735fb
--- /dev/null
+++ b/tests/componenttests/src/com/android/settings/users/UserSettingsComponentTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2021 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.users;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.os.UserManager;
+import android.util.Log;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.settings.Settings;
+import com.android.settings.testutils.AdbUtils;
+import com.android.settings.testutils.UiUtils;
+import com.android.settingslib.utils.ThreadUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Random;
+import java.util.stream.Collectors;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class UserSettingsComponentTest {
+    public static final int TIMEOUT = 2000;
+    private static final int USER_TYPE_RESTRICTED_PROFILE = 2;
+    public final String TAG = this.getClass().getName();
+    private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
+    private final ArrayList<Integer> mOriginUserIds = new ArrayList<>();
+    private final UserManager mUserManager =
+            (UserManager) mInstrumentation.getTargetContext().getSystemService("user");
+    @Rule
+    public ActivityScenarioRule<Settings.UserSettingsActivity>
+            rule = new ActivityScenarioRule<>(
+            new Intent(android.provider.Settings.ACTION_USER_SETTINGS)
+                    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+
+    @Before
+    public void setUp() {
+        for (UserInfo info : mUserManager.getUsers()) {
+            mOriginUserIds.add(info.id);
+        }
+
+        // Enable multiple user switch.
+        if (!mUserManager.isUserSwitcherEnabled()) {
+            android.provider.Settings.Global.putInt(
+                    mInstrumentation.getTargetContext().getContentResolver(),
+                    android.provider.Settings.Global.USER_SWITCHER_ENABLED, 1);
+        }
+    }
+
+    @Test
+    public void test_new_user_on_multiple_setting_page() throws IOException {
+        String randomUserName = gendrate_random_name(10);
+        ActivityScenario scenario = rule.getScenario();
+        scenario.onActivity(activity -> {
+            Fragment f =
+                    ((FragmentActivity) activity).getSupportFragmentManager().getFragments().get(0);
+            UserSettings us = (UserSettings) f;
+            Log.d(TAG, "Start to add user :" + randomUserName);
+            ThreadUtils.postOnBackgroundThread(
+                    us.new AddUserNowImpl(USER_TYPE_RESTRICTED_PROFILE, randomUserName));
+        });
+
+        assertThat(
+                UiUtils.waitUntilCondition(5000, () -> mUserManager.getAliveUsers().stream().filter(
+                        (user) -> user.name.equals(
+                                randomUserName)).findFirst().isPresent())).isTrue();
+    }
+
+    @After
+    public void tearDown() {
+        int retryNumber = 5;
+        for (int i = 0; i < retryNumber; ++i) {
+            int currentUsersCount = mUserManager.getUserCount();
+            if (currentUsersCount == mOriginUserIds.size()) {
+                break;
+            } else if (i != 0) {
+                Log.d(TAG, "[tearDown] User not fully removed. Retry #" + (i = 1) + " of total "
+                        + mOriginUserIds.size());
+            }
+
+            for (UserInfo info : mUserManager.getUsers()) {
+                if (mOriginUserIds.contains(info.id)) {
+                    continue;
+                }
+                Log.d(TAG, "[tearDown] Clean up user {" + info.id + "}:" + info.name);
+                try {
+                    AdbUtils.shell("pm remove-user " + info.id);
+                } catch (Exception e) {
+                    Log.w(TAG, "[tearDown] Error occurs while removing user. " + e.toString());
+                }
+            }
+        }
+    }
+
+    private String gendrate_random_name(int length) {
+        String seed = "abcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQSTUVWXYZ";
+        Random r1 = new Random();
+        String result = "";
+        for (int i = 0; i < length; ++i) {
+            result = result + seed.charAt(r1.nextInt(seed.length() - 1));
+        }
+        if (mUserManager.getAliveUsers().stream().map(user -> user.name).collect(
+                Collectors.toList()).contains(result)) {
+            Log.d(TAG, "Name repeated! add padding 'rpt' in the end of name.");
+            result += "rpt";
+        }
+        return result;
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/development/tare/OWNERS b/tests/robotests/src/com/android/settings/development/tare/OWNERS
new file mode 100644
index 0000000..46d25c8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/tare/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 330055
+
+include platform/frameworks/base:/apex/jobscheduler/service/java/com/android/server/tare/OWNERS
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java
deleted file mode 100644
index 87dcb33..0000000
--- a/tests/robotests/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2018 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.deviceinfo;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-
-import android.accounts.Account;
-import android.content.Context;
-
-import com.android.settings.testutils.FakeFeatureFactory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-@RunWith(RobolectricTestRunner.class)
-public class BrandedAccountPreferenceControllerTest {
-
-    private Context mContext;
-    private FakeFeatureFactory fakeFeatureFactory;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        fakeFeatureFactory = FakeFeatureFactory.setupForTest();
-
-    }
-
-    @Test
-    public void isAvailable_configOn_noAccount_off() {
-        final BrandedAccountPreferenceController controller =
-                new BrandedAccountPreferenceController(mContext, "test_key");
-        assertThat(controller.isAvailable()).isFalse();
-    }
-
-    @Test
-    public void isAvailable_accountIsAvailable_on() {
-        when(fakeFeatureFactory.mAccountFeatureProvider.getAccounts(any(Context.class)))
-                .thenReturn(new Account[]{new Account("fake@account.foo", "fake.reallyfake")});
-
-        final BrandedAccountPreferenceController controller =
-                new BrandedAccountPreferenceController(mContext, "test_key");
-
-        assertThat(controller.isAvailable()).isTrue();
-    }
-
-    @Test
-    @Config(qualifiers = "mcc999")
-    public void isAvailable_configOff_hasAccount_off() {
-        when(fakeFeatureFactory.mAccountFeatureProvider.getAccounts(any(Context.class)))
-                .thenReturn(new Account[]{new Account("fake@account.foo", "fake.reallyfake")});
-
-        final BrandedAccountPreferenceController controller =
-                new BrandedAccountPreferenceController(mContext, "test_key");
-
-        assertThat(controller.isAvailable()).isFalse();
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java
deleted file mode 100644
index d705b64..0000000
--- a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.deviceinfo.hardwareinfo;
-
-import static android.content.Context.CLIPBOARD_SERVICE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ClipboardManager;
-import android.content.Context;
-import android.os.SystemProperties;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class HardwareRevisionPreferenceControllerTest {
-
-    private Context mContext;
-    private HardwareRevisionPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mController = new HardwareRevisionPreferenceController(mContext,
-                "hardware_info_device_revision");
-    }
-
-    @Test
-    public void copy_shouldCopyHardwareRevisionToClipboard() {
-        final String fakeHardwareVer = "FakeVer1.0";
-        SystemProperties.set("ro.boot.hardware.revision", fakeHardwareVer);
-
-        mController.copy();
-
-        final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
-                CLIPBOARD_SERVICE);
-        final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
-
-        assertThat(data.toString()).isEqualTo(fakeHardwareVer);
-    }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java
deleted file mode 100644
index 2106b54..0000000
--- a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.deviceinfo.hardwareinfo;
-
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.content.Context;
-import android.os.Build;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class SerialNumberPreferenceControllerTest {
-
-    private Context mContext;
-    private SerialNumberPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        mContext = RuntimeEnvironment.application;
-        mController = new SerialNumberPreferenceController(mContext, "test");
-    }
-
-    @Test
-    public void copy_shouldPutSerialNumberToClipBoard() {
-        mController.copy();
-
-        final ClipboardManager clipboardManager = mContext.getSystemService(ClipboardManager.class);
-        final ClipData data = clipboardManager.getPrimaryClip();
-
-        assertThat(data.getItemAt(0).getText().toString()).contains(Build.getSerial());
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
index 47cd87c..7592c35 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
@@ -64,10 +64,10 @@
 import com.android.settings.testutils.shadow.ShadowFragment;
 import com.android.settings.wifi.AddWifiNetworkPreference;
 import com.android.settings.wifi.ConnectedWifiEntryPreference;
+import com.android.settings.wifi.LongPressWifiEntryPreference;
 import com.android.settings.wifi.WifiConfigController2;
 import com.android.settings.wifi.WifiDialog2;
 import com.android.settingslib.widget.LayoutPreference;
-import com.android.settingslib.wifi.LongPressWifiEntryPreference;
 import com.android.wifitrackerlib.WifiEntry;
 import com.android.wifitrackerlib.WifiPickerTracker;
 
diff --git a/tests/robotests/src/com/android/settings/network/WifiConnectionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/WifiConnectionPreferenceControllerTest.java
index ea957c3..038a292 100644
--- a/tests/robotests/src/com/android/settings/network/WifiConnectionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/WifiConnectionPreferenceControllerTest.java
@@ -34,8 +34,8 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.wifi.WifiConnectionPreferenceController;
+import com.android.settings.wifi.WifiEntryPreference;
 import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.wifi.WifiEntryPreference;
 import com.android.wifitrackerlib.WifiEntry;
 import com.android.wifitrackerlib.WifiPickerTracker;
 
diff --git a/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java b/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java
deleted file mode 100644
index 6bee38f..0000000
--- a/tests/robotests/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.network.telephony;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.telephony.CellIdentityLte;
-import android.telephony.CellIdentityWcdma;
-import android.telephony.CellInfoLte;
-import android.telephony.CellInfoWcdma;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceManager;
-
-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 java.util.Arrays;
-
-@RunWith(RobolectricTestRunner.class)
-public class NetworkSelectSettingsTest {
-    private static final int SUB_ID = 2;
-    private static final String CARRIER_NAME1 = "CarrierName1";
-    private static final String CARRIER_NAME2 = "CarrierName2";
-
-    @Mock
-    private TelephonyManager mTelephonyManager;
-    @Mock
-    private SubscriptionManager mSubscriptionManager;
-    @Mock
-    private CellInfoWcdma mCellInfo1;
-    @Mock
-    private CellIdentityWcdma mCellId1;
-    @Mock
-    private CellInfoLte mCellInfo2;
-    @Mock
-    private CellIdentityLte mCellId2;
-    @Mock
-    private PreferenceManager mPreferenceManager;
-    @Mock
-    private SharedPreferences mSharedPreferences;
-    private Context mContext;
-
-    private PreferenceCategory mPreferenceCategory;
-
-    private NetworkSelectSettings mNetworkSelectSettings;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mContext = spy(RuntimeEnvironment.application);
-        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
-        when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
-        when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager);
-
-        when(mCellInfo1.isRegistered()).thenReturn(true);
-        when(mCellInfo1.getCellIdentity()).thenReturn(mCellId1);
-        when(mCellId1.getOperatorAlphaLong()).thenReturn(CARRIER_NAME1);
-        when(mCellInfo2.isRegistered()).thenReturn(false);
-        when(mCellInfo2.getCellIdentity()).thenReturn(mCellId2);
-        when(mCellId2.getOperatorAlphaLong()).thenReturn(CARRIER_NAME2);
-
-        doReturn(mSharedPreferences).when(mPreferenceManager).getSharedPreferences();
-        mPreferenceCategory = spy(new PreferenceCategory(mContext));
-        doReturn(mPreferenceManager).when(mPreferenceCategory).getPreferenceManager();
-
-        mNetworkSelectSettings = spy(new NetworkSelectSettings());
-        doReturn(mContext).when(mNetworkSelectSettings).getContext();
-        doReturn(mPreferenceManager).when(mNetworkSelectSettings).getPreferenceManager();
-        doReturn(mContext).when(mPreferenceManager).getContext();
-
-        mNetworkSelectSettings.mTelephonyManager = mTelephonyManager;
-        mNetworkSelectSettings.mPreferenceCategory = mPreferenceCategory;
-        mNetworkSelectSettings.mCellInfoList = Arrays.asList(mCellInfo1, mCellInfo2);
-    }
-
-    @Test
-    public void updateAllPreferenceCategory_correctOrderingPreference() {
-        mNetworkSelectSettings.updateAllPreferenceCategory();
-
-        assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2);
-        final NetworkOperatorPreference preference =
-                (NetworkOperatorPreference) mPreferenceCategory.getPreference(1);
-        assertThat(preference.getOperatorName()).isEqualTo(mCellId2.getOperatorAlphaLong());
-    }
-
-    @Test
-    public void updateForbiddenPlmns_forbiddenPlmnsNull_shouldNotCrash() {
-        when(mTelephonyManager.getForbiddenPlmns()).thenReturn(null);
-
-        // Should not Crash
-        mNetworkSelectSettings.updateForbiddenPlmns();
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiEntryPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/WifiEntryPreferenceTest.java
new file mode 100644
index 0000000..ce1b46a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/WifiEntryPreferenceTest.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2021 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.Mockito.when;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settingslib.R;
+import com.android.wifitrackerlib.WifiEntry;
+
+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 java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class WifiEntryPreferenceTest {
+
+    private Context mContext;
+
+    @Mock
+    private WifiEntry mMockWifiEntry;
+    @Mock
+    private WifiEntryPreference.IconInjector mMockIconInjector;
+
+    @Mock
+    private Drawable mMockDrawable0;
+    @Mock
+    private Drawable mMockDrawable1;
+    @Mock
+    private Drawable mMockDrawable2;
+    @Mock
+    private Drawable mMockDrawable3;
+    @Mock
+    private Drawable mMockDrawable4;
+
+    @Mock
+    private Drawable mMockShowXDrawable0;
+    @Mock
+    private Drawable mMockShowXDrawable1;
+    @Mock
+    private Drawable mMockShowXDrawable2;
+    @Mock
+    private Drawable mMockShowXDrawable3;
+    @Mock
+    private Drawable mMockShowXDrawable4;
+
+    private static final String MOCK_TITLE = "title";
+    private static final String MOCK_SUMMARY = "summary";
+    private static final String FAKE_URI_STRING = "fakeuri";
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+
+        MockitoAnnotations.initMocks(this);
+
+        when(mMockWifiEntry.getTitle()).thenReturn(MOCK_TITLE);
+        when(mMockWifiEntry.getSummary(false /* concise */)).thenReturn(MOCK_SUMMARY);
+
+        when(mMockIconInjector.getIcon(false /* showX */, 0)).thenReturn(mMockDrawable0);
+        when(mMockIconInjector.getIcon(false /* showX */, 1)).thenReturn(mMockDrawable1);
+        when(mMockIconInjector.getIcon(false /* showX */, 2)).thenReturn(mMockDrawable2);
+        when(mMockIconInjector.getIcon(false /* showX */, 3)).thenReturn(mMockDrawable3);
+        when(mMockIconInjector.getIcon(false /* showX */, 4)).thenReturn(mMockDrawable4);
+
+        when(mMockIconInjector.getIcon(true /* showX */, 0))
+                .thenReturn(mMockShowXDrawable0);
+        when(mMockIconInjector.getIcon(true /* showX */, 1))
+                .thenReturn(mMockShowXDrawable1);
+        when(mMockIconInjector.getIcon(true /* showX */, 2))
+                .thenReturn(mMockShowXDrawable2);
+        when(mMockIconInjector.getIcon(true /* showX */, 3))
+                .thenReturn(mMockShowXDrawable3);
+        when(mMockIconInjector.getIcon(true /* showX */, 4))
+                .thenReturn(mMockShowXDrawable4);
+    }
+
+    @Test
+    public void constructor_shouldSetWifiEntryTitleAndSummary() {
+        final WifiEntryPreference pref =
+                new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+
+        assertThat(pref.getTitle()).isEqualTo(MOCK_TITLE);
+        assertThat(pref.getSummary()).isEqualTo(MOCK_SUMMARY);
+        assertThat(false).isTrue();
+    }
+
+    @Test
+    public void constructor_shouldSetIcon() {
+        when(mMockWifiEntry.getLevel()).thenReturn(0);
+
+        final WifiEntryPreference pref =
+                new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+
+        assertThat(pref.getIcon()).isEqualTo(mMockDrawable0);
+    }
+
+    @Test
+    public void titleChanged_refresh_shouldUpdateTitle() {
+        final WifiEntryPreference pref =
+                new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+        final String updatedTitle = "updated title";
+        when(mMockWifiEntry.getTitle()).thenReturn(updatedTitle);
+
+        pref.refresh();
+
+        assertThat(pref.getTitle()).isEqualTo(updatedTitle);
+    }
+
+    @Test
+    public void summaryChanged_refresh_shouldUpdateSummary() {
+        final WifiEntryPreference pref =
+                new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+        final String updatedSummary = "updated summary";
+        when(mMockWifiEntry.getSummary(false /* concise */)).thenReturn(updatedSummary);
+
+        pref.refresh();
+
+        assertThat(pref.getSummary()).isEqualTo(updatedSummary);
+    }
+
+    @Test
+    public void levelChanged_refresh_shouldUpdateLevelIcon() {
+        final List<Drawable> iconList = new ArrayList<>();
+        final WifiEntryPreference pref =
+                new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+
+        when(mMockWifiEntry.getLevel()).thenReturn(0);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+        when(mMockWifiEntry.getLevel()).thenReturn(1);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+        when(mMockWifiEntry.getLevel()).thenReturn(2);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+        when(mMockWifiEntry.getLevel()).thenReturn(3);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+        when(mMockWifiEntry.getLevel()).thenReturn(4);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+        when(mMockWifiEntry.getLevel()).thenReturn(-1);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+
+        assertThat(iconList).containsExactly(mMockDrawable0, mMockDrawable1,
+                mMockDrawable2, mMockDrawable3, mMockDrawable4, null);
+    }
+
+    @Test
+    public void levelChanged_showXWifiRefresh_shouldUpdateLevelIcon() {
+        final List<Drawable> iconList = new ArrayList<>();
+        when(mMockWifiEntry.shouldShowXLevelIcon()).thenReturn(true);
+        final WifiEntryPreference pref =
+                new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+
+        when(mMockWifiEntry.getLevel()).thenReturn(0);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+        when(mMockWifiEntry.getLevel()).thenReturn(1);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+        when(mMockWifiEntry.getLevel()).thenReturn(2);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+        when(mMockWifiEntry.getLevel()).thenReturn(3);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+        when(mMockWifiEntry.getLevel()).thenReturn(4);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+        when(mMockWifiEntry.getLevel()).thenReturn(-1);
+        pref.refresh();
+        iconList.add(pref.getIcon());
+
+        assertThat(iconList).containsExactly(mMockShowXDrawable0, mMockShowXDrawable1,
+                mMockShowXDrawable2, mMockShowXDrawable3, mMockShowXDrawable4, null);
+    }
+
+    @Test
+    public void notNull_whenGetHelpUriString_shouldSetImageButtonVisible() {
+        when(mMockWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING);
+        final WifiEntryPreference pref =
+                new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        final View view = inflater.inflate(pref.getLayoutResource(), new LinearLayout(mContext),
+                false);
+        final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
+
+        pref.onBindViewHolder(holder);
+
+        assertThat(view.findViewById(R.id.icon_button).getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void helpButton_whenGetHelpUriStringNotNull_shouldSetCorrectContentDescription() {
+        when(mMockWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING);
+        final WifiEntryPreference pref =
+                new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        final View view = inflater.inflate(pref.getLayoutResource(), new LinearLayout(mContext),
+                false);
+        final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
+
+        pref.onBindViewHolder(holder);
+
+        assertThat(view.findViewById(R.id.icon_button).getContentDescription()).isEqualTo(
+                mContext.getString(R.string.help_label));
+    }
+
+    @Test
+    public void subscriptionEntry_shouldSetImageButtonGone() {
+        when(mMockWifiEntry.isSubscription()).thenReturn(true);
+        final WifiEntryPreference pref =
+                new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        final View view = inflater.inflate(pref.getLayoutResource(), new LinearLayout(mContext),
+                false);
+        final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
+
+        pref.onBindViewHolder(holder);
+
+        assertThat(view.findViewById(R.id.icon_button).getVisibility()).isEqualTo(View.GONE);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
index 1f5abd3..c124c59 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
@@ -57,7 +57,6 @@
 import com.android.settings.datausage.DataUsagePreference;
 import com.android.settings.testutils.shadow.ShadowDataUsageUtils;
 import com.android.settings.testutils.shadow.ShadowFragment;
-import com.android.settingslib.wifi.LongPressWifiEntryPreference;
 import com.android.wifitrackerlib.WifiEntry;
 import com.android.wifitrackerlib.WifiPickerTracker;
 
diff --git a/tests/robotests/src/com/android/settings/wifi/dpp/WifiNetworkListFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/dpp/WifiNetworkListFragmentTest.java
index 70f2b1a..e78f1c1 100644
--- a/tests/robotests/src/com/android/settings/wifi/dpp/WifiNetworkListFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/dpp/WifiNetworkListFragmentTest.java
@@ -36,7 +36,7 @@
 import androidx.preference.PreferenceCategory;
 import androidx.test.InstrumentationRegistry;
 
-import com.android.settingslib.wifi.WifiEntryPreference;
+import com.android.settings.wifi.WifiEntryPreference;
 import com.android.wifitrackerlib.SavedNetworkTracker;
 import com.android.wifitrackerlib.WifiEntry;
 
diff --git a/tests/robotests/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsPreferenceController2Test.java
index 7b7a3b1..0d10223 100644
--- a/tests/robotests/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/savedaccesspoints2/SavedAccessPointsPreferenceController2Test.java
@@ -35,7 +35,7 @@
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceScreen;
 
-import com.android.settingslib.wifi.WifiEntryPreference;
+import com.android.settings.wifi.WifiEntryPreference;
 import com.android.wifitrackerlib.WifiEntry;
 
 import org.junit.Before;
diff --git a/tests/unit/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java
new file mode 100644
index 0000000..6e78d05
--- /dev/null
+++ b/tests/unit/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2018 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.deviceinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.content.res.Resources;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.ResourcesUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class BrandedAccountPreferenceControllerTest {
+
+    @Mock
+    private Resources mResources;
+    private Context mContext;
+    private FakeFeatureFactory mFakeFeatureFactory;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getResources()).thenReturn(mResources);
+        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+
+    }
+
+    @Test
+    public void isAvailable_configOn_noAccount_off() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool",
+                "config_show_branded_account_in_device_info");
+        when(mResources.getBoolean(boolId)).thenReturn(true);
+
+        final BrandedAccountPreferenceController controller =
+                new BrandedAccountPreferenceController(mContext, "test_key");
+        assertThat(controller.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isAvailable_accountIsAvailable_on() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool",
+                "config_show_branded_account_in_device_info");
+        when(mResources.getBoolean(boolId)).thenReturn(true);
+        when(mFakeFeatureFactory.mAccountFeatureProvider.getAccounts(any(Context.class)))
+                .thenReturn(new Account[]{new Account("fake@account.foo", "fake.reallyfake")});
+
+        final BrandedAccountPreferenceController controller =
+                new BrandedAccountPreferenceController(mContext, "test_key");
+
+        assertThat(controller.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_configOff_hasAccount_off() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool",
+                "config_show_branded_account_in_device_info");
+        when(mResources.getBoolean(boolId)).thenReturn(false);
+        when(mFakeFeatureFactory.mAccountFeatureProvider.getAccounts(any(Context.class)))
+                .thenReturn(new Account[]{new Account("fake@account.foo", "fake.reallyfake")});
+
+        final BrandedAccountPreferenceController controller =
+                new BrandedAccountPreferenceController(mContext, "test_key");
+
+        assertThat(controller.isAvailable()).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
similarity index 71%
rename from tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
rename to tests/unit/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
index 80a3a11..8c75449 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
@@ -22,52 +22,51 @@
 
 import static org.mockito.ArgumentMatchers.any;
 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.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
-import android.content.pm.UserInfo;
-import android.os.Process;
-import android.os.UserHandle;
+import android.os.Looper;
 import android.os.UserManager;
 import android.provider.Settings;
 
 import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.Preference;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.shadow.ShadowUtils;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowUserManager;
 
-@RunWith(RobolectricTestRunner.class)
-@Config(shadows = ShadowUtils.class)
+@RunWith(AndroidJUnit4.class)
 public class BuildNumberPreferenceControllerTest {
 
     private static final String KEY_BUILD_NUMBER = "build_number";
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private InstrumentedPreferenceFragment mFragment;
 
-    private ShadowUserManager mShadowUserManager;
-
     private Context mContext;
+    private UserManager mUserManager;
+    private ClipboardManager mClipboardManager;
     private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
     private FakeFeatureFactory mFactory;
@@ -75,15 +74,23 @@
     private BuildNumberPreferenceController mController;
 
     @Before
+    @UiThreadTest
     public void setUp() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mShadowUserManager = Shadows.shadowOf(
-                RuntimeEnvironment.application.getSystemService(UserManager.class));
+
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mUserManager = (UserManager) spy(mContext.getSystemService(Context.USER_SERVICE));
+        doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
+        mClipboardManager = (ClipboardManager) spy(mContext.getSystemService(CLIPBOARD_SERVICE));
+        doReturn(mClipboardManager).when(mContext).getSystemService(CLIPBOARD_SERVICE);
+
         mFactory = FakeFeatureFactory.setupForTest();
         mLifecycleOwner = () -> mLifecycle;
         mLifecycle = new Lifecycle(mLifecycleOwner);
-        mController = new BuildNumberPreferenceController(mContext, KEY_BUILD_NUMBER);
+        mController = spy(new BuildNumberPreferenceController(mContext, KEY_BUILD_NUMBER));
         mController.setHost(mFragment);
 
         mPreference = new Preference(mContext);
@@ -93,11 +100,6 @@
                 Settings.Global.DEVICE_PROVISIONED, 1);
     }
 
-    @After
-    public void tearDown() {
-        ShadowUtils.reset();
-    }
-
     @Test
     public void handlePrefTreeClick_onlyHandleBuildNumberPref() {
         assertThat(mController.handlePreferenceTreeClick(mock(Preference.class))).isFalse();
@@ -105,32 +107,32 @@
 
     @Test
     public void handlePrefTreeClick_notAdminUser_notDemoUser_doNothing() {
-        mShadowUserManager.setIsAdminUser(false);
-        mShadowUserManager.setIsDemoUser(false);
+        when(mUserManager.isAdminUser()).thenReturn(false);
+        when(mUserManager.isDemoUser()).thenReturn(false);
 
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
     }
 
     @Test
     public void handlePrefTreeClick_isAdminUser_notDemoUser_handleBuildNumberPref() {
-        mShadowUserManager.setIsAdminUser(true);
-        mShadowUserManager.setIsDemoUser(false);
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        when(mUserManager.isDemoUser()).thenReturn(false);
 
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
     }
 
     @Test
     public void handlePrefTreeClick_notAdminUser_isDemoUser_handleBuildNumberPref() {
-        mShadowUserManager.setIsAdminUser(false);
-        mShadowUserManager.addUser(UserHandle.myUserId(), "test", UserInfo.FLAG_DEMO);
+        when(mUserManager.isAdminUser()).thenReturn(false);
+        when(mUserManager.isDemoUser()).thenReturn(true);
 
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
     }
 
     @Test
     public void handlePrefTreeClick_deviceNotProvisioned_doNothing() {
-        mShadowUserManager.setIsAdminUser(true);
-        mShadowUserManager.setIsDemoUser(false);
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        when(mUserManager.isDemoUser()).thenReturn(false);
 
         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED,
                 0);
@@ -143,17 +145,16 @@
 
     @Test
     public void handlePrefTreeClick_isMonkeyRun_doNothing() {
-        ShadowUtils.setIsUserAMonkey(true);
+        when(mController.isUserAMonkey()).thenReturn(true);
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
     }
 
     @Test
     public void handlePrefTreeClick_userHasRestriction_doNothing() {
-        mShadowUserManager.setIsAdminUser(true);
-        mShadowUserManager.setIsDemoUser(false);
-
-        mShadowUserManager.setUserRestriction(Process.myUserHandle(),
-                UserManager.DISALLOW_DEBUGGING_FEATURES, true);
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        when(mUserManager.isDemoUser()).thenReturn(false);
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES))
+                .thenReturn(true);
 
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
         verify(mFactory.metricsFeatureProvider).action(
@@ -184,8 +185,9 @@
     }
 
     @Test
+    @UiThreadTest
     public void onActivityResult_confirmPasswordRequestCompleted_enableDevPref() {
-        mShadowUserManager.setIsAdminUser(true);
+        when(mUserManager.isAdminUser()).thenReturn(true);
 
         final boolean activityResultHandled = mController.onActivityResult(
                 BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF,
@@ -197,12 +199,14 @@
     }
 
     @Test
+    @UiThreadTest
     public void copy_shouldCopyBuildNumberToClipboard() {
+        ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class);
+        doNothing().when(mClipboardManager).setPrimaryClip(captor.capture());
+
         mController.copy();
 
-        final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
-                CLIPBOARD_SERVICE);
-        final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
-        assertThat(data.toString()).isEqualTo(mController.getSummary());
+        final ClipData data = captor.getValue();
+        assertThat(data.getItemAt(0).getText().toString()).isEqualTo(mController.getSummary());
     }
 }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
similarity index 71%
rename from tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
rename to tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
index 9bb2d3f..2a06ce9 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
@@ -21,38 +21,43 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
+import android.os.Looper;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
 import androidx.preference.Preference;
+import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 
-import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.ResourcesUtils;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
 
 import java.util.ArrayList;
 import java.util.List;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(AndroidJUnit4.class)
 public class PhoneNumberPreferenceControllerTest {
 
-    @Mock
     private Preference mPreference;
     @Mock
     private Preference mSecondPreference;
@@ -62,25 +67,34 @@
     private SubscriptionInfo mSubscriptionInfo;
     @Mock
     private SubscriptionManager mSubscriptionManager;
-    @Mock
     private PreferenceScreen mScreen;
 
     private Context mContext;
     private PhoneNumberPreferenceController mController;
+    private ClipboardManager mClipboardManager;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mContext = spy(RuntimeEnvironment.application);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mClipboardManager = (ClipboardManager) spy(mContext.getSystemService(CLIPBOARD_SERVICE));
+        doReturn(mClipboardManager).when(mContext).getSystemService(CLIPBOARD_SERVICE);
         when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
         when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
         mController = spy(new PhoneNumberPreferenceController(mContext, "phone_number"));
-        final String prefKey = mController.getPreferenceKey();
-        when(mScreen.findPreference(prefKey)).thenReturn(mPreference);
-        when(mScreen.getContext()).thenReturn(mContext);
+
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        final PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        mScreen = preferenceManager.createPreferenceScreen(mContext);
+        mPreference = spy(new Preference(mContext));
+        mPreference.setKey(mController.getPreferenceKey());
+        mPreference.setVisible(true);
+        mScreen.addPreference(mPreference);
+
         doReturn(mSubscriptionInfo).when(mController).getSubscriptionInfo(anyInt());
         doReturn(mSecondPreference).when(mController).createNewPreference(mContext);
-        when(mPreference.isVisible()).thenReturn(true);
     }
 
     @Test
@@ -105,7 +119,7 @@
 
         mController.displayPreference(mScreen);
 
-        verify(mScreen).addPreference(mSecondPreference);
+        assertThat(mScreen.getPreferenceCount()).isEqualTo(2);
     }
 
     @Test
@@ -117,7 +131,7 @@
 
         mController.updateState(mPreference);
 
-        verify(mPreference).setTitle(mContext.getString(R.string.status_number));
+        verify(mPreference).setTitle(ResourcesUtils.getResourcesString(mContext, "status_number"));
         verify(mPreference).setSummary(phoneNumber);
     }
 
@@ -130,11 +144,11 @@
 
         mController.updateState(mPreference);
 
-        verify(mPreference).setTitle(
-                mContext.getString(R.string.status_number_sim_slot, 1 /* sim slot */));
+        verify(mPreference).setTitle(ResourcesUtils.getResourcesString(
+                mContext, "status_number_sim_slot", 1 /* sim slot */));
         verify(mPreference).setSummary(phoneNumber);
-        verify(mSecondPreference).setTitle(
-                mContext.getString(R.string.status_number_sim_slot, 2 /* sim slot */));
+        verify(mSecondPreference).setTitle(ResourcesUtils.getResourcesString(
+                mContext, "status_number_sim_slot", 2 /* sim slot */));
         verify(mSecondPreference).setSummary(phoneNumber);
     }
 
@@ -145,7 +159,8 @@
         CharSequence primaryNumber = mController.getSummary();
 
         assertThat(primaryNumber).isNotNull();
-        assertThat(primaryNumber).isEqualTo(mContext.getString(R.string.device_info_default));
+        assertThat(primaryNumber).isEqualTo(ResourcesUtils.getResourcesString(
+                mContext, "device_info_default"));
     }
 
     @Test
@@ -155,22 +170,24 @@
 
         CharSequence primaryNumber = mController.getSummary();
 
-        assertThat(primaryNumber).isEqualTo(mContext.getString(R.string.device_info_default));
+        assertThat(primaryNumber).isEqualTo(ResourcesUtils.getResourcesString(
+                mContext, "device_info_default"));
     }
 
     @Test
+    @UiThreadTest
     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);
+        ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class);
+        doNothing().when(mClipboardManager).setPrimaryClip(captor.capture());
 
         mController.copy();
 
-        final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
-                CLIPBOARD_SERVICE);
-        final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
+        final CharSequence data = captor.getValue().getItemAt(0).getText();
         assertThat(phoneNumber.contentEquals(data)).isTrue();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java
similarity index 66%
rename from tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java
rename to tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java
index 65e29b4..847919a 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java
@@ -18,41 +18,57 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
 import android.content.Context;
+import android.content.res.Resources;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.ResourcesUtils;
 
 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;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(AndroidJUnit4.class)
 public class DeviceModelPreferenceControllerTest {
 
     private Context mContext;
     private DeviceModelPreferenceController mController;
 
+    @Mock
+    private Resources mResources;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getResources()).thenReturn(mResources);
         mController = new DeviceModelPreferenceController(mContext, "test_key");
     }
 
     @Test
     public void getAvailabilityStatus_configAllowed_available() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool", "config_show_device_model");
+        when(mResources.getBoolean(boolId)).thenReturn(true);
+
         assertThat(mController.getAvailabilityStatus()).isEqualTo(
                 BasePreferenceController.AVAILABLE);
     }
 
     @Test
-    @Config(qualifiers = "mcc999")
     public void getAvailabilityStatus_configDisallowed_unavailable() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool", "config_show_device_model");
+        when(mResources.getBoolean(boolId)).thenReturn(false);
+
         assertThat(mController.getAvailabilityStatus()).isEqualTo(
                 BasePreferenceController.UNSUPPORTED_ON_DEVICE);
     }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java
similarity index 70%
rename from tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java
rename to tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java
index c7c7669..7262615 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java
@@ -17,41 +17,53 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
 import android.content.Context;
+import android.content.res.Resources;
 import android.os.Build;
+import android.os.Looper;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.deviceinfo.HardwareInfoPreferenceController;
+import com.android.settings.testutils.ResourcesUtils;
 
 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;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(AndroidJUnit4.class)
 public class HardwareInfoPreferenceControllerTest {
 
-    private final String KEY = "device_model";
+    private static final String KEY = "device_model";
 
     private Preference mPreference;
     private PreferenceScreen mPreferenceScreen;
     private Context mContext;
+    @Mock
+    private Resources mResources;
     private HardwareInfoPreferenceController mController;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getResources()).thenReturn(mResources);
         mController = new HardwareInfoPreferenceController(mContext, KEY);
         mPreference = new Preference(mContext);
         mPreference.setKey(KEY);
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
         final PreferenceManager preferenceManager = new PreferenceManager(mContext);
         mPreferenceScreen = preferenceManager.createPreferenceScreen(mContext);
         mPreferenceScreen.addPreference(mPreference);
@@ -59,13 +71,20 @@
 
     @Test
     public void isAvailable_returnTrueIfVisible() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool", "config_show_device_model");
+
+        when(mResources.getBoolean(boolId)).thenReturn(true);
         assertThat(mController.getAvailabilityStatus()).isEqualTo(
                 BasePreferenceController.AVAILABLE);
     }
 
     @Test
-    @Config(qualifiers = "mcc999")
     public void isAvailable_returnFalseIfNotVisible() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool", "config_show_device_model");
+
+        when(mResources.getBoolean(boolId)).thenReturn(false);
         assertThat(mController.getAvailabilityStatus()).isEqualTo(
                 BasePreferenceController.UNSUPPORTED_ON_DEVICE);
     }
diff --git a/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java
new file mode 100644
index 0000000..fc1407f
--- /dev/null
+++ b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.deviceinfo.hardwareinfo;
+
+import static android.content.Context.CLIPBOARD_SERVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.os.Looper;
+import android.os.SystemProperties;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+@RunWith(AndroidJUnit4.class)
+public class HardwareRevisionPreferenceControllerTest {
+
+    private Context mContext;
+    private HardwareRevisionPreferenceController mController;
+    private ClipboardManager mClipboardManager;
+
+    @Before
+    public void setUp() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mClipboardManager = (ClipboardManager) spy(mContext.getSystemService(CLIPBOARD_SERVICE));
+        doReturn(mClipboardManager).when(mContext).getSystemService(CLIPBOARD_SERVICE);
+        mController = new HardwareRevisionPreferenceController(mContext,
+                "hardware_info_device_revision");
+    }
+
+    @Test
+    @UiThreadTest
+    public void copy_shouldCopyHardwareRevisionToClipboard() {
+        ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class);
+        doNothing().when(mClipboardManager).setPrimaryClip(captor.capture());
+
+        mController.copy();
+
+        final ClipData data = captor.getValue();
+        final String hardwareVer = SystemProperties.get("ro.boot.hardware.revision");
+        assertThat(data.getItemAt(0).getText().toString()).isEqualTo(hardwareVer);
+    }
+}
diff --git a/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java
new file mode 100644
index 0000000..eaf97d4
--- /dev/null
+++ b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.deviceinfo.hardwareinfo;
+
+import static android.content.Context.CLIPBOARD_SERVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.os.Build;
+import android.os.Looper;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+@RunWith(AndroidJUnit4.class)
+public class SerialNumberPreferenceControllerTest {
+
+    private Context mContext;
+    private SerialNumberPreferenceController mController;
+    private ClipboardManager mClipboardManager;
+
+    @Before
+    public void setUp() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mClipboardManager = (ClipboardManager) spy(mContext.getSystemService(CLIPBOARD_SERVICE));
+        doReturn(mClipboardManager).when(mContext).getSystemService(CLIPBOARD_SERVICE);
+        mController = new SerialNumberPreferenceController(mContext, "test");
+    }
+
+    @Test
+    @UiThreadTest
+    public void copy_shouldPutSerialNumberToClipBoard() {
+        ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class);
+        doNothing().when(mClipboardManager).setPrimaryClip(captor.capture());
+
+        mController.copy();
+
+        final ClipData data = captor.getValue();
+        assertThat(data.getItemAt(0).getText().toString()).contains(Build.getSerial());
+    }
+}
diff --git a/tests/unit/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java b/tests/unit/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java
new file mode 100644
index 0000000..8172e1a
--- /dev/null
+++ b/tests/unit/src/com/android/settings/network/telephony/NetworkSelectSettingsTest.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.network.telephony;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.PersistableBundle;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.CellIdentity;
+import android.telephony.CellInfo;
+import android.telephony.TelephonyManager;
+
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+
+public class NetworkSelectSettingsTest {
+    private static final int SUB_ID = 2;
+    private static final String CARRIER_NAME1 = "CarrierName1";
+    private static final String CARRIER_NAME2 = "CarrierName2";
+
+    @Mock
+    public Resources mResources;
+    @Mock
+    public TelephonyManager mTelephonyManager;
+    @Mock
+    public CarrierConfigManager mCarrierConfigManager;
+    @Mock
+    public MetricsFeatureProvider mMetricsFeatureProvider;
+    @Mock
+    public NetworkOperatorPreference mNetworkOperatorPreference1;
+    @Mock
+    public NetworkOperatorPreference mNetworkOperatorPreference2;
+    @Mock
+    private CellInfo mCellInfo1;
+    @Mock
+    private CellIdentity mCellId1;
+    @Mock
+    private CellInfo mCellInfo2;
+    @Mock
+    private CellIdentity mCellId2;
+
+    private PreferenceScreen mPreferenceScreen;
+    @Mock
+    public PreferenceManager mPreferenceManager;
+
+    public Context mContext;
+    public PreferenceCategory mPreferenceCategory;
+
+    private Bundle mInitArguments;
+    private TargetClass mNetworkSelectSettings;
+
+    @Before
+    @UiThreadTest
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        doReturn(mResources).when(mContext).getResources();
+        doReturn(mContext).when(mPreferenceManager).getContext();
+
+        mPreferenceCategory = spy(new PreferenceCategory(mContext));
+        doReturn(mPreferenceManager).when(mPreferenceCategory).getPreferenceManager();
+
+        doReturn(CARRIER_NAME1).when(mCellId1).getOperatorAlphaLong();
+        doReturn(CARRIER_NAME2).when(mCellId2).getOperatorAlphaLong();
+
+        mNetworkSelectSettings = spy(new TargetClass(this));
+
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL, true);
+        doReturn(config).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
+
+        doReturn(TelephonyManager.DATA_CONNECTED).when(mTelephonyManager).getDataState();
+    }
+
+    public class TargetClass extends NetworkSelectSettings {
+        private NetworkSelectSettingsTest mTestEnv;
+        private boolean mIsPreferenceScreenEnabled;
+
+        public TargetClass(NetworkSelectSettingsTest env) {
+            mTestEnv = env;
+
+            Bundle bundle = new Bundle();
+            bundle.putInt(Settings.EXTRA_SUB_ID, SUB_ID);
+            setArguments(bundle);
+        }
+
+        @Override
+        public Context getContext() {
+            return mTestEnv.mContext;
+        }
+
+        @Override
+        public PreferenceManager getPreferenceManager() {
+            return mTestEnv.mPreferenceManager;
+        }
+
+        @Override
+        protected PreferenceCategory getPreferenceCategory(String preferenceKey) {
+            return mTestEnv.mPreferenceCategory;
+        }
+
+        @Override
+        protected TelephonyManager getTelephonyManager(Context context, int subscriptionId) {
+            return mTestEnv.mTelephonyManager;
+        }
+
+        @Override
+        protected CarrierConfigManager getCarrierConfigManager(Context context) {
+            return mTestEnv.mCarrierConfigManager;
+        }
+
+        @Override
+        protected MetricsFeatureProvider getMetricsFeatureProvider(Context context) {
+            return mTestEnv.mMetricsFeatureProvider;
+        }
+
+        @Override
+        protected boolean isPreferenceScreenEnabled() {
+            return mIsPreferenceScreenEnabled;
+        }
+
+        @Override
+        protected void enablePreferenceScreen(boolean enable) {
+            mIsPreferenceScreenEnabled = enable;
+        }
+
+        @Override
+        protected NetworkOperatorPreference
+                createNetworkOperatorPreference(CellInfo cellInfo) {
+            NetworkOperatorPreference pref = super.createNetworkOperatorPreference(cellInfo);
+            if (cellInfo == mTestEnv.mCellInfo1) {
+                pref.updateCell(cellInfo, mTestEnv.mCellId1);
+            } else if (cellInfo == mTestEnv.mCellInfo2) {
+                pref.updateCell(cellInfo, mTestEnv.mCellId2);
+            }
+            return pref;
+        }
+    }
+
+    @Test
+    @UiThreadTest
+    public void updateAllPreferenceCategory_correctOrderingPreference() {
+        mNetworkSelectSettings.onCreateInitialization();
+        mNetworkSelectSettings.enablePreferenceScreen(true);
+        mNetworkSelectSettings.scanResultHandler(Arrays.asList(mCellInfo1, mCellInfo2));
+
+        assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2);
+        final NetworkOperatorPreference preference =
+                (NetworkOperatorPreference) mPreferenceCategory.getPreference(1);
+        assertThat(preference.getOperatorName()).isEqualTo(mCellId2.getOperatorAlphaLong());
+    }
+
+    @Test
+    @UiThreadTest
+    public void updateForbiddenPlmns_forbiddenPlmnsNull_shouldNotCrash() {
+        when(mTelephonyManager.getForbiddenPlmns()).thenReturn(null);
+
+        mNetworkSelectSettings.onCreateInitialization();
+        mNetworkSelectSettings.enablePreferenceScreen(true);
+
+        // Should not Crash
+        mNetworkSelectSettings.updateForbiddenPlmns();
+    }
+}
diff --git a/tests/unit/src/com/android/settings/vpn2/AppPreferenceTest.java b/tests/unit/src/com/android/settings/vpn2/AppPreferenceTest.java
new file mode 100644
index 0000000..1f618cc
--- /dev/null
+++ b/tests/unit/src/com/android/settings/vpn2/AppPreferenceTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2021 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.vpn2;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.UserHandle;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Unittest for AppPreference */
+@RunWith(AndroidJUnit4.class)
+public class AppPreferenceTest {
+    // Additional mocking of the underying classes is necsesary if another user id is used.
+    private static final int USER_ID = UserHandle.USER_NULL;
+    private static final String PACKAGE_NAME = "test_package";
+    private static final String DIFFERENT_PACKAGE_NAME = "not_test_package";
+
+    @Mock
+    private DevicePolicyManager mDevicePolicyManager;
+
+    private Context mContext;
+    private AppPreference mAppPreference;
+
+    @Before
+    public void setUp() throws NameNotFoundException {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt());
+        doReturn(mContext).when(mContext).createPackageContextAsUser(any(), anyInt(), any());
+        when(mContext.getSystemService(DevicePolicyManager.class)).thenReturn(mDevicePolicyManager);
+    }
+
+    @Test
+    public void getPackageName_returnsAccuratePackageName() {
+        doReturn(DIFFERENT_PACKAGE_NAME).when(mDevicePolicyManager).getAlwaysOnVpnPackage();
+
+        mAppPreference = spy(new AppPreference(mContext, USER_ID, PACKAGE_NAME));
+        assertThat(mAppPreference.getPackageName()).isEqualTo(PACKAGE_NAME);
+    }
+
+    @Test
+    public void disableIfConfiguredByAdmin_packageNameNotEqualsAlwaysOn_shouldEnable() {
+        doReturn(DIFFERENT_PACKAGE_NAME).when(mDevicePolicyManager).getAlwaysOnVpnPackage();
+
+        mAppPreference = spy(new AppPreference(mContext, USER_ID, PACKAGE_NAME));
+        assertFalse(mAppPreference.isDisabledByAdmin());
+    }
+}
diff --git a/tests/unit/src/com/android/settings/vpn2/LegacyVpnPreferenceTest.java b/tests/unit/src/com/android/settings/vpn2/LegacyVpnPreferenceTest.java
new file mode 100644
index 0000000..10077ad
--- /dev/null
+++ b/tests/unit/src/com/android/settings/vpn2/LegacyVpnPreferenceTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 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.vpn2;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.content.res.Resources.NotFoundException;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.net.VpnProfile;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unittest for LegacyVpnPreference */
+@RunWith(AndroidJUnit4.class)
+public class LegacyVpnPreferenceTest {
+    private static final String PROFILE_KEY = "test_key";
+    private static final String PROFILE_NAME = "test_vpn_name";
+
+    private Context mContext;
+    private LegacyVpnPreference mLegacyVpnPreference;
+    private VpnProfile mVpnProfile;
+
+
+    @Before
+    public void setUp() {
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mVpnProfile = new VpnProfile(PROFILE_KEY);
+        mVpnProfile.name = PROFILE_NAME;
+        try {
+            // In Junit, loading the presference at first yields a Resources.NotFoundException
+            mLegacyVpnPreference = new LegacyVpnPreference(mContext);
+        } catch (NotFoundException exception) {
+            mLegacyVpnPreference = new LegacyVpnPreference(mContext);
+        }
+
+    }
+
+    @Test
+    public void setProfile_successfullyStoresProfile() {
+        mLegacyVpnPreference.setProfile(mVpnProfile);
+        assertThat(mLegacyVpnPreference.getProfile()).isEqualTo(mVpnProfile);
+    }
+
+    @Test
+    public void setProfile_updatesPreferenceTitle() {
+        mLegacyVpnPreference.setProfile(mVpnProfile);
+        assertThat(mLegacyVpnPreference.getTitle()).isEqualTo(PROFILE_NAME);
+    }
+}