Merge "Import translations. DO NOT MERGE ANYWHERE"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9998d08..5352562 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2586,13 +2586,6 @@
             android:theme="@style/GlifTheme.Light"
             android:windowSoftInputMode="stateVisible|adjustResize"/>
 
-        <activity android:name=".SetupEncryptionInterstitial"
-            android:label="@string/encryption_interstitial_header"
-            android:theme="@style/GlifTheme.Light"/>
-
-        <activity android:name=".EncryptionInterstitial"
-            android:theme="@style/GlifTheme.Light" />
-
         <activity
             android:name=".Settings$StorageDashboardActivity"
             android:label="@string/storage_settings"
diff --git a/res/layout/dialog_sim_status.xml b/res/layout/dialog_sim_status.xml
index 4fc7f46..b9abb15 100644
--- a/res/layout/dialog_sim_status.xml
+++ b/res/layout/dialog_sim_status.xml
@@ -162,18 +162,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="@string/status_esim_id"/>
-        <TextView
-            style="@style/device_info_dialog_value"
-            android:id="@+id/esim_id_value"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:textIsSelectable="true"
-            android:text="@string/device_info_not_available"/>
-        <ImageView
-            android:id="@+id/esim_id_qrcode"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            tools:ignore="ContentDescription" />
+
+        <include layout="@xml/esim_eid_and_qrcode" />
 
         <TextView
             style="@style/device_info_dialog_label"
diff --git a/res/layout/encryption_interstitial.xml b/res/layout/encryption_interstitial.xml
deleted file mode 100644
index 61ed292..0000000
--- a/res/layout/encryption_interstitial.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2017 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.
--->
-
-<com.google.android.setupdesign.GlifLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:icon="@drawable/ic_lock">
-
-    <LinearLayout
-        style="@style/SudContentFrame"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:clipChildren="false"
-        android:clipToPadding="false"
-        android:orientation="vertical">
-
-        <TextView
-            android:id="@+id/sud_layout_description"
-            style="@style/SudDescription.Glif"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-
-    </LinearLayout>
-
-</com.google.android.setupdesign.GlifLayout>
diff --git a/res/layout/user_credential.xml b/res/layout/user_credential.xml
index f441bda..fa7abb3 100644
--- a/res/layout/user_credential.xml
+++ b/res/layout/user_credential.xml
@@ -40,6 +40,22 @@
         android:paddingTop="10dp">
 
         <TextView
+            android:id="@+id/credential_being_used_by_title"
+            android:text="@string/credential_being_used_by"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/textColorSecondary"/>
+
+        <TextView
+            android:id="@+id/credential_being_used_by_content"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/textColorTertiary"
+            android:paddingStart="?android:attr/listPreferredItemPaddingStart"/>
+
+        <TextView
             android:id="@+id/contents_title"
             android:text="@string/credential_contains"
             android:layout_width="wrap_content"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d17b501..733d0e1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4760,21 +4760,21 @@
     <!-- Summary for the battery high usage tip, which presents apps with highest usage [CHAR LIMIT=NONE] -->
     <string name="battery_tip_high_usage_summary">See apps with highest usage</string>
     <!-- Title for the battery limited temporarily tip [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_limited_temporarily_title">Charging is paused</string>
+    <string name="battery_tip_limited_temporarily_title">Charging optimized to protect your battery</string>
     <!-- Summary for the battery limited temporarily tip [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_limited_temporarily_summary">Protecting battery to extend battery lifespan</string>
+    <string name="battery_tip_limited_temporarily_summary">To help extend your batter\'s lifespan, charging is optimized</string>
     <!-- Title for the battery dock defender future bypass tip [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_dock_defender_future_bypass_title">Charging to <xliff:g id="percent" example="10%">%1$s</xliff:g> to protect the battery</string>
+    <string name="battery_tip_dock_defender_future_bypass_title">Charging optimized to protect your battery</string>
     <!-- Summary for the battery dock defender future bypass tip [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_dock_defender_future_bypass_summary">When your tablet is docked, charging will be paused at <xliff:g id="percent" example="10%">%1$s</xliff:g> to extend battery lifespan</string>
+    <string name="battery_tip_dock_defender_future_bypass_summary">To help extend your battery\'s lifespan, charging is optimized while docked</string>
     <!-- Title for the battery dock defender active tip [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_dock_defender_active_title">Charging paused to protect battery</string>
+    <string name="battery_tip_dock_defender_active_title">Charging optimized to protect your battery</string>
     <!-- Summary for the battery dock defender active tip [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_dock_defender_active_summary">When your tablet is docked, charging is paused at <xliff:g id="percent" example="10%">%1$s</xliff:g> to extend battery lifespan</string>
+    <string name="battery_tip_dock_defender_active_summary">To help extend your battery\'s lifespan, charging is optimized while docked</string>
     <!-- Title for the battery dock defender temporarily bypassed tip [CHAR LIMIT=NONE] -->
     <string name="battery_tip_dock_defender_temporarily_bypassed_title">Charging to full</string>
     <!-- Summary for the battery dock defender temporarily bypassed tip [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_dock_defender_temporarily_bypassed_summary">To protect your battery, charging will be paused at <xliff:g id="percent" example="10%">%1$s</xliff:g> the next time your tablet is docked</string>
+    <string name="battery_tip_dock_defender_temporarily_bypassed_summary">To protect your battery, charging will be optimized the next time your tablet is docked</string>
     <!-- Content description for the battery limited temporarily tip secondary button [CHAR LIMIT=NONE] -->
     <string name="battery_tip_limited_temporarily_sec_button_content_description">Learn more about charging is paused</string>
     <!-- Text of battery limited temporarily tip resume charge button. [CHAR LIMIT=NONE] -->
@@ -5258,8 +5258,10 @@
     <string name="credentials_settings_not_available">Credentials are not available for this user</string>
     <!-- Sub-heading for a user credential installed to be used by apps and as part of VPN configurations. [CHAR LIMIT=NONE] -->
     <string name="credential_for_vpn_and_apps">Installed for VPN and apps</string>
+    <!-- Sub-heading for a user credential installed for Wi-Fi configuration. [CHAR LIMIT=NONE]. -->
+    <string name="credential_for_wifi">Installed for Wi\u2011Fi</string>
     <!-- Sub-heading for a user credential installed to be used as part of a Wi-Fi configuration. [CHAR LIMIT=NONE]. -->
-    <string name="credential_for_wifi">Installed for Wi-Fi</string>
+    <string name="credential_for_wifi_in_use">Installed for Wi\u2011Fi (In use)</string>
     <!-- Description of dialog to reset credential storage [CHAR LIMIT=NONE] -->
     <string name="credentials_reset_hint">Remove all the contents?</string>
     <!-- Toast message [CHAR LIMIT=30] -->
@@ -5809,14 +5811,16 @@
     <!-- Alert dialog confirmation when removing a user CA certificate. -->
     <string name="trusted_credentials_remove_confirmation">Permanently remove the user CA certificate?</string>
 
+    <!-- Header for a list of items that a credential entry is required. For example, a network uses this credential. [CHAR LIMIT=NONE] -->
+    <string name="credential_being_used_by">Being used by</string>
     <!-- Header for a list of items that a credential entry contains. For example, one private key and one certificate. [CHAR LIMIT=NONE] -->
-    <string name="credential_contains">This entry contains:</string>
+    <string name="credential_contains">This entry contains</string>
     <!-- Item found in the PKCS12 keystore being investigated [CHAR LIMIT=NONE] -->
-    <string name="one_userkey">one user key</string>
+    <string name="one_userkey">1 user key</string>
     <!-- Item found in the PKCS12 keystore being investigated [CHAR LIMIT=NONE] -->
-    <string name="one_usercrt">one user certificate</string>
+    <string name="one_usercrt">1 user certificate</string>
     <!-- Item found in the PKCS12 keystore being investigated [CHAR LIMIT=NONE] -->
-    <string name="one_cacrt">one CA certificate</string>
+    <string name="one_cacrt">1 CA certificate</string>
     <!-- Item found in thee PKCS12 keystore being investigated [CHAR LIMIT=NONE]-->
     <string name="n_cacrts">%d CA certificates</string>
     <!-- Alert dialog when viewing a set of user credentials. -->
@@ -5979,9 +5983,6 @@
     <!-- Button label for opening an arbitrary app [CHAR LIMIT=60] -->
     <string name="open_app_button">Open <xliff:g id="app_name" example="Safety">%1$s</xliff:g></string>
 
-    <!-- Title for more settings button, clicking this button will open a new page containing more settings related to current page. [CHAR LIMIT=60] -->
-    <string name="more_settings_button">More Settings</string>
-
     <!-- Application Restrictions screen title [CHAR LIMIT=45] -->
     <string name="application_restrictions">Allow apps and content</string>
     <!-- Applications with restrictions header [CHAR LIMIT=45] -->
@@ -6144,6 +6145,8 @@
     <string name="help_url_battery" translatable="false"></string>
     <!-- Help URL, Battery Defender [DO NOT TRANSLATE] -->
     <string name="help_url_battery_defender" translatable="false"></string>
+    <!-- Help URL, Dock Defender [DO NOT TRANSLATE] -->
+    <string name="help_url_dock_defender" translatable="false"></string>
     <!-- Help URL, Accounts [DO NOT TRANSLATE] -->
     <string name="help_url_accounts" translatable="false"></string>
     <!-- Help URL, Choose lockscreen [DO NOT TRANSLATE] -->
@@ -8157,73 +8160,6 @@
     <!-- Summary for work profile accounts group. [CHAR LIMIT=25] -->
     <string name="managing_admin">Managed by <xliff:g id="admin_app_label">%s</xliff:g></string>
 
-    <!-- Encryption interstitial title. This screen asks the user whether the device will ask for a PIN / pattern / password before the device starts up. [CHAR LIMIT=30] -->
-    <string name="encryption_interstitial_header">Secure start-up</string>
-
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a PIN to encrypt the device. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_pin">
-   You can further protect this device by requiring your PIN before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.
-   \n\nThis helps protect data on lost or stolen devices. Require PIN to start your device?
-   </string>
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a pattern to encrypt the device. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_pattern">
-   You can further protect this device by requiring your pattern before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.
-   \n\nThis helps protect data on lost or stolen devices. Require pattern to start your device?
-   </string>
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a password to encrypt the device. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_password">
-   You can further protect this device by requiring your password before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.
-   \n\nThis helps protect data on lost or stolen devices. Require password to start your device?
-   </string>
-
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a PIN to encrypt the device while setting up fingerprint unlock. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_pin_for_fingerprint">In addition to using your fingerprint to unlock your device, you can further protect this device by requiring your PIN before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require PIN to start your device?</string>
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a pattern to encrypt the device while setting up fingerprint unlock. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_pattern_for_fingerprint">In addition to using your fingerprint to unlock your device, you can further protect this device by requiring your pattern before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require pattern to start your device?</string>
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a password to encrypt the device while setting up fingerprint unlock. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_password_for_fingerprint">In addition to using your fingerprint to unlock your device, you can further protect this device by requiring your password before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require password to start your device?</string>
-
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a PIN to encrypt the device while setting up face unlock. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_pin_for_face">In addition to using your face to unlock your device, you can further protect this device by requiring your PIN before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require PIN to start your device?</string>
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a pattern to encrypt the device while setting up face unlock. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_pattern_for_face">In addition to using your face to unlock your device, you can further protect this device by requiring your pattern before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require pattern to start your device?</string>
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a password to encrypt the device while setting up face unlock. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_password_for_face">In addition to using your face to unlock your device, you can further protect this device by requiring your password before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require password to start your device?</string>
-
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a PIN to encrypt the device while setting up biometric unlock. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_pin_for_biometrics">In addition to using your biometrics to unlock your device, you can further protect this device by requiring your PIN before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require PIN to start your device?</string>
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a pattern to encrypt the device while setting up biometric unlock. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_pattern_for_biometrics">In addition to using your biometrics to unlock your device, you can further protect this device by requiring your pattern before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require pattern to start your device?</string>
-    <!-- Message shown on encryption interstitial to ask the user whether or not they want to use a password to encrypt the device while setting up biometric unlock. [CHAR LIMIT=NONE] -->
-    <string name="encryption_interstitial_message_password_for_biometrics">In addition to using your biometrics to unlock your device, you can further protect this device by requiring your password before it starts up. Until the device starts up, it can\u2019t receive calls, messages, or notifications, including alarms.\n\nThis helps protect data on lost or stolen devices. Require password to start your device?</string>
-
-
-    <!-- Button label to say yes to the question of whether to require PIN/password/pattern to start your device. [CHAR LIMIT=20] -->
-    <string name="encryption_interstitial_yes">Yes</string>
-    <!-- Button label to say no to the question of whether to require PIN/password/pattern to start your device. [CHAR LIMIT=20] -->
-    <string name="encryption_interstitial_no">No</string>
-
-    <!-- Title for encryption dialog that disables TalkBack. [CHAR_LIMIT=25] -->
-    <string name="encrypt_talkback_dialog_require_pin">Require PIN?</string>
-
-    <!-- Title for encryption dialog that disables TalkBack. [CHAR_LIMIT=25] -->
-    <string name="encrypt_talkback_dialog_require_pattern">Require pattern?</string>
-
-    <!-- Title for encryption dialog that disables TalkBack. [CHAR_LIMIT=25] -->
-    <string name="encrypt_talkback_dialog_require_password">Require password?</string>
-
-    <!-- Message for encryption dialog telling the user that Talkback and other accessibility services will be disabled. -->
-    <string name="encrypt_talkback_dialog_message_pin">When you enter your PIN to start this device, accessibility services like <xliff:g id="service" example="TalkBack">%1$s</xliff:g> won\u2019t yet be available.</string>
-
-    <!-- Message for encryption dialog telling the user that Talkback and other accessibility services will be disabled. -->
-    <string name="encrypt_talkback_dialog_message_pattern">When you enter your pattern to start this device, accessibility services like <xliff:g id="service" example="TalkBack">%1$s</xliff:g> won\u2019t yet be available.</string>
-
-    <!-- Message for encryption dialog telling the user that Talkback and other accessibility services will be disabled. -->
-    <string name="encrypt_talkback_dialog_message_password">When you enter your password to start this device, accessibility services like <xliff:g id="service" example="TalkBack">%1$s</xliff:g> won\u2019t yet be available.</string>
-
-    <!-- [CHAR LIMIT=NONE] Dialog body explaining that the app just selected by the user will not work after a reboot until until after the user enters their credentials, such as a PIN or password. -->
-    <string name="direct_boot_unaware_dialog_message">Note: If you restart your phone and have a screen lock set, this app can\'t start until you unlock your phone</string>
-
     <!-- New strings needed for App Info 2 -->
     <!-- Preference label for app default launch settings [CHAR LIMIT=35]-->
     <string name="launch_by_default">Open by default</string>
@@ -11002,6 +10938,11 @@
     <!-- Title for if toggle access is disabled by carrier [CHAR LIMIT=NONE] -->
     <string name="enable_2g_summary_disabled_carrier"><xliff:g id="carrier_name_2g" example="Google Fi">%1$s</xliff:g> requires 2G to be available</string>
 
+    <!-- Title for toggle if user wants to allow null cellular algorithms [CHAR LIMIT=40] -->
+    <string name="allow_null_algorithms_title">Allow less secure connection</string>
+    <!-- Summary for if the user wants to allow null cellular algorithms [CHAR LIMIT=NONE] -->
+    <string name="allow_null_algorithms_summary">May improve your signal in some locations. For emergency calls, less secure connections are always allowed.</string>
+
     <!-- Label for All services preference in App info settings [CHAR LIMIT=40] -->
     <string name="app_info_all_services_label">All services</string>
 
diff --git a/res/xml/esim_eid_and_qrcode.xml b/res/xml/esim_eid_and_qrcode.xml
new file mode 100644
index 0000000..b1f1634
--- /dev/null
+++ b/res/xml/esim_eid_and_qrcode.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+       xmlns:tools="http://schemas.android.com/tools">
+
+    <TextView
+        style="@style/device_info_dialog_value"
+        android:id="@+id/esim_id_value"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textIsSelectable="true"
+        android:text="@string/device_info_not_available"/>
+    <ImageView
+        android:id="@+id/esim_id_qrcode"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        tools:ignore="ContentDescription" />
+
+</merge>
diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index 987c2ce..7f059fb 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -250,6 +250,13 @@
             settings:userRestriction="no_cellular_2g"/>
 
         <SwitchPreference
+            android:key="allow_null_algorithms"
+            android:title="@string/allow_null_algorithms_title"
+            android:summary="@string/allow_null_algorithms_summary"
+            settings:controller=
+                "com.android.settings.network.telephony.NullAlgorithmsPreferenceController" />
+
+        <SwitchPreference
             android:key="nr_advanced_calling"
             android:title="@string/nr_advanced_calling_title"
             android:persistent="false"
diff --git a/res/xml/stylus_usi_details_fragment.xml b/res/xml/stylus_usi_details_fragment.xml
new file mode 100644
index 0000000..8a1d036
--- /dev/null
+++ b/res/xml/stylus_usi_details_fragment.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 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.
+  -->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:title="@string/stylus_device_details_title">
+
+    <com.android.settingslib.widget.LayoutPreference
+        android:key="stylus_usi_header"
+        android:layout="@layout/settings_entity_header"
+        android:selectable="false"
+        settings:allowDividerBelow="true"
+        settings:searchable="false"/>
+
+    <PreferenceCategory
+        android:key="device_stylus"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/EncryptionInterstitial.java b/src/com/android/settings/EncryptionInterstitial.java
deleted file mode 100644
index 4ab197d..0000000
--- a/src/com/android/settings/EncryptionInterstitial.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.accessibilityservice.AccessibilityServiceInfo;
-import android.app.Activity;
-import android.app.Dialog;
-import android.app.admin.DevicePolicyManager;
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.TextView;
-
-import androidx.appcompat.app.AlertDialog;
-
-import com.android.settings.core.InstrumentedFragment;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-import com.android.settings.password.ChooseLockSettingsHelper;
-
-import com.google.android.setupcompat.template.FooterBarMixin;
-import com.google.android.setupcompat.template.FooterButton;
-import com.google.android.setupdesign.GlifLayout;
-
-import java.util.List;
-
-public class EncryptionInterstitial extends SettingsActivity {
-    private static final String TAG = EncryptionInterstitial.class.getSimpleName();
-
-    protected static final String EXTRA_PASSWORD_QUALITY = "extra_password_quality";
-    protected static final String EXTRA_UNLOCK_METHOD_INTENT = "extra_unlock_method_intent";
-    public static final String EXTRA_REQUIRE_PASSWORD = "extra_require_password";
-    private static final int CHOOSE_LOCK_REQUEST = 100;
-
-    @Override
-    public Intent getIntent() {
-        Intent modIntent = new Intent(super.getIntent());
-        modIntent.putExtra(EXTRA_SHOW_FRAGMENT, EncryptionInterstitialFragment.class.getName());
-        return modIntent;
-    }
-
-    @Override
-    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        final int new_resid = SetupWizardUtils.getTheme(this, getIntent());
-        super.onApplyThemeResource(theme, new_resid, first);
-    }
-
-    @Override
-    protected boolean isValidFragment(String fragmentName) {
-        return EncryptionInterstitialFragment.class.getName().equals(fragmentName);
-    }
-
-    public static Intent createStartIntent(Context ctx, int quality,
-            boolean requirePasswordDefault, Intent unlockMethodIntent) {
-        return new Intent(ctx, EncryptionInterstitial.class)
-                .putExtra(EXTRA_PASSWORD_QUALITY, quality)
-                .putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, R.string.encryption_interstitial_header)
-                .putExtra(EXTRA_REQUIRE_PASSWORD, requirePasswordDefault)
-                .putExtra(EXTRA_UNLOCK_METHOD_INTENT, unlockMethodIntent);
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstance) {
-        super.onCreate(savedInstance);
-        findViewById(R.id.content_parent).setFitsSystemWindows(false);
-    }
-
-    public static class EncryptionInterstitialFragment extends InstrumentedFragment {
-
-        private boolean mPasswordRequired;
-        private Intent mUnlockMethodIntent;
-        private int mRequestedPasswordQuality;
-
-        @Override
-        public int getMetricsCategory() {
-            return SettingsEnums.ENCRYPTION;
-        }
-
-        @Override
-        public View onCreateView(
-                LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-            return inflater.inflate(R.layout.encryption_interstitial, container, false);
-        }
-
-        @Override
-        public void onViewCreated(View view, Bundle savedInstanceState) {
-            super.onViewCreated(view, savedInstanceState);
-
-            final boolean forFingerprint = getActivity().getIntent().getBooleanExtra(
-                    ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
-            final boolean forFace = getActivity().getIntent()
-                    .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, false);
-            final boolean forBiometrics = getActivity().getIntent()
-                    .getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, false);
-            Intent intent = getActivity().getIntent();
-            mRequestedPasswordQuality = intent.getIntExtra(EXTRA_PASSWORD_QUALITY, 0);
-            mUnlockMethodIntent = intent.getParcelableExtra(EXTRA_UNLOCK_METHOD_INTENT);
-            final int msgId;
-            switch (mRequestedPasswordQuality) {
-                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
-                    msgId = forFingerprint ?
-                            R.string.encryption_interstitial_message_pattern_for_fingerprint :
-                            forFace ?
-                            R.string.encryption_interstitial_message_pattern_for_face :
-                            forBiometrics ?
-                            R.string.encryption_interstitial_message_pattern_for_biometrics :
-                            R.string.encryption_interstitial_message_pattern;
-                    break;
-                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
-                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
-                    msgId = forFingerprint ?
-                            R.string.encryption_interstitial_message_pin_for_fingerprint :
-                            forFace ?
-                            R.string.encryption_interstitial_message_pin_for_face :
-                            forBiometrics ?
-                            R.string.encryption_interstitial_message_pin_for_biometrics :
-                            R.string.encryption_interstitial_message_pin;
-                    break;
-                default:
-                    msgId = forFingerprint ?
-                            R.string.encryption_interstitial_message_password_for_fingerprint :
-                            forFace ?
-                            R.string.encryption_interstitial_message_password_for_face :
-                            forBiometrics ?
-                            R.string.encryption_interstitial_message_password_for_biometrics :
-                            R.string.encryption_interstitial_message_password;
-                    break;
-            }
-            TextView message = (TextView) getActivity().findViewById(R.id.sud_layout_description);
-            message.setText(msgId);
-
-            setRequirePasswordState(getActivity().getIntent().getBooleanExtra(
-                    EXTRA_REQUIRE_PASSWORD, true));
-
-            GlifLayout layout = (GlifLayout) view;
-            layout.setHeaderText(getActivity().getTitle());
-
-            final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
-            mixin.setSecondaryButton(
-                    new FooterButton.Builder(getContext())
-                            .setText(R.string.encryption_interstitial_no)
-                            .setListener(this::onNoButtonClicked)
-                            .setButtonType(FooterButton.ButtonType.SKIP)
-                            .setTheme(R.style.SudGlifButton_Secondary)
-                            .build()
-            );
-
-            mixin.setPrimaryButton(
-                    new FooterButton.Builder(getContext())
-                            .setText(R.string.encryption_interstitial_yes)
-                            .setListener(this::onYesButtonClicked)
-                            .setButtonType(FooterButton.ButtonType.NEXT)
-                            .setTheme(R.style.SudGlifButton_Primary)
-                            .build()
-            );
-        }
-
-        protected void startLockIntent() {
-            if (mUnlockMethodIntent != null) {
-                mUnlockMethodIntent.putExtra(EXTRA_REQUIRE_PASSWORD, mPasswordRequired);
-                startActivityForResult(mUnlockMethodIntent, CHOOSE_LOCK_REQUEST);
-            } else {
-                Log.wtf(TAG, "no unlock intent to start");
-                finish();
-            }
-        }
-
-        @Override
-        public void onActivityResult(int requestCode, int resultCode, Intent data) {
-            super.onActivityResult(requestCode, resultCode, data);
-            if (requestCode == CHOOSE_LOCK_REQUEST && resultCode != RESULT_CANCELED) {
-                getActivity().setResult(resultCode, data);
-                finish();
-            }
-        }
-
-        private void onYesButtonClicked(View view) {
-            final boolean accEn = AccessibilityManager.getInstance(getActivity()).isEnabled();
-            if (accEn && !mPasswordRequired) {
-                setRequirePasswordState(false); // clear the UI state
-                AccessibilityWarningDialogFragment.newInstance(mRequestedPasswordQuality)
-                        .show(
-                                getChildFragmentManager(),
-                                AccessibilityWarningDialogFragment.TAG);
-            } else {
-                setRequirePasswordState(true);
-                startLockIntent();
-            }
-        }
-
-        private void onNoButtonClicked(View view) {
-            setRequirePasswordState(false);
-            startLockIntent();
-        }
-
-        private void setRequirePasswordState(boolean required) {
-            mPasswordRequired = required;
-        }
-
-        public void finish() {
-            Activity activity = getActivity();
-            if (activity == null) return;
-            if (getFragmentManager().getBackStackEntryCount() > 0) {
-                getFragmentManager().popBackStack();
-            } else {
-                activity.finish();
-            }
-        }
-    }
-
-    public static class AccessibilityWarningDialogFragment extends InstrumentedDialogFragment
-            implements DialogInterface.OnClickListener {
-
-        public static final String TAG = "AccessibilityWarningDialog";
-
-        public static AccessibilityWarningDialogFragment newInstance(int passwordQuality) {
-            AccessibilityWarningDialogFragment fragment = new AccessibilityWarningDialogFragment();
-            Bundle args = new Bundle(1);
-            args.putInt(EXTRA_PASSWORD_QUALITY, passwordQuality);
-            fragment.setArguments(args);
-            return fragment;
-        }
-
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            final int titleId;
-            final int messageId;
-            switch (getArguments().getInt(EXTRA_PASSWORD_QUALITY)) {
-                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
-                    titleId = R.string.encrypt_talkback_dialog_require_pattern;
-                    messageId = R.string.encrypt_talkback_dialog_message_pattern;
-                    break;
-                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
-                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
-                    titleId = R.string.encrypt_talkback_dialog_require_pin;
-                    messageId = R.string.encrypt_talkback_dialog_message_pin;
-                    break;
-                default:
-                    titleId = R.string.encrypt_talkback_dialog_require_password;
-                    messageId = R.string.encrypt_talkback_dialog_message_password;
-                    break;
-            }
-
-
-            final Activity activity = getActivity();
-            List<AccessibilityServiceInfo> list =
-                    AccessibilityManager.getInstance(activity)
-                            .getEnabledAccessibilityServiceList(
-                                    AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
-            final CharSequence exampleAccessibility;
-            if (list.isEmpty()) {
-                // This should never happen.  But we shouldn't crash
-                exampleAccessibility = "";
-            } else {
-                exampleAccessibility = list.get(0).getResolveInfo()
-                        .loadLabel(activity.getPackageManager());
-            }
-            return new AlertDialog.Builder(activity)
-                    .setTitle(titleId)
-                    .setMessage(getString(messageId, exampleAccessibility))
-                    .setCancelable(true)
-                    .setPositiveButton(android.R.string.ok, this)
-                    .setNegativeButton(android.R.string.cancel, this)
-                    .create();
-        }
-
-        @Override
-        public int getMetricsCategory() {
-            return SettingsEnums.DIALOG_ENCRYPTION_INTERSTITIAL_ACCESSIBILITY;
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            EncryptionInterstitialFragment fragment =
-                    (EncryptionInterstitialFragment) getParentFragment();
-            if (fragment != null) {
-                if (which == DialogInterface.BUTTON_POSITIVE) {
-                    fragment.setRequirePasswordState(true);
-                    fragment.startLockIntent();
-                } else if (which == DialogInterface.BUTTON_NEGATIVE) {
-                    fragment.setRequirePasswordState(false);
-                }
-            }
-        }
-    }
-}
diff --git a/src/com/android/settings/SettingsApplication.java b/src/com/android/settings/SettingsApplication.java
index f06d999..0d2cfe9 100644
--- a/src/com/android/settings/SettingsApplication.java
+++ b/src/com/android/settings/SettingsApplication.java
@@ -75,9 +75,9 @@
     }
 
     @Override
-    public void onLowMemory() {
-        super.onLowMemory();
-        AppIconCacheManager.getInstance().release();
+    public void onTrimMemory(int level) {
+        super.onTrimMemory(level);
+        AppIconCacheManager.getInstance().trimMemory(level);
     }
 
     private class DeviceProvisionedObserver extends ContentObserver {
diff --git a/src/com/android/settings/SetupEncryptionInterstitial.java b/src/com/android/settings/SetupEncryptionInterstitial.java
deleted file mode 100644
index d9e265f..0000000
--- a/src/com/android/settings/SetupEncryptionInterstitial.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.content.Context;
-import android.content.Intent;
-
-/**
- * Setup Wizard's version of EncryptionInterstitial screen. It inherits the logic and basic
- * structure from EncryptionInterstitial class, and should remain similar to that behaviorally. This
- * class should only overload base methods for minor theme and behavior differences specific to
- * Setup Wizard. Other changes should be done to EncryptionInterstitial class instead and let this
- * class inherit those changes.
- */
-public class SetupEncryptionInterstitial extends EncryptionInterstitial {
-
-    public static Intent createStartIntent(Context ctx, int quality,
-            boolean requirePasswordDefault, Intent unlockMethodIntent) {
-        Intent startIntent = EncryptionInterstitial.createStartIntent(ctx, quality,
-                requirePasswordDefault, unlockMethodIntent);
-        startIntent.setClass(ctx, SetupEncryptionInterstitial.class);
-        startIntent.putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)
-                .putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, -1);
-        return startIntent;
-    }
-
-    @Override
-    public Intent getIntent() {
-        Intent modIntent = new Intent(super.getIntent());
-        modIntent.putExtra(EXTRA_SHOW_FRAGMENT,
-                SetupEncryptionInterstitialFragment.class.getName());
-        return modIntent;
-    }
-
-    @Override
-    protected boolean isValidFragment(String fragmentName) {
-        return SetupEncryptionInterstitialFragment.class.getName().equals(fragmentName);
-    }
-
-    public static class SetupEncryptionInterstitialFragment extends EncryptionInterstitialFragment {
-    }
-}
diff --git a/src/com/android/settings/UserCredentialsSettings.java b/src/com/android/settings/UserCredentialsSettings.java
index c45b5ef..73f1d9e 100644
--- a/src/com/android/settings/UserCredentialsSettings.java
+++ b/src/com/android/settings/UserCredentialsSettings.java
@@ -43,12 +43,14 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.app.AlertDialog;
 import androidx.fragment.app.DialogFragment;
 import androidx.fragment.app.Fragment;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.wifi.helper.SavedWifiHelper;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -74,6 +76,9 @@
 
     private static final String KEYSTORE_PROVIDER = "AndroidKeyStore";
 
+    @VisibleForTesting
+    protected SavedWifiHelper mSavedWifiHelper;
+
     @Override
     public int getMetricsCategory() {
         return SettingsEnums.USER_CREDENTIALS;
@@ -88,15 +93,23 @@
     @Override
     public void onClick(final View view) {
         final Credential item = (Credential) view.getTag();
-        if (item != null) {
-            CredentialDialogFragment.show(this, item);
+        if (item == null) return;
+        if (item.isInUse()) {
+            item.setUsedByNames(mSavedWifiHelper.getCertificateNetworkNames(item.alias));
         }
+        showCredentialDialogFragment(item);
     }
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         getActivity().setTitle(R.string.user_credentials);
+        mSavedWifiHelper = SavedWifiHelper.getInstance(getContext(), getSettingsLifecycle());
+    }
+
+    @VisibleForTesting
+    protected void showCredentialDialogFragment(Credential item) {
+        CredentialDialogFragment.show(this, item);
     }
 
     protected void announceRemoval(String alias) {
@@ -112,7 +125,9 @@
         }
     }
 
-    public static class CredentialDialogFragment extends InstrumentedDialogFragment {
+    /** The fragment to show the credential information. */
+    public static class CredentialDialogFragment extends InstrumentedDialogFragment
+            implements DialogInterface.OnShowListener {
         private static final String TAG = "CredentialDialogFragment";
         private static final String ARG_CREDENTIAL = "credential";
 
@@ -162,17 +177,23 @@
                         dialog.dismiss();
                     }
                 };
-                // TODO: b/127865361
-                //       a safe means of clearing wifi certificates. Configs refer to aliases
-                //       directly so deleting certs will break dependent access points.
-                //       However, Wi-Fi used to remove this certificate from storage if the network
-                //       was removed, regardless if it is used in more than one network.
-                //       It has been decided to allow removing certificates from this menu, as we
-                //       assume that the user who manually adds certificates must have a way to
-                //       manually remove them.
                 builder.setNegativeButton(R.string.trusted_credentials_remove_label, listener);
             }
-            return builder.create();
+            AlertDialog dialog = builder.create();
+            dialog.setOnShowListener(this);
+            return dialog;
+        }
+
+        /**
+         * Override for the negative button enablement on demand.
+         */
+        @Override
+        public void onShow(DialogInterface dialogInterface) {
+            final Credential item = (Credential) getArguments().getParcelable(ARG_CREDENTIAL);
+            if (item.isInUse()) {
+                ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_NEGATIVE)
+                        .setEnabled(false);
+            }
         }
 
         @Override
@@ -300,6 +321,9 @@
                 while (aliases.hasMoreElements()) {
                     String alias = aliases.nextElement();
                     Credential c = new Credential(alias, uid);
+                    if (!c.isSystem()) {
+                        c.setInUse(mSavedWifiHelper.isCertificateInUse(alias));
+                    }
                     Key key = null;
                     try {
                         key = keyStore.getKey(alias, null);
@@ -423,12 +447,13 @@
         }
 
         ((TextView) view.findViewById(R.id.alias)).setText(item.alias);
-        ((TextView) view.findViewById(R.id.purpose)).setText(item.isSystem()
-                ? R.string.credential_for_vpn_and_apps
-                : R.string.credential_for_wifi);
+        updatePurposeView(view.findViewById(R.id.purpose), item);
 
         view.findViewById(R.id.contents).setVisibility(expanded ? View.VISIBLE : View.GONE);
         if (expanded) {
+            updateUsedByViews(view.findViewById(R.id.credential_being_used_by_title),
+                    view.findViewById(R.id.credential_being_used_by_content), item);
+
             for (int i = 0; i < credentialViewTypes.size(); i++) {
                 final View detail = view.findViewById(credentialViewTypes.keyAt(i));
                 detail.setVisibility(item.storedTypes.contains(credentialViewTypes.valueAt(i))
@@ -438,6 +463,30 @@
         return view;
     }
 
+    @VisibleForTesting
+    protected static void updatePurposeView(TextView purpose, Credential item) {
+        int subTextResId = R.string.credential_for_vpn_and_apps;
+        if (!item.isSystem()) {
+            subTextResId = (item.isInUse())
+                    ? R.string.credential_for_wifi_in_use
+                    : R.string.credential_for_wifi;
+        }
+        purpose.setText(subTextResId);
+    }
+
+    @VisibleForTesting
+    protected static void updateUsedByViews(TextView title, TextView content, Credential item) {
+        List<String> usedByNames = item.getUsedByNames();
+        if (usedByNames.size() > 0) {
+            title.setVisibility(View.VISIBLE);
+            content.setText(String.join("\n", usedByNames));
+            content.setVisibility(View.VISIBLE);
+        } else {
+            title.setVisibility(View.GONE);
+            content.setVisibility(View.GONE);
+        }
+    }
+
     static class AliasEntry {
         public String alias;
         public int uid;
@@ -469,6 +518,16 @@
         final int uid;
 
         /**
+         * Indicate whether or not this credential is in use.
+         */
+        boolean mIsInUse;
+
+        /**
+         * The list of networks which use this credential.
+         */
+        List<String> mUsedByNames = new ArrayList<>();
+
+        /**
          * Should contain some non-empty subset of:
          * <ul>
          *   <li>{@link Credentials.CA_CERTIFICATE}</li>
@@ -524,10 +583,28 @@
             return UserHandle.getAppId(uid) == Process.SYSTEM_UID;
         }
 
-        public String getAlias() { return alias; }
+        public String getAlias() {
+            return alias;
+        }
 
         public EnumSet<Type> getStoredTypes() {
             return storedTypes;
         }
+
+        public void setInUse(boolean inUse) {
+            mIsInUse = inUse;
+        }
+
+        public boolean isInUse() {
+            return mIsInUse;
+        }
+
+        public void setUsedByNames(List<String> names) {
+            mUsedByNames = new ArrayList<>(names);
+        }
+
+        public List<String> getUsedByNames() {
+            return new ArrayList<String>(mUsedByNames);
+        }
     }
 }
diff --git a/src/com/android/settings/connecteddevice/stylus/StylusUsiDetailsFragment.java b/src/com/android/settings/connecteddevice/stylus/StylusUsiDetailsFragment.java
new file mode 100644
index 0000000..4691a5b
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/stylus/StylusUsiDetailsFragment.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 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.connecteddevice.stylus;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.hardware.input.InputManager;
+import android.view.InputDevice;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Controls the USI stylus details and provides updates to individual controllers. */
+public class StylusUsiDetailsFragment extends DashboardFragment {
+    private static final String TAG = StylusUsiDetailsFragment.class.getSimpleName();
+    private static final String KEY_DEVICE_INPUT_ID = "device_input_id";
+
+    @VisibleForTesting
+    @Nullable
+    InputDevice mInputDevice;
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        int inputDeviceId = getArguments().getInt(KEY_DEVICE_INPUT_ID);
+        InputManager im = context.getSystemService(InputManager.class);
+        mInputDevice = im.getInputDevice(inputDeviceId);
+
+        super.onAttach(context);
+        if (mInputDevice == null) {
+            finish();
+        }
+    }
+
+
+    @Override
+    public int getMetricsCategory() {
+        // TODO(b/261988317): for new SettingsEnum for this page
+        return SettingsEnums.BLUETOOTH_DEVICE_DETAILS;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.stylus_usi_details_fragment;
+    }
+
+    @Override
+    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+        ArrayList<AbstractPreferenceController> controllers = new ArrayList<>();
+        if (mInputDevice != null) {
+            Lifecycle lifecycle = getSettingsLifecycle();
+            controllers.add(new StylusUsiHeaderController(context, mInputDevice));
+            controllers.add(new StylusDevicesController(context, mInputDevice, lifecycle));
+        }
+        return controllers;
+    }
+}
diff --git a/src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderController.java b/src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderController.java
new file mode 100644
index 0000000..826cc1f
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderController.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2022 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.connecteddevice.stylus;
+
+import android.content.Context;
+import android.hardware.BatteryState;
+import android.hardware.input.InputManager;
+import android.os.Bundle;
+import android.view.InputDevice;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnCreate;
+import com.android.settingslib.core.lifecycle.events.OnDestroy;
+import com.android.settingslib.widget.LayoutPreference;
+
+import java.text.NumberFormat;
+
+/**
+ * This class adds a header for USI stylus devices with a heading, icon, and battery level.
+ * As opposed to the bluetooth device headers, this USI header gets its battery values
+ * from {@link InputManager} APIs, rather than the bluetooth battery levels.
+ */
+public class StylusUsiHeaderController extends BasePreferenceController implements
+        InputManager.InputDeviceBatteryListener, LifecycleObserver, OnCreate, OnDestroy {
+
+    private static final String KEY_STYLUS_USI_HEADER = "stylus_usi_header";
+    private static final String TAG = StylusUsiHeaderController.class.getSimpleName();
+
+    private final InputManager mInputManager;
+    private final InputDevice mInputDevice;
+
+    private LayoutPreference mHeaderPreference;
+
+
+    public StylusUsiHeaderController(Context context, InputDevice inputDevice) {
+        super(context, KEY_STYLUS_USI_HEADER);
+        mInputDevice = inputDevice;
+        mInputManager = context.getSystemService(InputManager.class);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        mHeaderPreference = screen.findPreference(getPreferenceKey());
+        View view = mHeaderPreference.findViewById(R.id.entity_header);
+        TextView titleView = view.findViewById(R.id.entity_header_title);
+        titleView.setText(R.string.stylus_usi_header_title);
+
+        ImageView iconView = mHeaderPreference.findViewById(R.id.entity_header_icon);
+        if (iconView != null) {
+            // TODO(b/250909304): get proper icon once VisD ready
+            iconView.setImageResource(R.drawable.circle);
+            iconView.setContentDescription("Icon for stylus");
+        }
+        refresh();
+        super.displayPreference(screen);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        refresh();
+    }
+
+    private void refresh() {
+        BatteryState batteryState = mInputDevice.getBatteryState();
+        View view = mHeaderPreference.findViewById(R.id.entity_header);
+        TextView summaryView = view.findViewById(R.id.entity_header_summary);
+
+        if (isValidBatteryState(batteryState)) {
+            summaryView.setVisibility(View.VISIBLE);
+            summaryView.setText(
+                    NumberFormat.getPercentInstance().format(batteryState.getCapacity()));
+        } else {
+            summaryView.setVisibility(View.INVISIBLE);
+        }
+    }
+
+    /**
+     * This determines if a battery state is 'stale', as indicated by the presence of
+     * battery values.
+     *
+     * A USI battery state is valid (and present) if a USI battery value has been pulled
+     * within the last 1 hour of a stylus touching/hovering on the screen. The header shows
+     * battery values in this case, Conversely, a stale battery state means no USI battery
+     * value has been detected within the last 1 hour. Thus, the USI stylus preference will
+     * not be shown in Settings, and accordingly, the USI battery state won't surface.
+     *
+     * @param batteryState Latest battery state pulled from the kernel
+     */
+    private boolean isValidBatteryState(BatteryState batteryState) {
+        return batteryState != null
+                && batteryState.isPresent()
+                && batteryState.getCapacity() > 0f;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_STYLUS_USI_HEADER;
+    }
+
+    @Override
+    public void onBatteryStateChanged(int deviceId, long eventTimeMillis,
+            @NonNull BatteryState batteryState) {
+        refresh();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        mInputManager.addInputDeviceBatteryListener(mInputDevice.getId(),
+                mContext.getMainExecutor(), this);
+    }
+
+    @Override
+    public void onDestroy() {
+        mInputManager.removeInputDeviceBatteryListener(mInputDevice.getId(),
+                this);
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java
index af7dded..d164e93 100644
--- a/src/com/android/settings/fuelgauge/BatteryInfo.java
+++ b/src/com/android/settings/fuelgauge/BatteryInfo.java
@@ -42,8 +42,6 @@
 import com.android.settingslib.utils.PowerUtil;
 import com.android.settingslib.utils.StringUtil;
 
-import java.text.NumberFormat;
-
 public class BatteryInfo {
     private static final String TAG = "BatteryInfo";
 
@@ -305,13 +303,9 @@
                     timeString);
             info.chargeLabel = context.getString(resId, info.batteryPercentString, timeString);
         } else if (dockDefenderMode == BatteryUtils.DockDefenderMode.FUTURE_BYPASS) {
-            // Dock defender will be triggered in the future, charging will be paused at 90%.
-            final int extraValue = context.getResources().getInteger(
-                    R.integer.config_battery_extra_tip_value);
-            final String extraPercentage = NumberFormat.getPercentInstance().format(
-                    extraValue * 0.01f);
+            // Dock defender will be triggered in the future, charging will be optimized.
             info.chargeLabel = context.getString(R.string.power_charging_future_paused,
-                    info.batteryPercentString, extraPercentage);
+                    info.batteryPercentString);
         } else {
             final String chargeStatusLabel = Utils.getBatteryStatus(context, batteryBroadcast,
                     compactStatus);
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index 8029194..959820a 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -146,9 +146,9 @@
     Set<CharSequence> getHideBackgroundUsageTimeSet(Context context);
 
     /**
-     * Returns package names for hiding application in the usage screen.
+     * Returns {@link Set} for hiding application package names in the usage screen.
      */
-    CharSequence[] getHideApplicationEntries(Context context);
+    Set<CharSequence> getHideApplicationSet(Context context);
 
     /**
      * Returns {@link Set} for ignoring task root class names for screen on time.
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index 53d8701..94e4872 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -162,8 +162,8 @@
     }
 
     @Override
-    public CharSequence[] getHideApplicationEntries(Context context) {
-        return new CharSequence[0];
+    public Set<CharSequence> getHideApplicationSet(Context context) {
+        return new ArraySet<>();
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java
index dae4af4..bc0ba08 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java
@@ -32,8 +32,6 @@
 import com.android.settingslib.HelpUtils;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
-import java.text.NumberFormat;
-
 /**
  * Tip to show dock defender status
  */
@@ -58,8 +56,7 @@
     public CharSequence getTitle(Context context) {
         switch (mMode) {
             case DockDefenderMode.FUTURE_BYPASS:
-                return context.getString(R.string.battery_tip_dock_defender_future_bypass_title,
-                        getExtraPercentage(context));
+                return context.getString(R.string.battery_tip_dock_defender_future_bypass_title);
             case DockDefenderMode.ACTIVE:
                 return context.getString(R.string.battery_tip_dock_defender_active_title);
             case DockDefenderMode.TEMPORARILY_BYPASSED:
@@ -74,15 +71,12 @@
     public CharSequence getSummary(Context context) {
         switch (mMode) {
             case DockDefenderMode.FUTURE_BYPASS:
-                return context.getString(R.string.battery_tip_dock_defender_future_bypass_summary,
-                        getExtraPercentage(context));
+                return context.getString(R.string.battery_tip_dock_defender_future_bypass_summary);
             case DockDefenderMode.ACTIVE:
-                return context.getString(R.string.battery_tip_dock_defender_active_summary,
-                        getExtraPercentage(context));
+                return context.getString(R.string.battery_tip_dock_defender_active_summary);
             case DockDefenderMode.TEMPORARILY_BYPASSED:
                 return context.getString(
-                        R.string.battery_tip_dock_defender_temporarily_bypassed_summary,
-                        getExtraPercentage(context));
+                        R.string.battery_tip_dock_defender_temporarily_bypassed_summary);
             default:
                 return null;
         }
@@ -145,12 +139,11 @@
         }
 
         cardPreference.setSecondaryButtonText(context.getString(R.string.learn_more));
-        //TODO: update helper string
         cardPreference.setSecondaryButtonClickListener(
                 button -> button.startActivityForResult(
                         HelpUtils.getHelpIntent(
                                 context,
-                                context.getString(R.string.help_url_battery_defender),
+                                context.getString(R.string.help_url_dock_defender),
                                 /* backupContext */ ""), /* requestCode */ 0));
         cardPreference.setSecondaryButtonVisible(true);
         cardPreference.setSecondaryButtonContentDescription(context.getString(
@@ -174,13 +167,6 @@
         Log.i(TAG, "send resume charging broadcast intent=" + intent);
     }
 
-    private String getExtraPercentage(Context context) {
-        final int extraValue = context.getResources()
-                .getInteger(R.integer.config_battery_extra_tip_value);
-        return NumberFormat.getPercentInstance()
-                .format(extraValue * 0.01f);
-    }
-
     public static final Creator CREATOR = new Creator() {
         public BatteryTip createFromParcel(Parcel in) {
             return new DockDefenderTip(in);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java
index caf2cf3..59903a0 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java
@@ -32,9 +32,6 @@
             @NonNull List<BatteryDiffEntry> systemDiffEntries) {
         mAppEntries = appDiffEntries;
         mSystemEntries = systemDiffEntries;
-        setTotalConsumePowerForAllEntries(mAppEntries);
-        setTotalConsumePowerForAllEntries(mSystemEntries);
-        sortEntries();
     }
 
     public List<BatteryDiffEntry> getAppDiffEntryList() {
@@ -45,6 +42,18 @@
         return mSystemEntries;
     }
 
+    // Sorts entries based on consumed percentage.
+    void sortEntries() {
+        Collections.sort(mAppEntries, BatteryDiffEntry.COMPARATOR);
+        Collections.sort(mSystemEntries, BatteryDiffEntry.COMPARATOR);
+    }
+
+    // Sets total consume power for app and system entries separately.
+    void setTotalConsumePower() {
+        setTotalConsumePowerForAllEntries(mAppEntries);
+        setTotalConsumePowerForAllEntries(mSystemEntries);
+    }
+
     // Sets total consume power for each entry.
     private void setTotalConsumePowerForAllEntries(List<BatteryDiffEntry> batteryDiffEntries) {
         double totalConsumePower = 0.0;
@@ -55,10 +64,4 @@
             batteryDiffEntry.setTotalConsumePower(totalConsumePower);
         }
     }
-
-    // Sorts entries based on consumed percentage.
-    private void sortEntries() {
-        Collections.sort(mAppEntries, BatteryDiffEntry.COMPARATOR);
-        Collections.sort(mSystemEntries, BatteryDiffEntry.COMPARATOR);
-    }
 }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index e3e1912..2db6849 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -280,9 +280,7 @@
                     case Event.DEVICE_SHUTDOWN:
                         final String taskRootClassName = event.getTaskRootClassName();
                         if (!TextUtils.isEmpty(taskRootClassName)
-                                && !ignoreScreenOnTimeTaskRootSet.isEmpty()
-                                && contains(
-                                        taskRootClassName, ignoreScreenOnTimeTaskRootSet)) {
+                                && ignoreScreenOnTimeTaskRootSet.contains(taskRootClassName)) {
                             Log.w(TAG, String.format(
                                     "Ignoring a usage event with task root class name %s, "
                                             + "(timestamp=%d, type=%d)",
@@ -548,7 +546,7 @@
         insertDailyUsageDiffData(hourlyBatteryLevelsPerDay, resultMap);
         // Insert diff data [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL].
         insertAllUsageDiffData(resultMap);
-        purgeFakeAndHiddenPackages(context, resultMap);
+        processBatteryDiffData(context, resultMap);
         if (!isUsageMapValid(resultMap, hourlyBatteryLevelsPerDay)) {
             return null;
         }
@@ -653,7 +651,7 @@
         allUsageMap.put(SELECTED_INDEX_ALL,
                 generateBatteryDiffData(context, getBatteryHistListFromFromStatsService(context)));
         resultMap.put(SELECTED_INDEX_ALL, allUsageMap);
-        purgeFakeAndHiddenPackages(context, resultMap);
+        processBatteryDiffData(context, resultMap);
         return resultMap;
     }
 
@@ -1234,49 +1232,55 @@
         }
     }
 
-    // Removes low percentage data and fake usage data, which will be zero value.
-    private static void purgeFakeAndHiddenPackages(
+    // Process every battery diff data in the battery usage result map.
+    // (1) Removes low percentage data and fake usage data, which will be zero value.
+    // (2) Sets total consume power, so the usage percentage is updated.
+    // (3) Sorts the result.
+    private static void processBatteryDiffData(
             final Context context,
             final Map<Integer, Map<Integer, BatteryDiffData>> resultMap) {
-        final Set<CharSequence> backgroundUsageTimeHideList =
+        final Set<CharSequence> hideBackgroundUsageTimeSet =
                 FeatureFactory.getFactory(context)
                         .getPowerUsageFeatureProvider(context)
                         .getHideBackgroundUsageTimeSet(context);
-        final CharSequence[] notAllowShowEntryPackages =
+        final Set<CharSequence> hideApplicationSet =
                 FeatureFactory.getFactory(context)
                         .getPowerUsageFeatureProvider(context)
-                        .getHideApplicationEntries(context);
+                        .getHideApplicationSet(context);
         resultMap.keySet().forEach(dailyKey -> {
             final Map<Integer, BatteryDiffData> dailyUsageMap = resultMap.get(dailyKey);
-            dailyUsageMap.values().forEach(diffEntryLists -> {
-                if (diffEntryLists == null) {
+            dailyUsageMap.values().forEach(batteryDiffData -> {
+                if (batteryDiffData == null) {
                     return;
                 }
                 purgeFakeAndHiddenPackages(
-                        diffEntryLists.getAppDiffEntryList(), backgroundUsageTimeHideList,
-                        notAllowShowEntryPackages);
+                        batteryDiffData.getAppDiffEntryList(), hideBackgroundUsageTimeSet,
+                        hideApplicationSet);
                 purgeFakeAndHiddenPackages(
-                        diffEntryLists.getSystemDiffEntryList(), backgroundUsageTimeHideList,
-                        notAllowShowEntryPackages);
+                        batteryDiffData.getSystemDiffEntryList(), hideBackgroundUsageTimeSet,
+                        hideApplicationSet);
+                batteryDiffData.setTotalConsumePower();
+                batteryDiffData.sortEntries();
             });
         });
     }
 
     private static void purgeFakeAndHiddenPackages(
             final List<BatteryDiffEntry> entries,
-            final Set<CharSequence> backgroundUsageTimeHideList,
-            final CharSequence[] notAllowShowEntryPackages) {
+            final Set<CharSequence> hideBackgroundUsageTimeSet,
+            final Set<CharSequence> hideApplicationSet) {
         final Iterator<BatteryDiffEntry> iterator = entries.iterator();
         while (iterator.hasNext()) {
             final BatteryDiffEntry entry = iterator.next();
             final String packageName = entry.getPackageName();
+            if (packageName == null) {
+                continue;
+            }
             if (ConvertUtils.FAKE_PACKAGE_NAME.equals(packageName)
-                    || contains(packageName, notAllowShowEntryPackages)) {
+                    || hideApplicationSet.contains(packageName)) {
                 iterator.remove();
             }
-            if (packageName != null
-                    && !backgroundUsageTimeHideList.isEmpty()
-                    && contains(packageName, backgroundUsageTimeHideList)) {
+            if (hideBackgroundUsageTimeSet.contains(packageName)) {
                 entry.mBackgroundUsageTimeInMs = 0;
             }
         }
@@ -1465,18 +1469,6 @@
         return calendar.getTimeInMillis();
     }
 
-    /** Whether the Set contains the target. */
-    private static boolean contains(String target, Set<CharSequence> packageNames) {
-        if (target != null && packageNames != null) {
-            for (CharSequence packageName : packageNames) {
-                if (TextUtils.equals(target, packageName)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
     private static long getDiffValue(long v1, long v2, long v3) {
         return (v2 > v1 ? v2 - v1 : 0) + (v3 > v2 ? v3 - v2 : 0);
     }
@@ -1521,20 +1513,6 @@
         return sFakeCurrentTimeMillis > 0 ? sFakeCurrentTimeMillis : System.currentTimeMillis();
     }
 
-    /**
-     * @return Returns whether the target is in the CharSequence array.
-     */
-    private static boolean contains(String target, CharSequence[] packageNames) {
-        if (target != null && packageNames != null) {
-            for (CharSequence packageName : packageNames) {
-                if (TextUtils.equals(target, packageName)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
     private static void log(Context context, final String content, final long timestamp,
             final BatteryHistEntry entry) {
         if (DEBUG) {
diff --git a/src/com/android/settings/network/MobileNetworkRepository.java b/src/com/android/settings/network/MobileNetworkRepository.java
index 42f15c8..0c150af 100644
--- a/src/com/android/settings/network/MobileNetworkRepository.java
+++ b/src/com/android/settings/network/MobileNetworkRepository.java
@@ -15,6 +15,7 @@
  */
 package com.android.settings.network;
 
+import static android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING;
 import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_PRESENT;
 
 import static com.android.internal.telephony.TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED;
@@ -265,7 +266,7 @@
                         mPortIndex = portInfo.getPortIndex();
                     } else if (DEBUG) {
                         Log.d(TAG, "Can not get port index and physicalSlotIndex for subId "
-                                        + mSubId);
+                                + mSubId);
                     }
                 });
                 if (mPhysicalSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
@@ -324,7 +325,12 @@
             SubscriptionInfoEntity subInfoEntity =
                     convertToSubscriptionInfoEntity(context, info);
             if (subInfoEntity != null) {
-                mSubscriptionInfoMap.put(info.getSubscriptionId(), info);
+                int subId = info.getSubscriptionId();
+                mSubscriptionInfoMap.put(subId, info);
+                if (DEBUG) {
+                    Log.d(TAG, "convert subId " + subId + "to SubscriptionInfoEntity: "
+                            + subInfoEntity);
+                }
                 mMobileNetworkDatabase.insertSubsInfo(subInfoEntity);
                 mMetricsFeatureProvider.action(mContext,
                         SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_SUB_INFO);
@@ -401,13 +407,21 @@
     }
 
     public void insertUiccInfo() {
-        mMobileNetworkDatabase.insertUiccInfo(convertToUiccInfoEntity());
+        UiccInfoEntity uiccInfoEntity = convertToUiccInfoEntity();
+        if (DEBUG) {
+            Log.d(TAG, "uiccInfoEntity = " + uiccInfoEntity);
+        }
+        mMobileNetworkDatabase.insertUiccInfo(uiccInfoEntity);
         mMetricsFeatureProvider.action(mContext,
                 SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_UICC_INFO);
     }
 
     public void insertMobileNetworkInfo(Context context) {
-        mMobileNetworkDatabase.insertMobileNetworkInfo(convertToMobileNetworkInfoEntity(context));
+        MobileNetworkInfoEntity mobileNetworkInfoEntity = convertToMobileNetworkInfoEntity(context);
+        if (DEBUG) {
+            Log.d(TAG, "mobileNetworkInfoEntity = " + mobileNetworkInfoEntity);
+        }
+        mMobileNetworkDatabase.insertMobileNetworkInfo(mobileNetworkInfoEntity);
         mMetricsFeatureProvider.action(mContext,
                 SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_MOBILE_NETWORK_INFO);
     }
@@ -449,7 +463,8 @@
 
     @Override
     public void onSubscriptionsChanged() {
-        insertAvailableSubInfoToEntity(mSubscriptionManager.getAvailableSubscriptionInfoList());
+        insertAvailableSubInfoToEntity(
+                SubscriptionUtil.getSelectableSubscriptionInfoList(mContext));
     }
 
     private void insertAvailableSubInfoToEntity(List<SubscriptionInfo> availableInfoList) {
@@ -470,8 +485,14 @@
             for (SubscriptionInfo subInfo : infoArray) {
                 mSubscriptionInfoMap.remove(subInfo.getSubscriptionId());
                 if (DEBUG) {
-                    Log.d(TAG,
-                            "insert sudInfo " + subInfo.getSubscriptionId() + " to subInfoEntity");
+                    Log.d(TAG, "insert subInfo to subInfoEntity, subInfo = " + subInfo);
+                }
+                if (subInfo.isEmbedded()
+                        && subInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Do not insert the provision eSIM");
+                    }
+                    continue;
                 }
                 insertSubInfo(mContext, subInfo);
             }
diff --git a/src/com/android/settings/network/telephony/NullAlgorithmsPreferenceController.java b/src/com/android/settings/network/telephony/NullAlgorithmsPreferenceController.java
new file mode 100644
index 0000000..c4fdcbd
--- /dev/null
+++ b/src/com/android/settings/network/telephony/NullAlgorithmsPreferenceController.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2022 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 android.content.Context;
+import android.provider.DeviceConfig;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+/**
+ * Preference controller for "Allow Null Algorithms"
+ *
+ * <p>This preference controller is toggling null algorithms is not a per-sim operation.
+ */
+public class NullAlgorithmsPreferenceController extends TelephonyTogglePreferenceController {
+
+    // log tags have a char limit of 24 so we can't use the class name
+    private static final String LOG_TAG = "NullAlgosController";
+
+    private TelephonyManager mTelephonyManager;
+
+    /**
+     * Class constructor of "Allow Null Algorithms" toggle.
+     *
+     * @param context of settings
+     * @param key     assigned within UI entry of XML file
+     */
+    public NullAlgorithmsPreferenceController(Context context, String key) {
+        super(context, key);
+        mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+    }
+
+    /**
+     * Get the {@link com.android.settings.core.BasePreferenceController.AvailabilityStatus} for
+     * this preference given a {@code subId}. This dictates whether the setting is available on
+     * the device, and if it is not, offers some context as to why.
+     */
+    @Override
+    public int getAvailabilityStatus(int subId) {
+        if (mTelephonyManager == null) {
+            Log.w(LOG_TAG,
+                    "Telephony manager not yet initialized. Marking availability as "
+                            + "CONDITIONALLY_UNAVAILABLE");
+            mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+            return CONDITIONALLY_UNAVAILABLE;
+        }
+
+        if (!DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_CELLULAR_SECURITY,
+                TelephonyManager.PROPERTY_ENABLE_NULL_CIPHER_TOGGLE, false)) {
+            Log.i(LOG_TAG, "Null cipher toggle is disabled by DeviceConfig");
+            return CONDITIONALLY_UNAVAILABLE;
+        }
+
+        try {
+            mTelephonyManager.isNullCipherAndIntegrityPreferenceEnabled();
+        } catch (UnsupportedOperationException e) {
+            Log.i(LOG_TAG, "Null cipher enablement is unsupported: " + e.getMessage());
+            return UNSUPPORTED_ON_DEVICE;
+        }
+
+        return AVAILABLE;
+    }
+
+    /**
+     * Return {@code true} if null algorithms are currently allowed.
+     *
+     * <p><b>NOTE:</b> This method returns the active state of the preference controller and is not
+     * the parameter passed into {@link #setChecked(boolean)}, which is instead the requested future
+     * state.
+     */
+    @Override
+    public boolean isChecked() {
+        return mTelephonyManager.isNullCipherAndIntegrityPreferenceEnabled();
+    }
+
+    /**
+     * Called when a user preference changes on the toggle. We pass this info on to the Telephony
+     * Framework so that the modem can be updated with the user's preference.
+     *
+     * <p>See {@link com.android.settings.core.TogglePreferenceController#setChecked(boolean)} for
+     * details.
+     *
+     * @param isChecked The toggle value that we're being requested to enforce. A value of {@code
+     *                  false} denotes that null ciphers will be disabled by the modem after this
+     *                  function
+     *                  completes, if it is not already.
+     */
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        if (isChecked) {
+            Log.i(LOG_TAG, "Enabling null algorithms");
+        } else {
+            Log.i(LOG_TAG, "Disabling null algorithms");
+        }
+        mTelephonyManager.setNullCipherAndIntegrityEnabled(isChecked);
+        return true;
+    }
+}
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index 63c4a62..491d967 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -54,7 +54,6 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityManager;
 import android.widget.TextView;
 
 import androidx.annotation.StringRes;
@@ -67,7 +66,6 @@
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockscreenCredential;
-import com.android.settings.EncryptionInterstitial;
 import com.android.settings.EventLogTags;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
@@ -143,8 +141,6 @@
         @VisibleForTesting
         static final int CONFIRM_EXISTING_REQUEST = 100;
         @VisibleForTesting
-        static final int ENABLE_ENCRYPTION_REQUEST = 101;
-        @VisibleForTesting
         static final int CHOOSE_LOCK_REQUEST = 102;
         @VisibleForTesting
         static final int CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST = 103;
@@ -156,7 +152,6 @@
         private boolean mRequestGatekeeperPasswordHandle = false;
         private boolean mPasswordConfirmed = false;
         private boolean mWaitingForConfirmation = false;
-        private boolean mForChangeCredRequiredForBoot = false;
         private LockscreenCredential mUserPassword;
         private FingerprintManager mFingerprintManager;
         private FaceManager mFaceManager;
@@ -250,8 +245,6 @@
 
             mIsCallingAppAdmin = intent
                     .getBooleanExtra(EXTRA_KEY_IS_CALLING_APP_ADMIN, /* defValue= */ false);
-            mForChangeCredRequiredForBoot = arguments != null && arguments.getBoolean(
-                    ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT);
             mUserManager = UserManager.get(activity);
 
             if (arguments != null) {
@@ -299,10 +292,6 @@
 
             if (mPasswordConfirmed) {
                 updatePreferencesOrFinish(savedInstanceState != null);
-                if (mForChangeCredRequiredForBoot) {
-                    maybeEnableEncryption(mLockPatternUtils.getKeyguardStoredPasswordQuality(
-                            mUserId), false);
-                }
             } else if (!mWaitingForConfirmation) {
                 final ChooseLockSettingsHelper.Builder builder =
                         new ChooseLockSettingsHelper.Builder(activity, this);
@@ -447,58 +436,6 @@
             }
         }
 
-        /**
-         * If the device has encryption already enabled, then ask the user if they
-         * also want to encrypt the phone with this password.
-         *
-         * @param quality
-         * @param disabled
-         */
-        // TODO: why does this take disabled, its always called with a quality higher than
-        //  what makes sense with disabled == true
-        private void maybeEnableEncryption(int quality, boolean disabled) {
-            DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
-            if (UserManager.get(getActivity()).isAdminUser()
-                    && mUserId == UserHandle.myUserId()
-                    && LockPatternUtils.isDeviceEncryptionEnabled()
-                    && !LockPatternUtils.isFileEncryptionEnabled()
-                    && !dpm.getDoNotAskCredentialsOnBoot()) {
-                // Get the intent that the encryption interstitial should start for creating
-                // the new unlock method.
-                Intent unlockMethodIntent = getIntentForUnlockMethod(quality);
-                unlockMethodIntent.putExtra(
-                        ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT,
-                        mForChangeCredRequiredForBoot);
-                final Context context = getActivity();
-                // If accessibility is enabled and the user hasn't seen this dialog before, set the
-                // default state to agree with that which is compatible with accessibility
-                // (password not required).
-                final boolean accEn = AccessibilityManager.getInstance(context).isEnabled();
-                final boolean required = mLockPatternUtils.isCredentialRequiredToDecrypt(!accEn);
-                Intent intent = getEncryptionInterstitialIntent(context, quality, required,
-                        unlockMethodIntent);
-                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
-                        mForFingerprint);
-                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, mForFace);
-                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, mForBiometrics);
-                // If the caller requested Gatekeeper Password to be returned, we assume it came
-                // from biometric enrollment. This should be cleaned up, since requesting
-                // Gatekeeper Password should not imply it came from biometric setup/settings.
-                startActivityForResult(
-                        intent,
-                        mIsSetNewPassword && mRequestGatekeeperPasswordHandle
-                                ? CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST
-                                : ENABLE_ENCRYPTION_REQUEST);
-            } else {
-                if (mForChangeCredRequiredForBoot) {
-                    // Welp, couldn't change it. Oh well.
-                    finish();
-                    return;
-                }
-                updateUnlockMethodAndFinish(quality, disabled, false /* chooseLockSkipped */);
-            }
-        }
-
         @Override
         public void onActivityResult(int requestCode, int resultCode, Intent data) {
             super.onActivityResult(requestCode, resultCode, data);
@@ -509,17 +446,8 @@
                     ? data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)
                     : null;
                 updatePreferencesOrFinish(false /* isRecreatingActivity */);
-                if (mForChangeCredRequiredForBoot) {
-                    if (mUserPassword != null && !mUserPassword.isNone()) {
-                        maybeEnableEncryption(
-                                mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId), false);
-                    } else {
-                        finish();
-                    }
-                }
-            } else if (requestCode == CHOOSE_LOCK_REQUEST
-                    || requestCode == ENABLE_ENCRYPTION_REQUEST) {
-                if (resultCode != RESULT_CANCELED || mForChangeCredRequiredForBoot) {
+            } else if (requestCode == CHOOSE_LOCK_REQUEST) {
+                if (resultCode != RESULT_CANCELED) {
                     getActivity().setResult(resultCode, data);
                     finish();
                 } else {
@@ -559,9 +487,6 @@
                 getActivity().setResult(Activity.RESULT_CANCELED);
                 finish();
             }
-            if (requestCode == Activity.RESULT_CANCELED && mForChangeCredRequiredForBoot) {
-                finish();
-            }
         }
 
         protected Intent getBiometricEnrollIntent(Context context) {
@@ -590,8 +515,8 @@
             if (StorageManager.isFileEncrypted()) {
                 quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
             } else {
-                // For non-file encrypted devices we need to show encryption interstitial, so always
-                // show the lock type picker and ignore PASSWORD_TYPE_KEY.
+                // For unencrypted devices, always show the lock type picker and ignore
+                // PASSWORD_TYPE_KEY.
                 Log.i(TAG, "Ignoring PASSWORD_TYPE_KEY because device is not file encrypted");
             }
             if (quality == -1) {
@@ -821,12 +746,6 @@
             return builder.build();
         }
 
-        protected Intent getEncryptionInterstitialIntent(Context context, int quality,
-                boolean required, Intent unlockMethodIntent) {
-            return EncryptionInterstitial.createStartIntent(context, quality, required,
-                    unlockMethodIntent);
-        }
-
         /**
          * Invokes an activity to change the user's pattern, password or PIN based on given quality
          * and minimum quality specified by DevicePolicyManager. If quality is
@@ -992,16 +911,14 @@
                 switch (lock) {
                     case NONE:
                     case SWIPE:
-                        updateUnlockMethodAndFinish(
-                                lock.defaultQuality,
-                                lock == ScreenLockType.NONE,
-                                false /* chooseLockSkipped */);
-                        return true;
                     case PATTERN:
                     case PIN:
                     case PASSWORD:
                     case MANAGED:
-                        maybeEnableEncryption(lock.defaultQuality, false);
+                        updateUnlockMethodAndFinish(
+                                lock.defaultQuality,
+                                lock == ScreenLockType.NONE,
+                                false /* chooseLockSkipped */);
                         return true;
                 }
             }
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index 265cee8..648b644 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -86,7 +86,6 @@
 import com.android.internal.widget.PasswordValidationError;
 import com.android.internal.widget.TextViewInputDisabler;
 import com.android.internal.widget.VerifyCredentialResponse;
-import com.android.settings.EncryptionInterstitial;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.SetupWizardUtils;
@@ -124,7 +123,6 @@
         public IntentBuilder(Context context) {
             mIntent = new Intent(context, ChooseLockPassword.class);
             mIntent.putExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, false);
-            mIntent.putExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, false);
         }
 
         /**
@@ -461,21 +459,6 @@
             mMinMetrics = intent.getParcelableExtra(EXTRA_KEY_MIN_METRICS);
             if (mMinMetrics == null) mMinMetrics = new PasswordMetrics(CREDENTIAL_TYPE_NONE);
 
-            if (intent.getBooleanExtra(
-                    ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, false)) {
-                SaveAndFinishWorker w = new SaveAndFinishWorker();
-                final boolean required = getActivity().getIntent().getBooleanExtra(
-                        EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
-                LockscreenCredential currentCredential = intent.getParcelableExtra(
-                        ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
-
-                final LockPatternUtils utils = new LockPatternUtils(getActivity());
-
-                w.setBlocking(true);
-                w.setListener(this);
-                w.start(utils, required, false /* requestGatekeeperPassword */, currentCredential,
-                        currentCredential, mUserId);
-            }
             mTextChangedHandler = new TextChangedHandler();
         }
 
@@ -968,8 +951,6 @@
             getFragmentManager().executePendingTransactions();
 
             final Intent intent = getActivity().getIntent();
-            final boolean required = intent.getBooleanExtra(
-                    EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
             if (mUnificationProfileId != UserHandle.USER_NULL) {
                 try (LockscreenCredential profileCredential = (LockscreenCredential)
                         intent.getParcelableExtra(EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL)) {
@@ -977,7 +958,7 @@
                             profileCredential);
                 }
             }
-            mSaveAndFinishWorker.start(mLockPatternUtils, required, mRequestGatekeeperPassword,
+            mSaveAndFinishWorker.start(mLockPatternUtils, mRequestGatekeeperPassword,
                     mChosenPassword, mCurrentCredential, mUserId);
         }
 
@@ -1036,10 +1017,10 @@
         private LockscreenCredential mChosenPassword;
         private LockscreenCredential mCurrentCredential;
 
-        public void start(LockPatternUtils utils, boolean required,
-                boolean requestGatekeeperPassword, LockscreenCredential chosenPassword,
-                LockscreenCredential currentCredential, int userId) {
-            prepare(utils, required, requestGatekeeperPassword, userId);
+        public void start(LockPatternUtils utils, boolean requestGatekeeperPassword,
+                LockscreenCredential chosenPassword, LockscreenCredential currentCredential,
+                int userId) {
+            prepare(utils, requestGatekeeperPassword, userId);
 
             mChosenPassword = chosenPassword;
             mCurrentCredential = currentCredential != null ? currentCredential
diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java
index 07c533f..9cdbaed 100644
--- a/src/com/android/settings/password/ChooseLockPattern.java
+++ b/src/com/android/settings/password/ChooseLockPattern.java
@@ -54,7 +54,6 @@
 import com.android.internal.widget.LockPatternView.DisplayMode;
 import com.android.internal.widget.LockscreenCredential;
 import com.android.internal.widget.VerifyCredentialResponse;
-import com.android.settings.EncryptionInterstitial;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.SetupWizardUtils;
@@ -106,7 +105,6 @@
 
         public IntentBuilder(Context context) {
             mIntent = new Intent(context, ChooseLockPattern.class);
-            mIntent.putExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, false);
             mIntent.putExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, false);
         }
 
@@ -458,18 +456,6 @@
 
             mLockPatternUtils = new LockPatternUtils(getActivity());
 
-            if (intent.getBooleanExtra(
-                    ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, false)) {
-                SaveAndFinishWorker w = new SaveAndFinishWorker();
-                final boolean required = getActivity().getIntent().getBooleanExtra(
-                        EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
-                LockscreenCredential current = intent.getParcelableExtra(
-                        ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
-                w.setBlocking(true);
-                w.setListener(this);
-                w.start(mLockPatternUtils, required, false /* requestGatekeeperPassword */, current,
-                        current, mUserId);
-            }
             mForFingerprint = intent.getBooleanExtra(
                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
             mForFace = intent.getBooleanExtra(
@@ -854,8 +840,6 @@
             getFragmentManager().executePendingTransactions();
 
             final Intent intent = getActivity().getIntent();
-            final boolean required = intent.getBooleanExtra(
-                    EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
             if (intent.hasExtra(EXTRA_KEY_UNIFICATION_PROFILE_ID)) {
                 try (LockscreenCredential profileCredential = (LockscreenCredential)
                         intent.getParcelableExtra(EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL)) {
@@ -865,8 +849,8 @@
                             profileCredential);
                 }
             }
-            mSaveAndFinishWorker.start(mLockPatternUtils, required,
-                    mRequestGatekeeperPassword, mChosenPattern, mCurrentCredential, mUserId);
+            mSaveAndFinishWorker.start(mLockPatternUtils, mRequestGatekeeperPassword,
+                    mChosenPattern, mCurrentCredential, mUserId);
         }
 
         @Override
@@ -896,10 +880,10 @@
         private LockscreenCredential mCurrentCredential;
         private boolean mLockVirgin;
 
-        public void start(LockPatternUtils utils, boolean credentialRequired,
-                boolean requestGatekeeperPassword, LockscreenCredential chosenPattern,
-                LockscreenCredential currentCredential, int userId) {
-            prepare(utils, credentialRequired, requestGatekeeperPassword, userId);
+        public void start(LockPatternUtils utils, boolean requestGatekeeperPassword,
+                LockscreenCredential chosenPattern, LockscreenCredential currentCredential,
+                int userId) {
+            prepare(utils, requestGatekeeperPassword, userId);
 
             mCurrentCredential = currentCredential != null ? currentCredential
                     : LockscreenCredential.createNone();
diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java
index 85c203d..6ccf7be 100644
--- a/src/com/android/settings/password/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java
@@ -58,7 +58,6 @@
     public static final String EXTRA_KEY_FOR_FACE = "for_face";
     // For the paths where multiple biometric sensors exist
     public static final String EXTRA_KEY_FOR_BIOMETRICS = "for_biometrics";
-    public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
     public static final String EXTRA_KEY_FOREGROUND_ONLY = "foreground_only";
     public static final String EXTRA_KEY_REQUEST_GK_PW_HANDLE = "request_gk_pw_handle";
     // Gatekeeper password handle, which can subsequently be used to generate Gatekeeper
diff --git a/src/com/android/settings/password/SaveChosenLockWorkerBase.java b/src/com/android/settings/password/SaveChosenLockWorkerBase.java
index 980b022..4864941 100644
--- a/src/com/android/settings/password/SaveChosenLockWorkerBase.java
+++ b/src/com/android/settings/password/SaveChosenLockWorkerBase.java
@@ -16,12 +16,10 @@
 
 package com.android.settings.password;
 
-import android.content.Context;
 import android.content.Intent;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.util.Pair;
 import android.widget.Toast;
 
@@ -68,21 +66,12 @@
         }
     }
 
-    protected void prepare(LockPatternUtils utils, boolean credentialRequired,
-            boolean requestGatekeeperPassword, int userId) {
+    protected void prepare(LockPatternUtils utils, boolean requestGatekeeperPassword, int userId) {
         mUtils = utils;
         mUserId = userId;
         mRequestGatekeeperPassword = requestGatekeeperPassword;
         // This will be a no-op for non managed profiles.
         mWasSecureBefore = mUtils.isSecure(mUserId);
-
-        Context context = getContext();
-        // If context is null, we're being invoked to change the setCredentialRequiredToDecrypt,
-        // and we made sure that this is the primary user already.
-        if (context == null || UserManager.get(context).getUserInfo(mUserId).isPrimary()) {
-            mUtils.setCredentialRequiredToDecrypt(credentialRequired);
-        }
-
         mFinished = false;
         mResultData = null;
     }
diff --git a/src/com/android/settings/password/SetupChooseLockGeneric.java b/src/com/android/settings/password/SetupChooseLockGeneric.java
index 968af32..a3ae78e 100644
--- a/src/com/android/settings/password/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/password/SetupChooseLockGeneric.java
@@ -38,7 +38,6 @@
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
-import com.android.settings.SetupEncryptionInterstitial;
 import com.android.settings.SetupWizardUtils;
 import com.android.settings.utils.SettingsDividerItemDecoration;
 
@@ -217,15 +216,6 @@
         }
 
         @Override
-        protected Intent getEncryptionInterstitialIntent(Context context, int quality,
-                boolean required, Intent unlockMethodIntent) {
-            Intent intent = SetupEncryptionInterstitial.createStartIntent(context, quality,
-                    required, unlockMethodIntent);
-            SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
-            return intent;
-        }
-
-        @Override
         protected Intent getBiometricEnrollIntent(Context context) {
             final Intent intent = super.getBiometricEnrollIntent(context);
             SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
diff --git a/src/com/android/settings/spa/app/AllAppList.kt b/src/com/android/settings/spa/app/AllAppList.kt
index cd116c1..05f77ed 100644
--- a/src/com/android/settings/spa/app/AllAppList.kt
+++ b/src/com/android/settings/spa/app/AllAppList.kt
@@ -36,6 +36,7 @@
 import com.android.settingslib.spaprivileged.template.app.AppList
 import com.android.settingslib.spaprivileged.template.app.AppListInput
 import com.android.settingslib.spaprivileged.template.app.AppListItem
+import com.android.settingslib.spaprivileged.template.app.AppListItemModel
 import com.android.settingslib.spaprivileged.template.app.AppListPage
 import com.android.settingslib.spaprivileged.template.app.getStorageSize
 import kotlinx.coroutines.flow.Flow
@@ -70,9 +71,7 @@
         showInstantApps = true,
         moreOptions = { ResetAppPreferences(resetAppDialogPresenter::open) },
         appList = appList,
-    ) {
-        AppListItem(onClick = AppInfoSettingsProvider.navigator(app = record.app))
-    }
+    )
 }
 
 data class AppRecordWithSize(
@@ -88,4 +87,9 @@
 
     @Composable
     override fun getSummary(option: Int, record: AppRecordWithSize) = record.app.getSummary()
+
+    @Composable
+    override fun AppListItemModel<AppRecordWithSize>.AppItem() {
+        AppListItem(onClick = AppInfoSettingsProvider.navigator(app = record.app))
+    }
 }
diff --git a/src/com/android/settings/spa/development/UsageStats.kt b/src/com/android/settings/spa/development/UsageStats.kt
index d98ef59..b681d75 100644
--- a/src/com/android/settings/spa/development/UsageStats.kt
+++ b/src/com/android/settings/spa/development/UsageStats.kt
@@ -21,11 +21,7 @@
 import androidx.compose.ui.res.stringResource
 import com.android.settings.R
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
-import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.compose.rememberContext
-import com.android.settingslib.spa.widget.preference.Preference
-import com.android.settingslib.spa.widget.preference.PreferenceModel
-import com.android.settingslib.spaprivileged.template.app.AppListItem
 import com.android.settingslib.spaprivileged.template.app.AppListPage
 
 object UsageStatsPageProvider : SettingsPageProvider {
@@ -37,14 +33,6 @@
             title = stringResource(R.string.testing_usage_stats),
             listModel = rememberContext(::UsageStatsListModel),
             primaryUserOnly = true,
-        ) { AppListItem {} }
-    }
-
-    @Composable
-    fun EntryItem() {
-        Preference(object : PreferenceModel {
-            override val title = stringResource(R.string.testing_usage_stats)
-            override val onClick = navigator(name)
-        })
+        )
     }
 }
diff --git a/src/com/android/settings/spa/notification/AppListNotifications.kt b/src/com/android/settings/spa/notification/AppListNotifications.kt
index 0e6c5e2..c1e5d64 100644
--- a/src/com/android/settings/spa/notification/AppListNotifications.kt
+++ b/src/com/android/settings/spa/notification/AppListNotifications.kt
@@ -16,27 +16,17 @@
 
 package com.android.settings.spa.notification
 
-import android.app.settings.SettingsEnums
-import android.content.Context
-import android.content.pm.ApplicationInfo
 import android.os.Bundle
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.livedata.observeAsState
-import androidx.compose.runtime.produceState
-import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
 import com.android.settings.R
-import com.android.settings.applications.AppInfoBase
-import com.android.settings.notification.app.AppNotificationSettings
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.compose.rememberContext
 import com.android.settingslib.spa.framework.compose.toState
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
-import com.android.settingslib.spaprivileged.template.app.AppListItemModel
 import com.android.settingslib.spaprivileged.template.app.AppListPage
-import com.android.settingslib.spaprivileged.template.app.AppListSwitchItem
 
 object AppListNotificationsPageProvider : SettingsPageProvider {
     override val name = "AppListNotifications"
@@ -46,7 +36,7 @@
         AppListPage(
             title = stringResource(R.string.app_notifications_title),
             listModel = rememberContext(::AppNotificationsListModel),
-        ) { AppNotificationsItem() }
+        )
     }
 
     @Composable
@@ -58,32 +48,3 @@
         })
     }
 }
-
-@Composable
-private fun AppListItemModel<AppNotificationsRecord>.AppNotificationsItem() {
-    val appNotificationsRepository = rememberContext(::AppNotificationRepository)
-    val context = LocalContext.current
-    AppListSwitchItem(
-        onClick = {
-            navigateToAppNotificationSettings(
-                context = context,
-                app = record.app,
-            )
-        },
-        checked = record.controller.isEnabled.observeAsState(),
-        changeable = produceState(initialValue = false) {
-            value = appNotificationsRepository.isChangeable(record.app)
-        },
-        onCheckedChange = record.controller::setEnabled,
-    )
-}
-
-private fun navigateToAppNotificationSettings(context: Context, app: ApplicationInfo) {
-    AppInfoBase.startAppInfoFragment(
-        AppNotificationSettings::class.java,
-        context.getString(R.string.notifications_title),
-        app,
-        context,
-        SettingsEnums.MANAGE_APPLICATIONS_NOTIFICATIONS,
-    )
-}
diff --git a/src/com/android/settings/spa/notification/AppNotificationsListModel.kt b/src/com/android/settings/spa/notification/AppNotificationsListModel.kt
index ff951fc..c7baa03 100644
--- a/src/com/android/settings/spa/notification/AppNotificationsListModel.kt
+++ b/src/com/android/settings/spa/notification/AppNotificationsListModel.kt
@@ -16,11 +16,16 @@
 
 package com.android.settings.spa.notification
 
+import android.app.settings.SettingsEnums
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import android.icu.text.RelativeDateTimeFormatter
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.produceState
 import com.android.settings.R
+import com.android.settings.applications.AppInfoBase
+import com.android.settings.notification.app.AppNotificationSettings
 import com.android.settings.spa.notification.SpinnerItem.Companion.toSpinnerItem
 import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.util.asyncFilter
@@ -28,6 +33,8 @@
 import com.android.settingslib.spaprivileged.model.app.AppEntry
 import com.android.settingslib.spaprivileged.model.app.AppListModel
 import com.android.settingslib.spaprivileged.model.app.AppRecord
+import com.android.settingslib.spaprivileged.template.app.AppListItemModel
+import com.android.settingslib.spaprivileged.template.app.AppListSwitchItem
 import com.android.settingslib.utils.StringUtil
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
@@ -114,6 +121,28 @@
             )
         }
     }
+
+    @Composable
+    override fun AppListItemModel<AppNotificationsRecord>.AppItem() {
+        AppListSwitchItem(
+            onClick = { navigateToAppNotificationSettings(app = record.app) },
+            checked = record.controller.isEnabled.observeAsState(),
+            changeable = produceState(initialValue = false) {
+                value = repository.isChangeable(record.app)
+            },
+            onCheckedChange = record.controller::setEnabled,
+        )
+    }
+
+    private fun navigateToAppNotificationSettings(app: ApplicationInfo) {
+        AppInfoBase.startAppInfoFragment(
+            AppNotificationSettings::class.java,
+            context.getString(R.string.notifications_title),
+            app,
+            context,
+            SettingsEnums.MANAGE_APPLICATIONS_NOTIFICATIONS,
+        )
+    }
 }
 
 private enum class SpinnerItem(val stringResId: Int) {
diff --git a/src/com/android/settings/spa/system/AppLanguages.kt b/src/com/android/settings/spa/system/AppLanguages.kt
index bcb6535..f53a63d 100644
--- a/src/com/android/settings/spa/system/AppLanguages.kt
+++ b/src/com/android/settings/spa/system/AppLanguages.kt
@@ -16,17 +16,13 @@
 
 package com.android.settings.spa.system
 
-import android.content.Intent
-import android.net.Uri
 import android.os.Bundle
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.padding
 import androidx.compose.runtime.Composable
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
 import com.android.settings.R
-import com.android.settings.localepicker.AppLocalePickerActivity
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.framework.compose.rememberContext
@@ -35,8 +31,6 @@
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
 import com.android.settingslib.spa.widget.ui.SettingsBody
-import com.android.settingslib.spaprivileged.template.app.AppListItem
-import com.android.settingslib.spaprivileged.template.app.AppListItemModel
 import com.android.settingslib.spaprivileged.template.app.AppListPage
 
 object AppLanguagesPageProvider : SettingsPageProvider {
@@ -52,7 +46,7 @@
                     SettingsBody(stringResource(R.string.desc_app_locale_selection_supported))
                 }
             },
-        ) { AppLanguageItem() }
+        )
     }
 
     @Composable
@@ -64,15 +58,3 @@
         })
     }
 }
-
-@Composable
-private fun AppListItemModel<AppLanguagesRecord>.AppLanguageItem() {
-    val context = LocalContext.current
-    AppListItem {
-        val intent = Intent(context, AppLocalePickerActivity::class.java).apply {
-            data = Uri.parse("package:${record.app.packageName}")
-            putExtra("uid", record.app.uid)
-        }
-        context.startActivity(intent)
-    }
-}
diff --git a/src/com/android/settings/spa/system/AppLanguagesListModel.kt b/src/com/android/settings/spa/system/AppLanguagesListModel.kt
index eea72f2..4aa4c7a 100644
--- a/src/com/android/settings/spa/system/AppLanguagesListModel.kt
+++ b/src/com/android/settings/spa/system/AppLanguagesListModel.kt
@@ -17,8 +17,10 @@
 package com.android.settings.spa.system
 
 import android.content.Context
+import android.content.Intent
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageManager
+import android.net.Uri
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
@@ -28,56 +30,73 @@
 import com.android.settings.R
 import com.android.settings.applications.AppLocaleUtil
 import com.android.settings.applications.appinfo.AppLocaleDetails
+import com.android.settings.localepicker.AppLocalePickerActivity
+import com.android.settingslib.spa.framework.util.filterItem
 import com.android.settingslib.spaprivileged.model.app.AppListModel
 import com.android.settingslib.spaprivileged.model.app.AppRecord
+import com.android.settingslib.spaprivileged.template.app.AppListItem
+import com.android.settingslib.spaprivileged.template.app.AppListItemModel
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.map
 
 data class AppLanguagesRecord(
     override val app: ApplicationInfo,
-    val isAppLocaleSupported: Boolean
+    val isAppLocaleSupported: Boolean,
 ) : AppRecord
 
 class AppLanguagesListModel(private val context: Context) : AppListModel<AppLanguagesRecord> {
-    private val now = System.currentTimeMillis()
     private val packageManager = context.packageManager
 
     override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
         userIdFlow.map { userId ->
             packageManager.queryIntentActivitiesAsUser(
-                    AppLocaleUtil.LAUNCHER_ENTRY_INTENT,
-                    PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA.toLong()),
-                    userId,
-                )
+                AppLocaleUtil.LAUNCHER_ENTRY_INTENT,
+                PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA.toLong()),
+                userId,
+            )
         }.combine(appListFlow) { resolveInfos, appList ->
             appList.map { app ->
-                AppLanguagesRecord(app,
-                    AppLocaleUtil.canDisplayLocaleUi(context,
-                    app, resolveInfos))
+                AppLanguagesRecord(
+                    app = app,
+                    isAppLocaleSupported = AppLocaleUtil.canDisplayLocaleUi(
+                        context, app, resolveInfos
+                    ),
+                )
             }
         }
 
     override fun filter(
         userIdFlow: Flow<Int>,
         option: Int,
-        recordListFlow: Flow<List<AppLanguagesRecord>>
-    ) = recordListFlow.map { recordList ->
-        recordList.filter { it.isAppLocaleSupported }
-    }
+        recordListFlow: Flow<List<AppLanguagesRecord>>,
+    ) = recordListFlow.filterItem { it.isAppLocaleSupported }
 
     @OptIn(ExperimentalLifecycleComposeApi::class)
     @Composable
-    override fun getSummary(option: Int, record: AppLanguagesRecord): State<String>? =
+    override fun getSummary(option: Int, record: AppLanguagesRecord): State<String> =
         remember(record.app) {
             flow {
                 emit(getSummary(record.app))
-            }
+            }.flowOn(Dispatchers.IO)
         }.collectAsStateWithLifecycle(initialValue = stringResource(R.string.summary_placeholder))
 
     private fun getSummary(app: ApplicationInfo): String =
         AppLocaleDetails.getAppDefaultLocale(context, app.packageName)?.let {
             AppLocaleDetails.getSummary(context, app).toString()
         } ?: context.getString(R.string.preference_of_system_locale_summary)
-}
\ No newline at end of file
+
+    @Composable
+    override fun AppListItemModel<AppLanguagesRecord>.AppItem() {
+        AppListItem {
+            val intent = Intent(context, AppLocalePickerActivity::class.java).apply {
+                data = Uri.parse("package:${record.app.packageName}")
+                this.putExtra("uid", record.app.uid)
+            }
+            context.startActivity(intent)
+        }
+    }
+}
diff --git a/src/com/android/settings/wifi/helper/SavedWifiHelper.java b/src/com/android/settings/wifi/helper/SavedWifiHelper.java
new file mode 100644
index 0000000..ebc9728
--- /dev/null
+++ b/src/com/android/settings/wifi/helper/SavedWifiHelper.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2022 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.helper;
+
+import android.annotation.TestApi;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+
+import com.android.wifitrackerlib.SavedNetworkTracker;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Helper for saved Wi-Fi networks tracker from WifiTrackerLib.
+ */
+public class SavedWifiHelper extends WifiTrackerBase {
+    private static final String TAG = "SavedWifiHelper";
+
+    private static final Object sInstanceLock = new Object();
+    @TestApi
+    @GuardedBy("sInstanceLock")
+    private static Map<Context, SavedWifiHelper> sTestInstances;
+
+    protected SavedNetworkTracker mSavedNetworkTracker;
+
+    /**
+     * Static method to create a SavedWifiHelper class.
+     *
+     * @param context   The Context this is associated with.
+     * @param lifecycle The lifecycle this is associated with.
+     * @return an instance of {@link SavedWifiHelper} object.
+     */
+    public static SavedWifiHelper getInstance(@NonNull Context context,
+            @NonNull Lifecycle lifecycle) {
+        synchronized (sInstanceLock) {
+            if (sTestInstances != null && sTestInstances.containsKey(context)) {
+                SavedWifiHelper testInstance = sTestInstances.get(context);
+                Log.w(TAG, "The context owner use a test instance:" + testInstance);
+                return testInstance;
+            }
+            return new SavedWifiHelper(context, lifecycle);
+        }
+    }
+
+    /**
+     * A convenience method to set pre-prepared instance or mock(SavedWifiHelper.class) for
+     * testing.
+     *
+     * @param context  The Context this is associated with.
+     * @param instance of {@link SavedWifiHelper} object.
+     * @hide
+     */
+    @TestApi
+    @VisibleForTesting
+    public static void setTestInstance(@NonNull Context context, SavedWifiHelper instance) {
+        synchronized (sInstanceLock) {
+            if (sTestInstances == null) sTestInstances = new ConcurrentHashMap<>();
+            Log.w(TAG, "Set a test instance by context:" + context);
+            sTestInstances.put(context, instance);
+        }
+    }
+
+    public SavedWifiHelper(@NonNull Context context, @NonNull Lifecycle lifecycle) {
+        this(context, lifecycle, null);
+    }
+
+    @VisibleForTesting
+    protected SavedWifiHelper(@NonNull Context context, @NonNull Lifecycle lifecycle,
+            SavedNetworkTracker saveNetworkTracker) {
+        super(lifecycle);
+        mSavedNetworkTracker = (saveNetworkTracker != null) ? saveNetworkTracker
+                : createSavedNetworkTracker(context, lifecycle);
+    }
+
+    @VisibleForTesting
+    protected SavedNetworkTracker createSavedNetworkTracker(@NonNull Context context,
+            @NonNull Lifecycle lifecycle) {
+        return new SavedNetworkTracker(lifecycle, context.getApplicationContext(),
+                context.getApplicationContext().getSystemService(WifiManager.class),
+                context.getApplicationContext().getSystemService(ConnectivityManager.class),
+                new Handler(Looper.getMainLooper()),
+                getWorkerThreadHandler(),
+                ELAPSED_REALTIME_CLOCK,
+                MAX_SCAN_AGE_MILLIS,
+                SCAN_INTERVAL_MILLIS,
+                null /* SavedNetworkTrackerCallback */);
+    }
+
+    @Override
+    protected String getTag() {
+        return TAG;
+    }
+
+    public SavedNetworkTracker getSavedNetworkTracker() {
+        return mSavedNetworkTracker;
+    }
+
+    /**
+     * Returns true when the certificate is being used by a saved network or network suggestion.
+     */
+    public boolean isCertificateInUse(String certAlias) {
+        return mSavedNetworkTracker.isCertificateRequired(certAlias);
+    }
+
+    /**
+     * Returns a list of network names which is using the certificate alias.
+     *
+     * @return a list of network names.
+     */
+    public List<String> getCertificateNetworkNames(String certAlias) {
+        return mSavedNetworkTracker.getCertificateRequesterNames(certAlias);
+    }
+}
diff --git a/src/com/android/settings/wifi/helper/WifiTrackerBase.java b/src/com/android/settings/wifi/helper/WifiTrackerBase.java
new file mode 100644
index 0000000..19be76a
--- /dev/null
+++ b/src/com/android/settings/wifi/helper/WifiTrackerBase.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 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.helper;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Process;
+import android.os.SimpleClock;
+import android.os.SystemClock;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+
+import java.time.Clock;
+import java.time.ZoneOffset;
+
+/**
+ * Base class for the WifiTrackerLib related classes.
+ */
+public class WifiTrackerBase implements DefaultLifecycleObserver {
+    private static final String TAG = "WifiTrackerBase";
+
+    // Max age of tracked WifiEntries
+    protected static final long MAX_SCAN_AGE_MILLIS = 15_000;
+    // Interval between initiating Wi-Fi Tracker scans
+    protected static final long SCAN_INTERVAL_MILLIS = 10_000;
+    // Clock used for evaluating the age of scans
+    protected static final Clock ELAPSED_REALTIME_CLOCK = new SimpleClock(ZoneOffset.UTC) {
+        @Override
+        public long millis() {
+            return SystemClock.elapsedRealtime();
+        }
+    };
+
+    @VisibleForTesting
+    protected HandlerThread mWorkerThread;
+
+    public WifiTrackerBase(@NonNull Lifecycle lifecycle) {
+        this(lifecycle, null /* handlerThread */);
+    }
+
+    @VisibleForTesting
+    protected WifiTrackerBase(@NonNull Lifecycle lifecycle, HandlerThread handlerThread) {
+        lifecycle.addObserver(this);
+        mWorkerThread = (handlerThread != null) ? handlerThread :
+                new HandlerThread(getTag()
+                        + "{" + Integer.toHexString(System.identityHashCode(this)) + "}",
+                        Process.THREAD_PRIORITY_BACKGROUND);
+        mWorkerThread.start();
+    }
+
+    protected String getTag() {
+        return TAG;
+    }
+
+    @Override
+    public void onDestroy(@NonNull LifecycleOwner owner) {
+        mWorkerThread.quit();
+    }
+
+    /** Returns the worker thread handler. */
+    public Handler getWorkerThreadHandler() {
+        return mWorkerThread.getThreadHandler();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderControllerTest.java
new file mode 100644
index 0000000..27b1de5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderControllerTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2022 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.connecteddevice.stylus;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.hardware.BatteryState;
+import android.hardware.input.InputManager;
+import android.os.Bundle;
+import android.view.InputDevice;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settingslib.widget.LayoutPreference;
+
+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;
+
+@RunWith(RobolectricTestRunner.class)
+public class StylusUsiHeaderControllerTest {
+
+    private Context mContext;
+    private StylusUsiHeaderController mController;
+    private LayoutPreference mLayoutPreference;
+    private PreferenceScreen mScreen;
+    private InputDevice mInputDevice;
+
+    @Mock
+    private InputManager mInputManager;
+    @Mock
+    private BatteryState mBatteryState;
+    @Mock
+    private Bundle mBundle;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        InputDevice device = new InputDevice.Builder().setId(1).setSources(
+                InputDevice.SOURCE_BLUETOOTH_STYLUS).build();
+        mInputDevice = spy(device);
+        when(mInputDevice.getBatteryState()).thenReturn(mBatteryState);
+        when(mBatteryState.getCapacity()).thenReturn(1f);
+        when(mBatteryState.isPresent()).thenReturn(true);
+
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getSystemService(InputManager.class)).thenReturn(mInputManager);
+        mController = new StylusUsiHeaderController(mContext, mInputDevice);
+
+        PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        mLayoutPreference = new LayoutPreference(mContext,
+                LayoutInflater.from(mContext).inflate(R.layout.advanced_bt_entity_header, null));
+        mLayoutPreference.setKey(mController.getPreferenceKey());
+
+        mScreen = preferenceManager.createPreferenceScreen(mContext);
+        mScreen.addPreference(mLayoutPreference);
+
+    }
+
+    @Test
+    public void onCreate_registersBatteryListener() {
+        mController.onCreate(mBundle);
+
+        verify(mInputManager).addInputDeviceBatteryListener(mInputDevice.getId(),
+                mContext.getMainExecutor(),
+                mController);
+    }
+
+    @Test
+    public void onDestroy_unregistersBatteryListener() {
+        mController.onDestroy();
+
+        verify(mInputManager).removeInputDeviceBatteryListener(mInputDevice.getId(),
+                mController);
+    }
+
+    @Test
+    public void displayPreference_showsCorrectTitle() {
+        mController.displayPreference(mScreen);
+
+        assertThat(((TextView) mLayoutPreference.findViewById(
+                R.id.entity_header_title)).getText().toString()).isEqualTo(
+                mContext.getString(R.string.stylus_usi_header_title));
+    }
+
+    @Test
+    public void displayPreference_hasBattery_showsCorrectBatterySummary() {
+        mController.displayPreference(mScreen);
+
+        assertThat(mLayoutPreference.findViewById(
+                R.id.entity_header_summary).getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(((TextView) mLayoutPreference.findViewById(
+                R.id.entity_header_summary)).getText().toString()).isEqualTo(
+                "100%");
+    }
+
+    @Test
+    public void displayPreference_noBattery_showsEmptySummary() {
+        when(mBatteryState.isPresent()).thenReturn(false);
+
+        mController.displayPreference(mScreen);
+
+        assertThat(mLayoutPreference.findViewById(
+                R.id.entity_header_summary).getVisibility()).isEqualTo(View.INVISIBLE);
+    }
+
+    @Test
+    public void displayPreference_invalidCapacity_showsEmptySummary() {
+        when(mBatteryState.getCapacity()).thenReturn(-1f);
+
+        mController.displayPreference(mScreen);
+
+        assertThat(mLayoutPreference.findViewById(
+                R.id.entity_header_summary).getVisibility()).isEqualTo(View.INVISIBLE);
+    }
+
+    @Test
+    public void onBatteryStateChanged_updatesSummary() {
+        mController.displayPreference(mScreen);
+
+        when(mBatteryState.getCapacity()).thenReturn(0.2f);
+        mController.onBatteryStateChanged(mInputDevice.getId(),
+                System.currentTimeMillis(), mBatteryState);
+
+        assertThat(((TextView) mLayoutPreference.findViewById(
+                R.id.entity_header_summary)).getText().toString()).isEqualTo(
+                "20%");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java
index af95f15..eb4b598 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java
@@ -65,8 +65,8 @@
     private static final String STATUS_CHARGING_NO_TIME = "50% - charging";
     private static final String STATUS_CHARGING_TIME = "50% - 0 min left until full";
     private static final String STATUS_NOT_CHARGING = "Not charging";
-    private static final String STATUS_CHARGING_FUTURE_BYPASS = "50% - Charging to 12%";
-    private static final String STATUS_CHARGING_PAUSED = "50% - Charging paused";
+    private static final String STATUS_CHARGING_FUTURE_BYPASS = "50% - Charging optimized";
+    private static final String STATUS_CHARGING_PAUSED = "50% - Charging optimized";
     private static final long REMAINING_TIME_NULL = -1;
     private static final long REMAINING_TIME = 2;
     // Strings are defined in frameworks/base/packages/SettingsLib/res/values/strings.xml
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTipTest.java
index 69d5477..e897a1c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTipTest.java
@@ -44,8 +44,6 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.shadows.ShadowLog;
 
-import java.text.NumberFormat;
-
 @RunWith(RobolectricTestRunner.class)
 public class DockDefenderTipTest {
     private Context mContext;
@@ -85,8 +83,7 @@
     @Test
     public void testGetTitle() {
         assertThat(mDockDefenderTipFutureBypass.getTitle(mContext).toString()).isEqualTo(
-                mContext.getString(R.string.battery_tip_dock_defender_future_bypass_title,
-                        getExtraPercentage(mContext)));
+                mContext.getString(R.string.battery_tip_dock_defender_future_bypass_title));
         assertThat(mDockDefenderTipActive.getTitle(mContext).toString()).isEqualTo(
                 mContext.getString(R.string.battery_tip_dock_defender_active_title));
         assertThat(mDockDefenderTipTemporarilyBypassed.getTitle(mContext).toString()).isEqualTo(
@@ -97,14 +94,12 @@
     @Test
     public void testGetSummary() {
         assertThat(mDockDefenderTipFutureBypass.getSummary(mContext).toString()).isEqualTo(
-                mContext.getString(R.string.battery_tip_dock_defender_future_bypass_summary,
-                        getExtraPercentage(mContext)));
+                mContext.getString(R.string.battery_tip_dock_defender_future_bypass_summary));
         assertThat(mDockDefenderTipActive.getSummary(mContext).toString()).isEqualTo(
-                mContext.getString(R.string.battery_tip_dock_defender_active_summary,
-                        getExtraPercentage(mContext)));
+                mContext.getString(R.string.battery_tip_dock_defender_active_summary));
         assertThat(mDockDefenderTipTemporarilyBypassed.getSummary(mContext).toString()).isEqualTo(
-                mContext.getString(R.string.battery_tip_dock_defender_temporarily_bypassed_summary,
-                        getExtraPercentage(mContext)));
+                mContext.getString(
+                        R.string.battery_tip_dock_defender_temporarily_bypassed_summary));
         assertThat(mDockDefenderTipDisabled.getSummary(mContext)).isNull();
     }
 
@@ -195,11 +190,4 @@
     private ShadowLog.LogItem createErrorLog(String msg) {
         return new ShadowLog.LogItem(Log.ERROR, "tag", msg, null);
     }
-
-    private String getExtraPercentage(Context context) {
-        final int extraValue = context.getResources().getInteger(
-                R.integer.config_battery_extra_tip_value);
-        return NumberFormat.getPercentInstance().format(extraValue * 0.01f);
-    }
-
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
index 95e3bad..57963aa 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
@@ -57,6 +57,7 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 import java.util.TimeZone;
 
 @RunWith(RobolectricTestRunner.class)
@@ -92,9 +93,9 @@
         final Resources resources = spy(mContext.getResources());
         resources.getConfiguration().setLocales(new LocaleList(new Locale("en_US")));
         doReturn(resources).when(mContext).getResources();
-        doReturn(new String[]{"com.android.gms.persistent"})
+        doReturn(Set.of("com.android.gms.persistent"))
                 .when(mFeatureFactory.powerUsageFeatureProvider)
-                .getHideApplicationEntries(mContext);
+                .getHideApplicationSet(mContext);
         doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
         doReturn(mIntent).when(mContext).registerReceiver(any(), any());
         doReturn(100).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_SCALE), anyInt());
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
index 0bc8693..1d06e60 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
@@ -48,6 +48,7 @@
 
 import java.util.Arrays;
 import java.util.Locale;
+import java.util.Set;
 import java.util.TimeZone;
 
 @RunWith(RobolectricTestRunner.class)
@@ -86,9 +87,9 @@
         final Resources resources = spy(mContext.getResources());
         resources.getConfiguration().setLocales(new LocaleList(new Locale("en_US")));
         doReturn(resources).when(mContext).getResources();
-        doReturn(new String[]{"com.android.gms.persistent"})
+        doReturn(Set.of("com.android.gms.persistent"))
                 .when(mFeatureFactory.powerUsageFeatureProvider)
-                .getHideApplicationEntries(mContext);
+                .getHideApplicationSet(mContext);
         mBatteryUsageBreakdownController = createController();
         mBatteryUsageBreakdownController.mAppListPreferenceGroup = mAppListPreferenceGroup;
         mBatteryDiffEntry = new BatteryDiffEntry(
@@ -104,6 +105,8 @@
         mBatteryDiffEntry = spy(mBatteryDiffEntry);
         mBatteryUsageBreakdownController.mBatteryDiffData =
                 new BatteryDiffData(Arrays.asList(mBatteryDiffEntry), Arrays.asList());
+        mBatteryUsageBreakdownController.mBatteryDiffData.setTotalConsumePower();
+        mBatteryUsageBreakdownController.mBatteryDiffData.sortEntries();
         // Adds fake testing data.
         BatteryDiffEntry.sResourceCache.put(
                 "fakeBatteryDiffEntryKey",
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
index ce958c9..b1695eb 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -60,6 +60,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TimeZone;
 
 @RunWith(RobolectricTestRunner.class)
@@ -1062,8 +1063,8 @@
         final List<Integer> levels = List.of(100, 100);
         hourlyBatteryLevelsPerDay.add(
                 new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
-        when(mPowerUsageFeatureProvider.getHideApplicationEntries(mContext))
-                .thenReturn(new CharSequence[]{"package1"});
+        when(mPowerUsageFeatureProvider.getHideApplicationSet(mContext))
+                .thenReturn(Set.of("package1"));
 
         final Map<Integer, Map<Integer, BatteryDiffData>> resultMap =
                 DataProcessor.getBatteryUsageMap(
@@ -1075,7 +1076,7 @@
                         .get(DataProcessor.SELECTED_INDEX_ALL);
         assertBatteryDiffEntry(
                 resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 2L,
-                ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 50.0,
+                ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 100.0,
                 /*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
                 /*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
                 /*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 20);
@@ -1225,6 +1226,8 @@
 
         final BatteryDiffData batteryDiffData = DataProcessor.generateBatteryDiffData(mContext,
                 DataProcessor.convertToBatteryHistEntry(batteryEntryList, mBatteryUsageStats));
+        batteryDiffData.setTotalConsumePower();
+        batteryDiffData.sortEntries();
 
         assertBatteryDiffEntry(
                 batteryDiffData.getAppDiffEntryList().get(0), 0, /*uid=*/ 2L,
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java
index 0d26acf..d06ba59 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericTest.java
@@ -253,17 +253,6 @@
     }
 
     @Test
-    public void onActivityResult_requestcode101_shouldFinish() {
-        initActivity(null);
-
-        mFragment.onActivityResult(
-                ChooseLockGenericFragment.ENABLE_ENCRYPTION_REQUEST, Activity.RESULT_OK,
-                null /* data */);
-
-        assertThat(mActivity.isFinishing()).isTrue();
-    }
-
-    @Test
     public void onActivityResult_requestcode102_shouldFinish() {
         initActivity(null);
 
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/AllAppListTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/AllAppListTest.kt
index 1a5f3ab..b767912 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/AllAppListTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/AllAppListTest.kt
@@ -156,13 +156,13 @@
 
     private fun setItemContent() {
         composeTestRule.setContent {
-            AllAppListPage {
-                fakeNavControllerWrapper.Wrapper {
+            fakeNavControllerWrapper.Wrapper {
+                with(AllAppListModel()) {
                     AppListItemModel(
                         record = AppRecordWithSize(app = APP),
                         label = LABEL,
                         summary = stateOf(SUMMARY),
-                    ).appItem()
+                    ).AppItem()
                 }
             }
         }
diff --git a/tests/unit/src/com/android/settings/UserCredentialsSettingsTest.java b/tests/unit/src/com/android/settings/UserCredentialsSettingsTest.java
new file mode 100644
index 0000000..c4cdf80
--- /dev/null
+++ b/tests/unit/src/com/android/settings/UserCredentialsSettingsTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2022 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.Looper;
+import android.os.Process;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.testutils.ResourcesUtils;
+import com.android.settings.wifi.helper.SavedWifiHelper;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class UserCredentialsSettingsTest {
+    static final String TEST_ALIAS = "test_alias";
+    static final String TEST_USER_BY_NAME = "test_used_by_name";
+
+    static final String TEXT_PURPOSE_SYSTEM = "credential_for_vpn_and_apps";
+    static final String TEXT_PURPOSE_WIFI = "credential_for_wifi";
+    static final String TEXT_PURPOSE_WIFI_IN_USE = "credential_for_wifi_in_use";
+
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Spy
+    final Context mContext = ApplicationProvider.getApplicationContext();
+    @Mock
+    SavedWifiHelper mSavedWifiHelper;
+    @Mock
+    View mView;
+
+    UserCredentialsSettings mSettings;
+    UserCredentialsSettings.Credential mSysCredential =
+            new UserCredentialsSettings.Credential(TEST_ALIAS, Process.SYSTEM_UID);
+    UserCredentialsSettings.Credential mWifiCredential =
+            new UserCredentialsSettings.Credential(TEST_ALIAS, Process.WIFI_UID);
+    List<String> mUsedByNames = Arrays.asList(TEST_USER_BY_NAME);
+    TextView mPurposeView = new TextView(ApplicationProvider.getApplicationContext());
+    TextView mUsedByTitleView = new TextView(ApplicationProvider.getApplicationContext());
+    TextView mUsedByContentView = new TextView(ApplicationProvider.getApplicationContext());
+
+    @Before
+    @UiThreadTest
+    public void setUp() {
+        when(mSavedWifiHelper.isCertificateInUse(any(String.class))).thenReturn(false);
+        when(mSavedWifiHelper.getCertificateNetworkNames(any(String.class)))
+                .thenReturn(new ArrayList<>());
+        when(mView.getTag()).thenReturn(mWifiCredential);
+
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        mSettings = spy(new UserCredentialsSettings());
+        when(mSettings.getContext()).thenReturn(mContext);
+        mSettings.mSavedWifiHelper = mSavedWifiHelper;
+        doNothing().when(mSettings)
+                .showCredentialDialogFragment(any(UserCredentialsSettings.Credential.class));
+    }
+
+    @Test
+    @UiThreadTest
+    public void onClick_noCredentialInTag_doNothing() {
+        when(mView.getTag()).thenReturn(null);
+
+        mSettings.onClick(mView);
+
+        verify(mSavedWifiHelper, never()).getCertificateNetworkNames(any(String.class));
+        verify(mSettings, never())
+                .showCredentialDialogFragment(any(UserCredentialsSettings.Credential.class));
+    }
+
+    @Test
+    @UiThreadTest
+    public void onClick_credentialInNotUse_notSetUsedByNamesThenShowDialog() {
+        mWifiCredential.setInUse(false);
+        when(mView.getTag()).thenReturn(mWifiCredential);
+
+        mSettings.onClick(mView);
+
+        verify(mSavedWifiHelper, never()).getCertificateNetworkNames(any(String.class));
+        verify(mSettings)
+                .showCredentialDialogFragment(any(UserCredentialsSettings.Credential.class));
+    }
+
+    @Test
+    @UiThreadTest
+    public void onClick_credentialInUse_setUsedByNamesThenShowDialog() {
+        mWifiCredential.setInUse(true);
+        when(mView.getTag()).thenReturn(mWifiCredential);
+        when(mSavedWifiHelper.getCertificateNetworkNames(any(String.class)))
+                .thenReturn(mUsedByNames);
+
+        mSettings.onClick(mView);
+
+        verify(mSavedWifiHelper).getCertificateNetworkNames(any(String.class));
+        assertThat(mWifiCredential.getUsedByNames()).isEqualTo(mUsedByNames);
+        verify(mSettings)
+                .showCredentialDialogFragment(any(UserCredentialsSettings.Credential.class));
+    }
+
+    @Test
+    @UiThreadTest
+    public void updatePurposeView_getSystemCert_setTextCorrectly() {
+        mSettings.updatePurposeView(mPurposeView, mSysCredential);
+
+        assertThat(mPurposeView.getText()).isEqualTo(getResString(TEXT_PURPOSE_SYSTEM));
+    }
+
+    @Test
+    @UiThreadTest
+    public void updatePurposeView_getWifiCert_setTextCorrectly() {
+        mWifiCredential.setInUse(false);
+
+        mSettings.updatePurposeView(mPurposeView, mWifiCredential);
+
+        assertThat(mPurposeView.getText()).isEqualTo(getResString(TEXT_PURPOSE_WIFI));
+    }
+
+    @Test
+    @UiThreadTest
+    public void updatePurposeView_isWifiCertInUse_setTextCorrectly() {
+        mWifiCredential.setInUse(true);
+
+        mSettings.updatePurposeView(mPurposeView, mWifiCredential);
+
+        assertThat(mPurposeView.getText()).isEqualTo(getResString(TEXT_PURPOSE_WIFI_IN_USE));
+    }
+
+    @Test
+    @UiThreadTest
+    public void updateUsedByViews_noUsedByName_hideViews() {
+        mWifiCredential.setUsedByNames(new ArrayList<>());
+
+        mSettings.updateUsedByViews(mUsedByTitleView, mUsedByContentView, mWifiCredential);
+
+        assertThat(mUsedByTitleView.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mUsedByContentView.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    @UiThreadTest
+    public void updateUsedByViews_hasUsedByName_showViews() {
+        mWifiCredential.setUsedByNames(mUsedByNames);
+
+        mSettings.updateUsedByViews(mUsedByTitleView, mUsedByContentView, mWifiCredential);
+
+        assertThat(mUsedByTitleView.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mUsedByContentView.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mUsedByContentView.getText().toString().contains(TEST_USER_BY_NAME)).isTrue();
+    }
+
+    static String getResString(String name) {
+        return ResourcesUtils.getResourcesString(ApplicationProvider.getApplicationContext(), name);
+    }
+}
diff --git a/tests/unit/src/com/android/settings/network/telephony/NullAlgorithmsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/NullAlgorithmsPreferenceControllerTest.java
new file mode 100644
index 0000000..e57dfcd
--- /dev/null
+++ b/tests/unit/src/com/android/settings/network/telephony/NullAlgorithmsPreferenceControllerTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2020 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.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.Looper;
+import android.provider.DeviceConfig;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+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 org.junit.After;
+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 final class NullAlgorithmsPreferenceControllerTest {
+    private static final String LOG_TAG = "NullAlgosControllerTest";
+    private static final int SUB_ID = 2;
+    private static final String PREFERENCE_KEY = "TEST_NULL_CIPHER_PREFERENCE";
+
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    private Preference mPreference;
+    private PreferenceScreen mPreferenceScreen;
+    private NullAlgorithmsPreferenceController mController;
+    private Context mContext;
+    // Ideally we would use TestableDeviceConfig, but that's not doable because the Settings
+    // app is not currently debuggable. For now, we use the real device config and ensure that
+    // we reset the cellular_security namespace property to its pre-test value after every test.
+    private DeviceConfig.Properties mPreTestProperties;
+
+    @Before
+    public void setUp() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        mPreTestProperties = DeviceConfig.getProperties(
+                TelephonyManager.PROPERTY_ENABLE_NULL_CIPHER_TOGGLE);
+
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+
+        mController = new NullAlgorithmsPreferenceController(mContext, PREFERENCE_KEY);
+
+        mPreference = spy(new Preference(mContext));
+        mPreference.setKey(PREFERENCE_KEY);
+        mPreferenceScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
+        mPreferenceScreen.addPreference(mPreference);
+    }
+
+    @After
+    public void tearDown() {
+        try {
+            DeviceConfig.setProperties(mPreTestProperties);
+        } catch (DeviceConfig.BadConfigException e) {
+            Log.e(LOG_TAG,
+                    "Failed to reset DeviceConfig to pre-test state. Test results may be impacted. "
+                            + e.getMessage());
+        }
+    }
+
+    @Test
+    public void getAvailabilityStatus_unsupportedHardware_unsupportedOnDevice() {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_CELLULAR_SECURITY,
+                TelephonyManager.PROPERTY_ENABLE_NULL_CIPHER_TOGGLE, Boolean.TRUE.toString(),
+                false);
+        doThrow(UnsupportedOperationException.class).when(
+                mTelephonyManager).isNullCipherAndIntegrityPreferenceEnabled();
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_featureFlagOff_conditionallyUnavailable() {
+        doReturn(true).when(mTelephonyManager).isNullCipherAndIntegrityPreferenceEnabled();
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_CELLULAR_SECURITY,
+                TelephonyManager.PROPERTY_ENABLE_NULL_CIPHER_TOGGLE, Boolean.FALSE.toString(),
+                false);
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_returnAvailable() {
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_CELLULAR_SECURITY,
+                TelephonyManager.PROPERTY_ENABLE_NULL_CIPHER_TOGGLE, Boolean.TRUE.toString(),
+                false);
+        // The value returned here shouldn't matter. The fact that this call is successful
+        // indicates that the device supports this operation
+        doReturn(true).when(mTelephonyManager).isNullCipherAndIntegrityPreferenceEnabled();
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void setChecked_true() {
+        mController.setChecked(true);
+        verify(mTelephonyManager, times(1)).setNullCipherAndIntegrityEnabled(true);
+    }
+
+    @Test
+    public void setChecked_false() {
+        mController.setChecked(false);
+        verify(mTelephonyManager, times(1)).setNullCipherAndIntegrityEnabled(false);
+    }
+}
diff --git a/tests/unit/src/com/android/settings/wifi/helper/SavedWifiHelperTest.java b/tests/unit/src/com/android/settings/wifi/helper/SavedWifiHelperTest.java
new file mode 100644
index 0000000..2ad77e1
--- /dev/null
+++ b/tests/unit/src/com/android/settings/wifi/helper/SavedWifiHelperTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 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.helper;
+
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.wifitrackerlib.SavedNetworkTracker;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@RunWith(AndroidJUnit4.class)
+public class SavedWifiHelperTest {
+    static final String TEST_ALIAS = "test_alias";
+
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Spy
+    final Context mContext = ApplicationProvider.getApplicationContext();
+    @Mock
+    Lifecycle mLifecycle;
+    @Mock
+    SavedNetworkTracker mSaveNetworkTracker;
+
+    SavedWifiHelper mSavedWifiHelper;
+
+    @Before
+    public void setUp() {
+        mSavedWifiHelper = new SavedWifiHelper(mContext, mLifecycle, mSaveNetworkTracker);
+    }
+
+    @Test
+    public void isCertificateInUse_redirectToSavedNetworkTracker() {
+        mSavedWifiHelper.isCertificateInUse(TEST_ALIAS);
+
+        verify(mSaveNetworkTracker).isCertificateRequired(TEST_ALIAS);
+    }
+
+    @Test
+    public void getCertificateNetworkNames_redirectToSavedNetworkTracker() {
+        mSavedWifiHelper.getCertificateNetworkNames(TEST_ALIAS);
+
+        verify(mSaveNetworkTracker).getCertificateRequesterNames(TEST_ALIAS);
+    }
+}
diff --git a/tests/unit/src/com/android/settings/wifi/helper/WifiTrackerBaseTest.java b/tests/unit/src/com/android/settings/wifi/helper/WifiTrackerBaseTest.java
new file mode 100644
index 0000000..159e2e2
--- /dev/null
+++ b/tests/unit/src/com/android/settings/wifi/helper/WifiTrackerBaseTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 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.helper;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.os.HandlerThread;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@RunWith(AndroidJUnit4.class)
+public class WifiTrackerBaseTest {
+
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Mock
+    Lifecycle mLifecycle;
+    @Mock
+    HandlerThread mWorkerThread;
+
+    WifiTrackerBase mWifiTrackerBase;
+
+    @Before
+    public void setUp() {
+        mWifiTrackerBase = new WifiTrackerBase(mLifecycle, mWorkerThread);
+    }
+
+    @Test
+    public void constructor_createWorkerThread() {
+        mWifiTrackerBase = new WifiTrackerBase(mLifecycle);
+
+        assertThat(mWifiTrackerBase.mWorkerThread).isNotNull();
+    }
+
+    @Test
+    public void constructor_startWorkerThread() {
+        verify(mWorkerThread).start();
+    }
+
+    @Test
+    public void onDestroy_quitWorkerThread() {
+        mWifiTrackerBase.onDestroy(mock(LifecycleOwner.class));
+
+        verify(mWorkerThread).quit();
+    }
+
+    @Test
+    public void getWorkerThreadHandler_isNotNull() {
+        mWifiTrackerBase = new WifiTrackerBase(mLifecycle);
+
+        assertThat(mWifiTrackerBase.getWorkerThreadHandler()).isNotNull();
+    }
+}