diff --git a/Android.bp b/Android.bp
index 0a58ee8ea7c..652757935b3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -55,6 +55,7 @@ android_library {
     srcs: [
         "src/**/*.java",
         "src/**/*.kt",
+        "src/**/*.aidl",
     ],
     exclude_srcs: [
         "src/com/android/settings/biometrics/fingerprint2/lib/**/*.kt",
@@ -92,6 +93,7 @@ android_library {
         // Settings dependencies
         "FingerprintManagerInteractor",
         "MediaDrmSettingsFlagsLib",
+        "ReverseWirelessCharging",
         "Settings-change-ids",
         "SettingsLib",
         "SettingsLibActivityEmbedding",
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index cc4d898403a..978d9ac5973 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -148,11 +148,13 @@
     <uses-permission android:name="android.permission.GET_BACKGROUND_INSTALLED_PACKAGES" />
     <uses-permission android:name="android.permission.SATELLITE_COMMUNICATION" />
     <uses-permission android:name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER" />
+    <uses-permission android:name="app.grapheneos.logviewer.SHOW_LOGCAT" />
 
     <application
             android:name=".SettingsApplication"
             android:label="@string/settings_label"
-            android:icon="@drawable/ic_launcher_settings"
+            android:icon="@mipmap/ic_launcher"
+            android:roundIcon="@mipmap/ic_launcher_round"
             android:theme="@style/Theme.Settings"
             android:hardwareAccelerated="true"
             android:requiredForAllUsers="true"
@@ -513,6 +515,19 @@
                 android:value="true" />
         </activity>
 
+        <!-- this is supposed to be used both for wifi and mobile data, controlled by flags -->
+        <activity
+            android:name=".network.InternetSetupActivity"
+            android:theme="@style/GlifV4Theme.DayNight"
+            android:exported="true">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.SETUP_INTERNET" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                android:value="true" />
+        </activity>
+
         <activity
             android:name=".wifi.WifiPickerActivity"
             android:permission="android.permission.CHANGE_WIFI_STATE"
@@ -605,6 +620,7 @@
         </activity>
 
         <activity android:name=".wifi.WifiConfigInfo"
+            android:theme="@style/Theme.DeviceDefault.DayNight.NoEdgeToEdge"
             android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
@@ -627,6 +643,7 @@
         </activity>
 
         <activity android:name=".wifi.WifiStatusTest"
+            android:theme="@style/Theme.DeviceDefault.DayNight.NoEdgeToEdge"
             android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
@@ -2199,6 +2216,23 @@
                        android:value="@string/menu_key_safety_center"/>
         </activity>
 
+        <activity
+            android:name=".Settings$ExploitProtectionActivity"
+            android:label="@string/exploit_protection_settings"
+            android:permission="android.permission.MANAGE_SAFETY_CENTER"
+            android:exported="true">
+
+            <intent-filter>
+                <action android:name="com.android.settings.EXPLOIT_PROTECTION_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.safetycenter.ExploitProtectionFragment" />
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                       android:value="@string/menu_key_safety_center"/>
+        </activity>
+
         <activity android:name="MonitoringCertInfoActivity"
                 android:label=""
                 android:theme="@style/Transparent"
@@ -2972,6 +3006,26 @@
             <meta-data android:name="com.android.settings.icon_tintable" android:value="true" />
         </activity>
 
+        <activity android:name=".security.DuressPasswordMainActivity"
+            android:excludeFromRecents="true"
+            android:theme="@style/GlifTheme.Light"
+            android:permission="android.permission.MANAGE_SAFETY_CENTER"
+            android:exported="true">
+
+            <intent-filter>
+                <action android:name="com.android.settings.DURESS_PASSWORD_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                       android:value="@string/menu_key_safety_center"/>
+        </activity>
+
+        <activity android:name=".security.DuressPasswordSetupActivity"
+            android:excludeFromRecents="true"
+            android:theme="@style/GlifTheme.Light"
+            android:exported="false" />
+
         <activity android:name=".biometrics.fingerprint.FingerprintEnrollSuggestionActivity"
             android:exported="true"
             android:icon="@drawable/ic_suggestion_fingerprint">
@@ -3184,6 +3238,7 @@
         </activity>
 
         <activity android:name=".development.AppPicker"
+                  android:theme="@style/Theme.DeviceDefault.DayNight.NoEdgeToEdge"
                   android:label="@string/select_application" />
 
         <activity android:name=".development.AdbQrCodeActivity" />
@@ -5287,6 +5342,12 @@
                 android:value="@string/menu_key_apps"/>
         </activity-alias>
 
+        <provider
+            android:name="com.android.settings.sudconfig.SudConfigProvider"
+            android:authorities="com.google.android.setupwizard.partner"
+            android:directBootAware="true"
+            android:exported="true" />
+
         <!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
         <provider
             android:name="androidx.startup.InitializationProvider"
@@ -5371,5 +5432,91 @@
         </receiver>
 
         <!-- This is the longest AndroidManifest.xml ever. -->
+
+        <activity
+            android:name="Settings$AppNativeDebuggingActivity"
+            android:permission="android.permission.WRITE_SECURE_SETTINGS"
+            android:exported="true">
+
+            <intent-filter>
+                <action android:name="android.settings.OPEN_APP_NATIVE_DEBUGGING_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="package" />
+            </intent-filter>
+
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.applications.AppNativeDebuggingFragment"/>
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                android:value="@string/menu_key_apps"/>
+        </activity>
+
+        <activity
+            android:name="Settings$AppMemtagActivity"
+            android:permission="android.permission.WRITE_SECURE_SETTINGS"
+            android:exported="true">
+
+            <intent-filter>
+                <action android:name="android.settings.OPEN_APP_MEMTAG_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="package" />
+            </intent-filter>
+
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.applications.AppMemtagFragment"/>
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                android:value="@string/menu_key_apps"/>
+        </activity>
+
+        <activity
+            android:name="Settings$AppHardenedMallocActivity"
+            android:permission="android.permission.WRITE_SECURE_SETTINGS"
+            android:exported="true">
+
+            <intent-filter>
+                <action android:name="android.settings.OPEN_APP_HARDENED_MALLOC_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="package" />
+            </intent-filter>
+
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.applications.AppHardenedMallocFragment"/>
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                android:value="@string/menu_key_apps"/>
+        </activity>
+
+        <activity
+            android:name=".Settings$AppMemoryDynCodeLoadingActivity"
+            android:permission="android.permission.WRITE_SECURE_SETTINGS"
+            android:exported="true">
+
+            <intent-filter>
+                <action android:name="android.settings.OPEN_APP_MEMORY_DYN_CODE_LOADING_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="package" />
+            </intent-filter>
+
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.applications.AppMemoryDynCodeLoadingFragment"/>
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                android:value="@string/menu_key_apps"/>
+        </activity>
+
+        <activity
+            android:name=".Settings$AppStorageDynCodeLoadingActivity"
+            android:permission="android.permission.WRITE_SECURE_SETTINGS"
+            android:exported="true">
+
+            <intent-filter>
+                <action android:name="android.settings.OPEN_APP_STORAGE_DYN_CODE_LOADING_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="package" />
+            </intent-filter>
+
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.applications.AppStorageDynCodeLoadingFragment"/>
+            <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+                android:value="@string/menu_key_apps"/>
+        </activity>
+
     </application>
 </manifest>
diff --git a/res-product/values/strings.xml b/res-product/values/strings.xml
index d5ef1c888f6..621f65b2e91 100644
--- a/res-product/values/strings.xml
+++ b/res-product/values/strings.xml
@@ -509,6 +509,8 @@
     <string name="ethernet_tethering_subtext" product="default">Share phone\u2019s internet connection via Ethernet</string>
     <!-- Ethernet Tethering subtext for tablet [CHAR LIMIT=NONE]-->
     <string name="ethernet_tethering_subtext" product="tablet">Share tablet\u2019s internet connection via Ethernet</string>
+    <!-- Data Saver Tethering subtext [CHAR LIMIT=NONE]-->
+    <string name="data_saver_tethering_subtext" product="default">Unconditionally allow tethering while on data saver mode</string>
     <!-- Main settings screen, setting title for the user to go into the About phone screen -->
     <string name="about_settings" product="tablet">About tablet</string>
     <!-- Main settings screen, setting title for the user to go into the About phone screen -->
diff --git a/res/drawable/baseline_wifi.xml b/res/drawable/baseline_wifi.xml
new file mode 100644
index 00000000000..e8b85e7ced0
--- /dev/null
+++ b/res/drawable/baseline_wifi.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="?attr/colorPrimary"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M1,9l2,2c4.97,-4.97 13.03,-4.97 18,0l2,-2C16.93,2.93 7.08,2.93 1,9zM9,17l3,3 3,-3c-1.65,-1.66 -4.34,-1.66 -6,0zM5,13l2,2c2.76,-2.76 7.24,-2.76 10,0l2,-2C15.14,9.14 8.87,9.14 5,13z" />
+</vector>
diff --git a/res/drawable/baseline_wifi_glif.xml b/res/drawable/baseline_wifi_glif.xml
new file mode 100644
index 00000000000..3f12842b089
--- /dev/null
+++ b/res/drawable/baseline_wifi_glif.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:width="?attr/sudGlifIconSize"
+        android:height="?attr/sudGlifIconSize"
+        android:drawable="@drawable/baseline_wifi" />
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/ic_launcher_foreground.xml b/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 00000000000..3a707cae45d
--- /dev/null
+++ b/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+<!--
+  Copyright (C) 2021 Google Inc.
+
+  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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <group
+        android:scaleX="2.277"
+        android:scaleY="2.277"
+        android:translateX="26.676"
+        android:translateY="26.676">
+        <path
+            android:fillColor="#000000"
+            android:pathData="M19.5,12c0,-0.23 -0.01,-0.45 -0.03,-0.68l1.86,-1.41c0.4,-0.3 0.51,-0.86 0.26,-1.3l-1.87,-3.23c-0.25,-0.44 -0.79,-0.62 -1.25,-0.42l-2.15,0.91c-0.37,-0.26 -0.76,-0.49 -1.17,-0.68l-0.29,-2.31C14.8,2.38 14.37,2 13.87,2h-3.73C9.63,2 9.2,2.38 9.14,2.88L8.85,5.19c-0.41,0.19 -0.8,0.42 -1.17,0.68L5.53,4.96c-0.46,-0.2 -1,-0.02 -1.25,0.42L2.41,8.62c-0.25,0.44 -0.14,0.99 0.26,1.3l1.86,1.41C4.51,11.55 4.5,11.77 4.5,12s0.01,0.45 0.03,0.68l-1.86,1.41c-0.4,0.3 -0.51,0.86 -0.26,1.3l1.87,3.23c0.25,0.44 0.79,0.62 1.25,0.42l2.15,-0.91c0.37,0.26 0.76,0.49 1.17,0.68l0.29,2.31C9.2,21.62 9.63,22 10.13,22h3.73c0.5,0 0.93,-0.38 0.99,-0.88l0.29,-2.31c0.41,-0.19 0.8,-0.42 1.17,-0.68l2.15,0.91c0.46,0.2 1,0.02 1.25,-0.42l1.87,-3.23c0.25,-0.44 0.14,-0.99 -0.26,-1.3l-1.86,-1.41C19.49,12.45 19.5,12.23 19.5,12zM12.04,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5s3.5,1.57 3.5,3.5S13.97,15.5 12.04,15.5z" />
+    </group>
+</vector>
diff --git a/res/drawable/ic_settings_install.xml b/res/drawable/ic_settings_install.xml
index 5bd5e300eae..eefecc242a4 100644
--- a/res/drawable/ic_settings_install.xml
+++ b/res/drawable/ic_settings_install.xml
@@ -18,7 +18,8 @@
     android:width="24dp"
     android:height="24dp"
     android:viewportWidth="24"
-    android:viewportHeight="24">
+    android:viewportHeight="24"
+    android:tint="?android:attr/colorControlNormal">
   <path
       android:fillColor="#FF000000"
       android:pathData="M18,15v3H6v-3H4v3c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-3H18z"/>
diff --git a/res/drawable/quickly_open_camera.xml b/res/drawable/quickly_open_camera.xml
deleted file mode 100644
index dcbf9f4dc68..00000000000
--- a/res/drawable/quickly_open_camera.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape>
-</shape>
diff --git a/res/layout/duress_password_setup.xml b/res/layout/duress_password_setup.xml
new file mode 100644
index 00000000000..a708b3fc3e5
--- /dev/null
+++ b/res/layout/duress_password_setup.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<com.google.android.setupdesign.GlifLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/glif_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:icon="@drawable/ic_lock"
+>
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        style="@style/SudContentFrame">
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
+            android:text="@string/unlock_set_unlock_pin_title" />
+
+        <EditText
+            android:id="@+id/pin_input"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:hint="@string/duress_pwd_enter_pin"
+            android:imeOptions="actionNext"
+            android:inputType="numberPassword" />
+
+        <EditText
+            android:id="@+id/pin_input_confirmation"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:hint="@string/duress_pwd_confirm_pin"
+            android:imeOptions="actionNext"
+            android:inputType="numberPassword" />
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="32dp"
+            android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
+            android:text="@string/unlock_set_unlock_password_title" />
+
+        <EditText
+            android:id="@+id/password_input"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:hint="@string/duress_pwd_enter_password"
+            android:imeOptions="actionNext"
+            android:inputType="textPassword" />
+
+        <EditText
+            android:id="@+id/password_input_confirmation"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dp"
+            android:hint="@string/duress_pwd_confirm_password"
+            android:imeOptions="actionDone"
+            android:inputType="textPassword" />
+
+    </LinearLayout>
+</com.google.android.setupdesign.GlifLayout>
diff --git a/res/layout/face_enroll_introduction.xml b/res/layout/face_enroll_introduction.xml
index 8b0352928ca..ea57f4acbc9 100644
--- a/res/layout/face_enroll_introduction.xml
+++ b/res/layout/face_enroll_introduction.xml
@@ -64,7 +64,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 style="@style/BiometricEnrollIntroTitle"
-                android:text="@string/security_settings_face_enroll_introduction_info_title" />
+                android:text="@string/security_settings_face_enroll_introduction_info_title_en" />
 
             <LinearLayout
                 android:layout_width="match_parent"
@@ -156,7 +156,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 style="@style/BiometricEnrollIntroTitle"
-                android:text="@string/security_settings_face_enroll_introduction_how_title" />
+                android:text="@string/security_settings_face_enroll_introduction_how_title_en" />
 
             <TextView
                 android:id="@+id/how_message"
diff --git a/res/layout/settings_main_prefs.xml b/res/layout/settings_main_prefs.xml
index 48352e2efa0..5111332bfbe 100644
--- a/res/layout/settings_main_prefs.xml
+++ b/res/layout/settings_main_prefs.xml
@@ -34,40 +34,38 @@
         android:layout_height="0dp"
         android:layout_weight="1"/>
 
-    <RelativeLayout android:id="@+id/button_bar"
-                    android:layout_height="wrap_content"
-                    android:layout_width="match_parent"
-                    android:layout_weight="0"
-                    android:visibility="gone">
-
-        <Button android:id="@+id/back_button"
-                android:layout_width="150dip"
-                android:layout_height="wrap_content"
-                android:layout_margin="5dip"
-                android:layout_alignParentStart="true"
-                android:text="@*android:string/back_button_label"/>
-
-        <LinearLayout
-                android:orientation="horizontal"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentEnd="true">
-
-            <Button android:id="@+id/skip_button"
-                    android:layout_width="150dip"
-                    android:layout_height="wrap_content"
-                    android:layout_margin="5dip"
-                    android:text="@*android:string/skip_button_label"
-                    android:visibility="gone"/>
+    <!-- button bar is used only by activities that use setupdesign-->
+    <RelativeLayout
+        android:id="@+id/button_bar"
+        style="@style/SudGlifButtonBar.Stackable"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:visibility="gone">
 
-            <Button android:id="@+id/next_button"
-                    android:layout_width="150dip"
-                    android:layout_height="wrap_content"
-                    android:layout_margin="5dip"
-                    android:text="@*android:string/next_button_label"/>
+        <Button
+            android:id="@+id/back_button"
+            style="@style/SudGlifButton.Secondary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentStart="true"
+            android:layout_marginEnd="@dimen/sud_glif_button_margin_end"
+            android:text="@*android:string/back_button_label" />
 
-        </LinearLayout>
+        <Button
+            android:id="@+id/skip_button"
+            style="@style/SudGlifButton.Secondary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_toEndOf="@id/back_button"
+            android:text="@*android:string/skip_button_label"
+            android:visibility="gone" />
 
+        <Button
+            android:id="@+id/next_button"
+            style="@style/SudGlifButton.Primary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentEnd="true"
+            android:text="@*android:string/next_button_label" />
     </RelativeLayout>
-
 </LinearLayout>
diff --git a/res/layout/wifi_network_config.xml b/res/layout/wifi_network_config.xml
index dbd3e673913..7c6ac3758f5 100644
--- a/res/layout/wifi_network_config.xml
+++ b/res/layout/wifi_network_config.xml
@@ -707,7 +707,7 @@
                      android:layout_height="wrap_content"
                      style="@style/wifi_item_spinner"
                      android:prompt="@string/wifi_privacy_settings"
-                     android:entries="@array/wifi_privacy_entries"/>
+                     android:entries="@array/wifi_privacy_entries_ext"/>
 
             <Spinner android:id="@+id/dhcp_settings"
                 android:layout_width="match_parent"
diff --git a/res/mipmap-anydpi/ic_launcher.xml b/res/mipmap-anydpi/ic_launcher.xml
new file mode 100644
index 00000000000..5c84730caa7
--- /dev/null
+++ b/res/mipmap-anydpi/ic_launcher.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@color/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+    <monochrome android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
diff --git a/res/mipmap-anydpi/ic_launcher_round.xml b/res/mipmap-anydpi/ic_launcher_round.xml
new file mode 100644
index 00000000000..5c84730caa7
--- /dev/null
+++ b/res/mipmap-anydpi/ic_launcher_round.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@color/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+    <monochrome android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
diff --git a/res/raw/lottie_quickly_open_camera.json b/res/raw/lottie_quickly_open_camera.json
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/res/values-night-v31/fractions.xml b/res/values-night-v31/fractions.xml
new file mode 100644
index 00000000000..547f63d5515
--- /dev/null
+++ b/res/values-night-v31/fractions.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <fraction name="setup_compat_footer_button_ripple_alpha">24%</fraction>
+</resources>
diff --git a/res/values-night/bools.xml b/res/values-night/bools.xml
new file mode 100644
index 00000000000..bfdd9cf0334
--- /dev/null
+++ b/res/values-night/bools.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <bool name="setup_compat_light_navigation_bar">false</bool>
+    <bool name="setup_compat_light_status_bar">false</bool>
+</resources>
diff --git a/res/values-sw600dp-v31/dimens.xml b/res/values-sw600dp-v31/dimens.xml
new file mode 100644
index 00000000000..3542f62dc08
--- /dev/null
+++ b/res/values-sw600dp-v31/dimens.xml
@@ -0,0 +1,9 @@
+<resources>
+    <!-- Fixes redundant horizontal margin issue on tablets -->
+    <dimen name="sud_glif_margin_start_material_you">24dp</dimen>
+    <dimen name="sud_glif_margin_end_material_you">24dp</dimen>
+    <dimen name="sud_glif_footer_bar_padding_start_material_you">8dp</dimen>
+    <dimen name="sud_glif_footer_bar_padding_end_material_you">20dp</dimen>
+    <dimen name="sud_glif_button_margin_end">20dp</dimen>
+    <dimen name="sud_glif_button_margin_start">8dp</dimen>
+</resources>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 55735e66322..170d6998c36 100755
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -29,6 +29,14 @@
     <!-- Lock pattern view size, align sysui biometric_auth_pattern_view_size -->
     <dimen name="biometric_auth_pattern_view_size">348dp</dimen>
 
+    <!-- Fixes redundant horizontal margin issue on tablets -->
+    <dimen name="sud_glif_margin_start_material_you">24dp</dimen>
+    <dimen name="sud_glif_margin_end_material_you">24dp</dimen>
+    <dimen name="sud_glif_footer_bar_padding_start_material_you">8dp</dimen>
+    <dimen name="sud_glif_footer_bar_padding_end_material_you">20dp</dimen>
+    <dimen name="sud_glif_button_margin_end">20dp</dimen>
+    <dimen name="sud_glif_button_margin_start">8dp</dimen>
+
     <!--  Pointer fill color preference  -->
     <dimen name="pointer_fill_container_height">104dp</dimen>
     <dimen name="pointer_fill_container_max_width">448dp</dimen>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 327ff44503e..7d28bb6efa9 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1090,8 +1090,9 @@
         <item>Treat as unmetered</item>
     </string-array>
 
-    <string-array name="wifi_privacy_entries">
-        <item>Use randomized MAC</item>
+    <string-array name="wifi_privacy_entries_ext">
+        <item>Use per-connection randomized MAC (default)</item>
+        <item>Use per-network randomized MAC</item>
         <item>Use device MAC</item>
     </string-array>
 
@@ -1111,7 +1112,8 @@
         <item>2</item>
     </string-array>
 
-    <string-array name="wifi_privacy_values" translatable="false">
+    <string-array name="wifi_privacy_values_ext" translatable="false">
+        <item>100</item>
         <item>1</item>
         <item>0</item>
     </string-array>
@@ -1628,4 +1630,6 @@
     <!-- Packages that will not show Display over other apps permission -->
     <string-array name="display_over_apps_permission_change_exempt">
     </string-array>
+    <string-array name="fingerprint_acquired_vendor" />
+
 </resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 200253acce6..d404f3ebfb0 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -68,6 +68,8 @@
         <attr name="searchable" format="boolean" />
         <!-- Classname of a PreferenceController corresponding to the preference -->
         <attr name="controller" format="string" />
+        <!-- Reference to a BoolSetting. Format: className <space> fieldName -->
+        <attr name="boolSettingField" format="string" />
         <!-- Customized subtitle if it's an unavailable slice -->
         <attr name="unavailableSliceSubtitle" format="string" />
         <!-- Whether or not the preference is for work profile, by default it's false. -->
diff --git a/res/values/bools.xml b/res/values/bools.xml
new file mode 100644
index 00000000000..d978b71d643
--- /dev/null
+++ b/res/values/bools.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <bool name="setup_compat_light_navigation_bar">true</bool>
+    <bool name="setup_compat_light_status_bar">true</bool>
+</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 95b38cb5250..ff95cdb8164 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -216,6 +216,11 @@
     <color name="screen_flash_preset_opacity_color_11">#4DFF00FE</color> <!-- 30% Magenta -->
     <color name="screen_flash_preset_opacity_color_12">#667F00FF</color> <!-- 40% Violet -->
 
+    <!-- Setup wizard related -->
+    <color name="setup_compat_footer_primary_button_bg_color">
+        @color/sud_color_accent_glif_v3_light
+    </color>
+
     <!-- Switch bar disabled state color-->
     <color name="switch_bar_state_disabled_color">#1F1F1F1F</color>
 
diff --git a/res/values/config.xml b/res/values/config.xml
index 065d28a786b..2af7dbe3d83 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -48,14 +48,14 @@
     </string>
 
     <!-- Package name and fully-qualified class name for the wallpaper picker activity. -->
-    <string name="config_wallpaper_picker_package" translatable="false">com.android.settings</string>
-    <string name="config_wallpaper_picker_class" translatable="false">com.android.settings.Settings$WallpaperSettingsActivity</string>
+    <string name="config_wallpaper_picker_package" translatable="false">com.android.wallpaper</string>
+    <string name="config_wallpaper_picker_class" translatable="false">com.android.wallpaper.picker.CategoryPickerActivity</string>
     <!-- Fully-qualified class name for the styles & wallpaper picker activity. -->
-    <string name="config_styles_and_wallpaper_picker_class" translatable="false"></string>
+    <string name="config_styles_and_wallpaper_picker_class" translatable="false">com.android.customization.picker.CustomizationPickerActivity</string>
     <!-- Action name for the wallpaper picker activity. -->
-    <string name="config_wallpaper_picker_action" translatable="false"></string>
+    <string name="config_wallpaper_picker_action" translatable="false">android.intent.action.MAIN</string>
     <!-- Action name for the styles & wallpaper picker activity. -->
-    <string name="config_styles_and_wallpaper_picker_action" translatable="false"></string>
+    <string name="config_styles_and_wallpaper_picker_action" translatable="false">android.intent.action.MAIN</string>
     <!-- Intent extra for wallpaper picker activity. -->
     <string name="config_wallpaper_picker_launch_extra" translatable="false">com.android.wallpaper.LAUNCH_SOURCE</string>
 
@@ -81,6 +81,7 @@
         <item>com.example.package.first/com.example.class.FirstService</item>
         <item>com.example.package.second/com.example.class.SecondService</item>
         -->
+        <item>com.android.talkback/com.google.android.marvin.talkback.TalkBackService</item>
     </string-array>
 
     <!-- List containing the component names of pre-installed captioning services. -->
@@ -239,7 +240,7 @@
         Whether or not the homepage should be powered by legacy suggestion (versus contextual cards)
         Default to true as not all devices support contextual cards.
     -->
-    <bool name="config_use_legacy_suggestion">true</bool>
+    <bool name="config_use_legacy_suggestion">false</bool>
 
     <!-- Whether or not homepage should display user's account avatar -->
     <bool name="config_show_avatar_in_homepage">false</bool>
@@ -478,7 +479,7 @@
     <bool name="config_show_trust_agent_click_intent">true</bool>
 
     <!-- Whether wallpaper attribution should be shown or not. -->
-    <bool name="config_show_wallpaper_attribution">true</bool>
+    <bool name="config_show_wallpaper_attribution">false</bool>
 
     <!-- Whether assist_and_voice_input should be shown or not. -->
     <bool name="config_show_assist_and_voice_input">true</bool>
@@ -517,7 +518,7 @@
     <bool name="config_disable_uninstall_update">false</bool>
 
     <!-- Slice Uri to query nearby devices. -->
-    <string name="config_nearby_devices_slice_uri" translatable="false">content://com.google.android.gms.nearby.fastpair/device_status_list_item</string>
+    <string name="config_nearby_devices_slice_uri" translatable="false"></string>
 
     <!-- BT Slice intent action. To support Settings 2 panel, BT slice can't use PendingIntent.send(). Therefore, here defines the Slice intent action. -->
     <string name="config_bt_slice_intent_action" translatable="false"></string>
@@ -611,7 +612,7 @@
     <string name="config_other_storage_category_uri" translatable="false">content://com.android.providers.media.documents/root/others_root</string>
 
     <!-- Whether to show Smart Storage toggle -->
-    <bool name="config_show_smart_storage_toggle">true</bool>
+    <bool name="config_show_smart_storage_toggle">false</bool>
 
     <!-- Display settings screen, Color mode options. Must be the same length and order as
          config_color_mode_options_values below. Only the values that also appear in
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c9a67e462bb..390390c8fc8 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -517,6 +517,16 @@
     <dimen name="audio_streams_qrcode_preview_radius">30dp</dimen>
     <dimen name="audio_streams_qrcode_scanner_fragment_padding">16dp</dimen>
 
+    <!-- Setup wizard related -->
+    <dimen name="sud_progress_bar_margin_top">
+        @dimen/sud_progress_bar_margin_top_material_you
+    </dimen>
+    <dimen name="setup_design_card_view_intrinsic_height">0dp</dimen>
+    <dimen name="setup_design_card_view_intrinsic_width">0dp</dimen>
+    <dimen name="setup_compat_footer_button_radius">
+        @dimen/sud_footer_bar_button_radius_material_you
+    </dimen>
+
     <!-- Zen Modes -->
     <dimen name="zen_mode_header_size">136dp</dimen>
     <dimen name="zen_mode_header_inner_icon_size">64dp</dimen>
diff --git a/res/values/fractions.xml b/res/values/fractions.xml
new file mode 100644
index 00000000000..78454226886
--- /dev/null
+++ b/res/values/fractions.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <fraction name="setup_compat_footer_button_ripple_alpha">12%</fraction>
+</resources>
diff --git a/res/values/ic_launcher_background.xml b/res/values/ic_launcher_background.xml
new file mode 100644
index 00000000000..f42ada656ee
--- /dev/null
+++ b/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="ic_launcher_background">#FFFFFF</color>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7e363e6f238..0d00ec8fe21 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -752,6 +752,18 @@
     <!-- Introduction detail message shown in face enrollment screen in setup wizard. [CHAR LIMIT=NONE] -->
     <string name="security_settings_face_enroll_introduction_message_setup">Use your face to unlock your phone, authorize purchases, or sign in to apps</string>
     <!-- Title of a section on the face enrollment introduction page that provides additional information. [CHAR LIMIT=40] -->
+
+    <string name="security_settings_face_enroll_introduction_info_title_en">Keep in mind</string>
+    <string name="security_settings_face_enroll_introduction_how_title_en">How it works</string>
+
+    <string name="security_settings_face_enroll_introduction_info_glasses_en">Glasses or lightly tinted sunglasses are OK.</string>
+    <string name="security_settings_face_enroll_introduction_info_looking_en">Looking at the phone can unlock it even when you don’t intend to. Your phone can also be unlocked by someone who looks a lot like you, like an identical sibling, or if someone holds it up to your face.</string>
+    <string name="security_settings_face_enroll_introduction_info_less_secure_en">Using a face to unlock the phone may be less secure than a strong pattern or PIN.</string>
+    <string name="security_settings_face_enroll_introduction_info_gaze_en">Face Unlock can require your eyes to be open to unlock the phone or verify it’s you. You can turn this option on at any time in Settings.</string>
+    <string name="security_settings_face_enroll_introduction_how_message_en">Face Unlock creates a unique model of your face to verify it’s you. To create this face model during setup, you will take images of your face from different angles.\n\nWhen you use Face Unlock, images are used to update your face model. Images used to create your face model are not stored, but the face model is stored securely on your phone and never leaves the phone. All processing occurs securely on your phone.</string>
+    <string name="security_settings_face_enroll_introduction_control_title_en">You’re in control</string>
+    <string name="security_settings_face_enroll_introduction_control_message_en">You can delete your face model or turn off Face Unlock at any time in Settings. Face models are stored on the phone until you delete them.\n\nLearn more at g.co/pixel/faceunlock.</string>
+
     <string name="security_settings_face_enroll_introduction_info_title"></string>
     <!-- Message on the face enrollment introduction page that provides information about glasses. [CHAR LIMIT=NONE] -->
     <string name="security_settings_face_enroll_introduction_info_glasses"></string>
@@ -2892,6 +2904,10 @@
     <string name="auto_rotate_summary_no_permission">Camera access is required for Face Detection. Tap to manage permissions for Device Personalization Services</string>
     <!-- auto_rotate settings screen, text for the camera permission button [CHAR LIMIT=NONE]-->
     <string name="auto_rotate_manage_permission_button">Manage permissions</string>
+    <!-- Display settings screen, increased touch sensitivity settings title [CHAR LIMIT=30] -->
+    <string name="touch_sensitivity_title">Increase touch sensitivity</string>
+    <!-- Display settings screen, increased touch sensitivity settings summary [CHAR LIMIT=NONE] -->
+    <string name="touch_sensitivity_summary">Improves touch when using screen protectors</string>
 
     <!-- Night display screen, setting option name to enable night display (renamed "Night Light" with title caps). [CHAR LIMIT=30] -->
     <string name="night_display_title">Night Light</string>
@@ -3169,6 +3185,8 @@
     <!-- About phone screen,  setting option name  [CHAR LIMIT=40] -->
     <string name="baseband_version">Baseband version</string>
     <!-- About phone screen,  setting option name  [CHAR LIMIT=40] -->
+    <string name="bootloader_version">Bootloader version</string>
+    <!-- About phone screen,  setting option name  [CHAR LIMIT=40] -->
     <string name="kernel_version">Kernel version</string>
     <!-- About phone screen,  setting option name  [CHAR LIMIT=40] -->
     <string name="build_number">Build number</string>
@@ -3693,6 +3711,10 @@
     <!-- Label for ethernet tether checkbox [CHAR LIMIT=NONE]-->
     <string name="ethernet_tether_checkbox_text">Ethernet tethering</string>
 
+    <!-- Enable Tethering on Data Saver -->
+    <!-- Label for data saver tether checkbox [CHAR LIMIT=NONE]-->
+    <string name="data_saver_tether_checkbox_text">Enable tethering on data saver</string>
+
     <!-- Tethering footer info [CHAR LIMIT=NONE]-->
     <string name="tethering_footer_info">Use hotspot and tethering to provide internet to other devices through your mobile data connection. Apps can also create a hotspot to share content with nearby devices.</string>
     <!-- Tethering footer info for the device which supports Wi-Fi and Wi-Fi tethering enabled at the same time [CHAR LIMIT=NONE]-->
@@ -4201,6 +4223,7 @@
     <string name="enable_text">Enable</string>
     <!-- Manage applications, individual application info screen, button label under Storage heading. Button to clear all data associated with tis app (for example, remove all cached emails for an Email app) -->
     <string name="clear_user_data_text">Clear storage</string>
+    <string name="manage_storage_text">Manage storage</string>
     <!-- Manage applications, restore updated system application to factory version -->
     <string name="app_factory_reset">Uninstall updates</string>
     <!-- [CHAR LIMIT=50] Manage applications, unlock restricted setting from lock screen title -->
@@ -11890,6 +11913,8 @@
     <string name="preferred_network_mode_cdma_evdo_gsm_wcdma_summary">Preferred network mode: CDMA/EvDo/GSM/WCDMA</string>
     <!-- LTE [CHAR LIMIT=NONE] -->
     <string name="preferred_network_mode_lte_summary">Preferred network mode: LTE </string>
+    <!-- LTE only [CHAR LIMIT=100] -->
+    <string name="preferred_network_mode_lte_only_summary">Preferred network mode: LTE only</string>
     <!-- GSM/WCDMA/LTE [CHAR LIMIT=NONE] -->
     <string name="preferred_network_mode_lte_gsm_wcdma_summary">Preferred network mode: GSM/WCDMA/LTE</string>
     <!-- CDMA+LTE/EVDO [CHAR LIMIT=NONE] -->
@@ -11955,8 +11980,12 @@
     <string name="network_4G_pure" translatable="false">4G</string>
     <!-- Text for Network lte [CHAR LIMIT=NONE] -->
     <string name="network_lte">LTE (recommended)</string>
+    <!-- Text for Network lte only [CHAR LIMIT=NONE] -->
+    <string name="network_lte_only">LTE only</string>
     <!-- Text for Network 4g [CHAR LIMIT=NONE] -->
     <string name="network_4G">4G (recommended)</string>
+    <!-- Text for Network 4g only [CHAR LIMIT=NONE] -->
+    <string name="network_4G_only">4G only</string>
     <!-- Text for Network 3g [CHAR LIMIT=NONE] -->
     <string name="network_3G" translatable="false">3G</string>
     <!-- Text for Network 2g [CHAR LIMIT=NONE] -->
@@ -13670,4 +13699,18 @@
 
     <!-- Text for Search bar of Settings home screen [CHAR LIMIT=34] -->
     <string name="homepage_search">Search Settings</string>
+
+    <string name="user_settings_send_censored_notifications_to_current">Send notifications to current user</string>
+    <string name="user_settings_send_censored_notifications_to_current_summary">Your lock screen notifications will be forwarded to the current user if you are active in the background. Only the user\'s name, the app\'s name, and the time received will be shown.</string>
+
+    <string name="sandboxed_google_play">Sandboxed Google Play</string>
+    <string name="sandboxed_google_play_work_profile">Sandboxed Google Play (work profile)</string>
+
+    <string name="storage_scopes">Storage Scopes</string>
+
+    <string name="allow_access_to_obb_directory_title">Allow access to Android/obb folder</string>
+    <string name="allow_access_to_obb_directory_summary">Required for installation of some large apps (mostly games) that use OBB expansion files</string>
+
+    <string name="battery_share_description">Charge other devices by placing them on the back of your phone</string>
+    <string name="battery_share">Battery share</string>
 </resources>
diff --git a/res/values/strings_app_exploit_protection.xml b/res/values/strings_app_exploit_protection.xml
new file mode 100644
index 00000000000..3c8a7c837bb
--- /dev/null
+++ b/res/values/strings_app_exploit_protection.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="exploit_protection_category_title">Exploit protection</string>
+
+    <string name="aep_allowed">Allowed</string>
+    <string name="aep_blocked">Blocked</string>
+    <string name="aep_default">Default (%1$s)</string>
+    <string name="aep_disabled">Disabled</string>
+    <string name="aep_enabled">Enabled</string>
+    <string name="aep_restricted">Restricted</string>
+
+    <string name="aep_confirm_disable_title">Warning</string>
+    <string name="aep_confirm_disable_warning_msg">This setting will weaken exploit protections for the selected app.</string>
+    <string name="aep_confirm_disable_proceed_btn">Proceed</string>
+
+    <string name="aep_dvr_default_security_setting">Default value can be changed in the %1$s section</string>
+
+    <string name="aep_dvr_compat_config_hardening_opt_in">The selected app is known to be compatible with this setting</string>
+    <string name="aep_dvr_compat_config_hardening_opt_out">%1$s by default, because this app is known to need it.
+This behavior can be disabled in the %2$s section.</string>
+
+    <string name="aep_default_main_switch_block_for_3p_apps">Block for third-party apps by default</string>
+    <string name="aep_default_main_switch_restrict_for_3p_apps">Restrict for third-party apps by default</string>
+    <string name="aep_default_main_switch_disable_for_3p_apps">Disable for third-party apps by default</string>
+    <string name="aep_default_summary_restricted">Restricted by default</string>
+    <string name="aep_default_summary_disabled">Disabled by default</string>
+    <string name="aep_default_summary_blocked">Blocked by default</string>
+    <string name="aep_default_summary_allowed_for_3p_apps">Allowed for third-party apps by default</string>
+    <string name="aep_default_summary_enabled_for_3p_apps">Enabled for third-party apps by default</string>
+
+    <string name="aep_ir_exploit_protection_compat_mode">%1$s is enabled</string>
+
+    <string name="aep_compat_mode_title">Exploit protection compatibility mode</string>
+    <string name="aep_compat_mode_summary">Improves compatibility by disabling some of the GrapheneOS exploit protections for this app</string>
+
+    <string name="aep_hmalloc">Hardened memory allocator</string>
+    <string name="aep_hmalloc_footer">
+        Hardened memory allocator (hardened_malloc) provides substantial defenses against the most common classes of vulnerabilities (heap memory corruption) along with reducing the lifetime of sensitive data in memory.</string>
+    <string name="aep_hmalloc_ir_no_native_code">This app doesn’t have native code</string>
+    <string name="aep_hmalloc_ir_32_bit_native_code">This is a 32-bit app, hardened_malloc is 64-bit only</string>
+    <string name="aep_hmalloc_ir_preinstalled_app">hardened_malloc is not allowed to be disabled for a preinstalled app</string>
+    <string name="aep_hmalloc_ir_debuggable_app">This is a debuggable app, hardened_malloc can’t be disabled</string>
+
+    <string name="aep_ext_va_space">Extended virtual address space</string>
+    <string name="aep_ext_va_space_footer">Extends virtual address space from 39 to 48 bits, which significantly improves the address space layout randomization.</string>
+    <string name="aep_ext_va_space_ir_32_bit_native_code">Incompatible with 32-bit apps</string>
+    <string name="aep_ext_va_space_ir_hardened_malloc">Required by hardened_malloc</string>
+
+    <string name="aep_native_debug_title">Native code debugging</string>
+    <string name="aep_native_debug_notif_toggle_title">Show notifications about blocked access attempts</string>
+    <string name="aep_native_debug_footer">
+Native code debugging (ptrace) slightly weakens the app sandbox. Some apps (most notably banking apps) use it as a tampering detection tool.
+    </string>
+    <string name="aep_native_debug_dvr_is_system_app">Native debugging is always blocked for preinstalled apps</string>
+
+    <string name="aep_memtag">Memory tagging</string>
+    <string name="aep_memtag_notif_toggle_time">Show notifications about detected errors</string>
+    <string name="aep_memtag_footer">Memory tagging provides strong protections against exploitation of heap memory bugs (e.g. use-after-free, buffer overflow).</string>
+    <string name="aep_memtag_dvr_is_system_app">Memory tagging is always enabled for preinstalled apps</string>
+    <string name="aep_memtag_dvr_no_native_code">Memory tagging is always enabled for apps that don’t have native code</string>
+    <string name="aep_memtag_dvr_manifest_opt_in">This app has opted-in to memory tagging</string>
+
+    <string name="aep_default_memtag_main_switch_title">Enable by default</string>
+    <string name="aep_default_memtag_main_switch_summary">
+        This setting doesn’t apply to apps that are known to be compatible with memory tagging</string>
+    <string name="aep_default_memtag_footer">"Memory tagging provides strong protections against exploitation of heap memory bugs (e.g. use-after-free, buffer overflow).
+
+Memory tagging is always enabled for preinstalled apps and for third-party apps that are known to be
+compatible with it (e.g. apps that don’t have native code), regardless of this setting."</string>
+    <string name="aep_default_memtag_summary_on">Enabled by default</string>
+    <string name="aep_default_memtag_summary_off">
+        Disabled by default, except for apps that are known to be compatible with memory tagging</string>
+
+    <string name="dcl_notif_toggle_title">Show notifications about blocked DCL attempts</string>
+    <string name="aep_default_dcl_footer_ending">This setting doesn’t apply to preinstalled apps, which are always restricted from performing DCL.</string>
+
+    <string name="aep_memory_dcl">Dynamic code loading via memory</string>
+    <string name="aep_memory_dcl_short">DCL via memory</string>
+    <string name="aep_memory_dcl_dvr_is_system_app">DCL via memory is always restricted for this preinstalled app</string>
+    <string name="aep_memory_dcl_footer">
+"Dynamic code loading (DCL) via memory is usually performed by apps that use just-in-time (JIT) compilation to run code from outside their APKs.
+DCL makes the app more vulnerable to exploitation, since the dynamically loaded code can be tampered with or substituted."
+    </string>
+
+    <string name="aep_storage_dcl">Dynamic code loading via storage</string>
+    <string name="aep_storage_dcl_short">DCL via storage</string>
+    <string name="aep_storage_dcl_dvr_is_system_app">DCL via storage is always restricted for this preinstalled app</string>
+    <string name="aep_storage_dcl_footer">
+"Dynamic code loading (DCL) via storage refers to the app's ability to run third-party code from files that are not its APKs.
+DCL makes the app more vulnerable to exploitation, since the dynamically loaded code can be tampered with or substituted."
+    </string>
+
+    <string name="aep_webview_jit">WebView JIT</string>
+    <string name="aep_webview_jit_footer">
+"WebView is an OS component that is used for displaying web content inside apps.
+Just-in-time code compilation (JIT) significantly improves the WebView performance, but makes the app more vulnerable to exploitation.
+
+This setting doesn’t apply to preinstalled apps, WebView JIT is always disabled for the vast majority of them."
+    </string>
+
+</resources>
diff --git a/res/values/strings_ext.xml b/res/values/strings_ext.xml
new file mode 100644
index 00000000000..0cd5e260bb6
--- /dev/null
+++ b/res/values/strings_ext.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="hardware_sku">Hardware SKU</string>
+    <string name="auto_off_never">Never</string>
+
+    <string name="bool_setting_enable">Enable</string>
+    <string name="bool_setting_enabled">Enabled</string>
+    <string name="bool_setting_disabled">Disabled</string>
+
+    <string name="exploit_protection_settings">Exploit protection</string>
+
+    <string name="app_exploit_protection_category">App exploit protection</string>
+
+    <string name="scramble_pin_title">Scramble PIN input layout</string>
+
+    <string name="auto_grant_OTHER_SENSORS_permission_title">Allow Sensors permission to apps by default</string>
+    <string name="auto_grant_OTHER_SENSORS_permission_summary_on">Sensors is a non-standard permission, apps may malfunction if it’s denied.</string>
+    <string name="auto_grant_OTHER_SENSORS_permission_summary_off">A permission prompt will be shown when an app tries to access sensors. Note that some apps may need to be manually restarted after allowing the Sensors permission.</string>
+
+    <string name="keyguard_camera_title">Allow camera access when locked</string>
+
+    <string name="auto_reboot_title">Auto reboot</string>
+    <string name="auto_reboot_footer">Automatically reboot the device if it hasn\'t been unlocked within the selected duration of time.</string>
+
+    <string name="screenshot_timestamp_exif_title">Save screenshot timestamp to EXIF</string>
+    <string name="screenshot_timestamp_exif_summary">Enables adding a timestamp to screenshot EXIF metadata</string>
+
+    <string name="pref_gnss_supl_title">Secure User Plane Location (SUPL)</string>
+    <string name="pref_gnss_supl_footer">A-GNSS (assisted satellite geolocation) based on nearby cell towers.</string>
+
+    <string name="supl_enabled_grapheneos_proxy">GrapheneOS proxy</string>
+    <string name="supl_enabled_standard_server">Standard server</string>
+    <string name="supl_disabled">Off</string>
+    <string name="supl_disabled_summary">Will make acquiring location lock significantly slower, especially if PSDS is turned off too</string>
+
+    <string name="g_euicc_lpa_title">eSIM support</string>
+    <string name="g_euicc_lpa_enable_dialog_msg">
+A device restart is required to enable this setting.
+    </string>
+    <string name="g_euicc_lpa_disable_dialog_title">Warning</string>
+    <string name="g_euicc_lpa_disable_dialog_msg">
+"Turning off eSIM support will break the following functionality:
+
+• adding new eSIMs
+• turning existing eSIMs on or off
+• removing eSIMs, including from the lock screen (e.g. when eSIM is locked with a forgotten PIN)
+• wiping eSIMs during factory reset
+
+Device will be automatically restarted."
+    </string>
+    <string name="g_euicc_lpa_restart_button">Restart</string>
+    <string name="g_euicc_lpa_proceed_button">Proceed</string>
+
+    <string name="remote_provisioning_title">Attestation key provisioning</string>
+    <string name="remote_provisioning_enabled_grapheneos_proxy">GrapheneOS proxy</string>
+    <string name="remote_provisioning_enabled_google_server">Google server</string>
+    <string name="remote_provisioning_disabled">Off</string>
+
+    <string name="Google_apps_special_accelerator_access_title">Special access to hardware accelerators for Google apps</string>
+    <string name="Google_apps_special_accelerator_access_summary_granted">Access granted</string>
+    <string name="Google_apps_special_accelerator_access_summary_not_granted">Access not granted</string>
+    <string name="Google_apps_special_accelerator_access_main_switch">Grant special access to hardware accelerators to Google apps</string>
+    <string name="Google_apps_special_accelerator_access_footer">
+"Some Google apps expect to be able to access hardware accelerators in a special, more capable way than regular apps do.
+
+Examples of such apps:
+• Pixel Camera
+• Google Photos
+• Google Recorder
+
+This setting applies to all users on the device."
+    </string>
+
+    <string name="pref_gnss_psds_title">Predicted Satellite Data Service (PSDS)</string>
+    <string name="gnss_psds_footer">
+"If PSDS is turned on, static PSDS information files will be downloaded periodically to improve location resolution speed and accuracy.
+No query or data is sent to the server. These files contain orbits and statuses of satellites, Earth environmental data and time adjustment information."
+</string>
+    <string name="psds_enabled_grapheneos_server">GrapheneOS server</string>
+    <string name="psds_enabled_qualcomm_server">Qualcomm server</string>
+    <string name="psds_enabled_standard_server">Standard server</string>
+    <string name="psds_disabled">Off</string>
+    <string name="psds_disabled_summary">Will make acquiring location lock significantly slower, especially if SUPL is turned off too</string>
+
+    <string name="contact_scopes">Contact Scopes</string>
+
+    <string name="conn_checks_grapheneos_server">GrapheneOS server</string>
+    <string name="conn_checks_google_server">Standard (Google) server</string>
+    <string name="conn_checks_disabled">Off</string>
+
+    <string name="conn_checks_title">Internet connectivity checks</string>
+    <string name="conn_checks_footer">
+"Connectivity check is a special empty server request that is made to find out whether the current network has internet connection.
+There are HTTP, HTTPS, DNS, DNS-over-TLS and DNS-over-HTTPS connectivity checks.
+    </string>
+
+    <string name="wifi_auto_off_title">Turn off Wi-Fi automatically</string>
+    <string name="wifi_auto_off_footer">If Wi-Fi is disconnected, it will be turned off after the selected timeout.</string>
+
+    <string name="bluetooth_auto_off_title">Turn off Bluetooth automatically</string>
+    <string name="bluetooth_auto_off_footer">
+"If there are no connected devices, Bluetooth will turn off after the selected timeout."
+    </string>
+
+    <string name="deny_new_usb_title">USB peripherals</string>
+    <string name="deny_new_usb_footer">This feature exists to reduce attack surface, especially for a locked device.</string>
+
+    <string name="deny_new_usb_val_disabled">Allow new USB peripherals</string>
+    <string name="deny_new_usb_val_dynamic">Allow new USB peripherals when unlocked</string>
+    <string name="deny_new_usb_val_enabled">Disallow new USB peripherals</string>
+
+    <string name="exec_spawning_title">Secure app spawning</string>
+    <string name="exec_spawning_title_inner">Use secure app spawning</string>
+    <string name="exec_spawning_footer">Launch apps in a more secure way than Android which takes slightly longer and increases memory usage by app processes.</string>
+
+    <string name="widevine_provisioning_title">Widevine provisioning</string>
+    <string name="widevine_provisioning_enabled_grapheneos_proxy">GrapheneOS proxy</string>
+    <string name="widevine_provisioning_enabled_google_server">Google server</string>
+    <string name="widevine_provisioning_footer">The provisioned certificate will be used for accessing DRM protected content.</string>
+
+    <!-- Title of preference to enable app installs and updates [CHAR LIMIT=40] -->
+    <string name="user_app_install">App installs and updates</string>
+    <!-- Options for setting app install and updates per user -->
+    <string name="user_app_install_enabled">Enabled</string>
+    <string name="user_app_install_enabled_first_party_sources">Enabled for first party sources</string>
+    <string name="user_app_install_disabled">Disabled</string>
+    <!-- Description for options for setting app installs and updates per user -->
+    <string name="user_app_install_enabled_desc">Enable app installs and updates</string>
+    <string name="user_app_install_enabled_first_party_sources_desc">Enable app installs and updates from first party sources only</string>
+    <string name="user_app_install_disabled_desc">Disable app installs and updates</string>
+    <!-- Title of preference to enable running in background [CHAR LIMIT=40] -->
+    <string name="user_run_in_background">Allow running in background</string>
+
+    <string name="allow_automatic_per_app_epcm_title">Automatic exploit protection compatibility mode</string>
+
+    <string name="allow_automatic_per_app_epcm_summary">
+"Allow automatically disabling exploit protections for apps that are known to need it"
+    </string>
+
+    <string name="app_exploit_protection_default_value_warning">"Warning: enabling this setting might cause some apps to stop working.</string>
+
+    <string name="show_system_process_crash_notifs_title">Notify about system process crashes</string>
+    <string name="show_system_process_crash_notifs_summary">Such crashes may indicate exploitation attempts</string>
+
+    <string name="view_logs">View logs</string>
+
+    <string name="usbc_port_title">USB-C port</string>
+    <string name="usbc_port_off_title">Off</string>
+    <string name="usbc_port_off_summary">Turns off the USB-C port.
+        Doesn’t impact the separate charging mode, which is activated by turning off the device and plugging it in to a charger.
+    </string>
+    <string name="usbc_port_charging_only_title">Charging-only</string>
+    <string name="usbc_port_charging_only_summary">Turns off all non-charging USB-C port functionality.</string>
+    <string name="usbc_port_charging_only_when_locked_title">Charging-only when locked</string>
+    <string name="usbc_port_charging_only_when_locked_summary">Enables the charging-only mode when the
+        device is locked and disables it when the device becomes unlocked. If the port is already
+        plugged-in at the time when the device becomes locked, then the activation of charging-only
+        mode will be delayed until the port is disconnected.</string>
+    <string name="usbc_port_charging_only_when_locked_afu_title">Charging-only when locked, except before first unlock</string>
+    <string name="usbc_port_charging_only_when_locked_afu_summary">This mode has the same behavior
+        as the “%1$s” mode, except for an additional exemption for before-first-unlock connections.
+    </string>
+    <string name="usbc_port_on_title">On</string>
+    <string name="usbc_port_on_summary">Does not add any restrictions.</string>
+
+    <string name="usbc_port_and_pogo_pins_title">USB-C port and pogo pins</string>
+    <string name="usbc_port_and_pogo_pins_off_title">USB-C port off, pogo pins used only for charging</string>
+    <string name="usbc_port_and_pogo_pins_off_summary">Turns off the USB-C port and turns off all
+        non-charging pogo pins functionality. Doesn’t impact the separate charging mode, which is
+        activated by turning off the device and plugging it in to a charger.
+    </string>
+    <string name="usbc_port_and_pogo_pins_charging_only_summary">Turns off all non-charging USB-C port and pogo pins functionality.</string>
+    <string name="usbc_port_and_pogo_pins_charging_only_when_locked_summary">Enables the charging-only mode when the
+        device is locked and disables it when the device becomes unlocked. If the port is already
+        plugged-in at the time when the device becomes locked, then the activation of charging-only
+        mode will be delayed until the port is disconnected. The same behavior applies to pogo pins.
+    </string>
+
+    <string name="duress_pwd_pref_title">Duress password</string>
+    <string name="duress_pwd_description">"Duress password can be entered instead of the user password in any place that asks for it, such as the lock screen of any user and any user or work profile password prompt.
+
+Submitting the duress password will immediately make the storage contents permanently inaccessible, delete all eSIMs and then power off the device. GrapheneOS will remain installed.
+
+Duress PIN works the same way duress password does."</string>
+    <string name="duress_pwd_enter_pin">Enter duress PIN</string>
+    <string name="duress_pwd_confirm_pin">Confirm duress PIN</string>
+    <string name="duress_pwd_enter_password">Enter duress password</string>
+    <string name="duress_pwd_confirm_password">Confirm duress password</string>
+    <string name="duress_pwd_action_add">Add duress PIN and password</string>
+    <string name="duress_pwd_add_button">Add</string>
+    <string name="duress_pwd_toast_added">Added duress PIN and password</string>
+    <string name="duress_pwd_toast_updated">Updated duress PIN and password</string>
+    <string name="duress_pwd_update_button">Update</string>
+    <string name="duress_pwd_cancel_button">Cancel</string>
+    <string name="duress_pwd_proceed_button">Proceed</string>
+    <string name="duress_pwd_delete_button">Delete</string>
+    <string name="duress_pwd_action_update">Update duress PIN and password</string>
+    <string name="duress_pwd_action_delete">Delete duress PIN and password</string>
+    <string name="duress_pwd_action_delete_confirmation">Delete duress PIN and password?</string>
+    <string name="duress_pwd_save_warning_title">WARNING</string>
+    <string name="duress_pwd_save_warning_text">"Submitting the duress PIN/password instead of the user PIN/password <b>will immediately make the storage contents permanently inaccessible</b> and will delete all eSIMs."</string>
+    <string name="duress_pwd_save_error">Duress PIN and password were not saved.\n\nDetails:\n%1$s</string>
+    <string name="duress_pwd_delete_error">Duress PIN and password were not deleted.\n\nDetails:\n%1$s</string>
+    <string name="duress_pwd_error_dialog_dismiss">Dismiss</string>
+
+    <string name="alt_touchscreen_mode_title">Alternative touchscreen mode</string>
+    <string name="alt_touchscreen_mode_summary">This mode is less susceptible to ghost touches. Don’t enable it unless you are experiencing touchscreen issues.</string>
+    <string name="alt_touchscreen_mode_confirm_message">Confirm that the touchscreen is working. Without confirmation, alternative touchscreen mode will be disabled after several seconds.</string>
+    <string name="alt_touchscreen_mode_confirm_button">Confirm</string>
+
+</resources>
diff --git a/res/values/strings_keyguard_fingerprint.xml b/res/values/strings_keyguard_fingerprint.xml
new file mode 100644
index 00000000000..edf85b2602a
--- /dev/null
+++ b/res/values/strings_keyguard_fingerprint.xml
@@ -0,0 +1,4 @@
+<resources>
+    <string name="keyguard_fingerprint_title">Use for screen unlocking</string>
+    <string name="keyguard_fingerprint_summary">When disabled, fingerprint unlock can still be used in apps</string>
+</resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index e91ca491213..c184a3e129b 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -250,4 +250,8 @@
         <item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
         <item name="colorAccent">@*android:color/accent_device_default_light</item>
     </style>
+
+    <style name="Theme.DeviceDefault.DayNight.NoEdgeToEdge" parent="@android:style/Theme.DeviceDefault.DayNight">
+        <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
+    </style>
 </resources>
diff --git a/res/values/themes_suw.xml b/res/values/themes_suw.xml
index 9efac286487..d7fec0b5c1d 100644
--- a/res/values/themes_suw.xml
+++ b/res/values/themes_suw.xml
@@ -150,6 +150,7 @@
 
         <!-- LockPatternView colors -->
         <item name="*android:lockPatternStyle">@style/LockPatternStyle</item>
+        <item name="sudUseBottomProgressBar">true</item>
     </style>
 
     <style name="GlifV4Theme.Light" parent="SudThemeGlifV4.Light">
@@ -168,6 +169,7 @@
         <item name="preferenceTheme">@style/PreferenceTheme.SetupWizard</item>
 
         <item name="*android:lockPatternStyle">@style/LockPatternStyle</item>
+        <item name="sudUseBottomProgressBar">true</item>
     </style>
 
     <style name="GlifV3Theme.Light.NoActionBar" parent="GlifV3Theme.Light">
diff --git a/res/xml/apps.xml b/res/xml/apps.xml
index 2ffd0b1eaba..0598d316a54 100644
--- a/res/xml/apps.xml
+++ b/res/xml/apps.xml
@@ -124,4 +124,17 @@
         </Preference>
     </PreferenceCategory>
 
+    <Preference
+        android:key="sandboxed_google_play"
+        android:title="@string/sandboxed_google_play"
+        android:order="-980"
+        settings:controller="com.android.settings.applications.GmsCompatAppController"/>
+
+    <Preference
+        android:key="sandboxed_google_play_work_profile"
+        android:title="@string/sandboxed_google_play_work_profile"
+        android:order="-979"
+        settings:forWork="true"
+        settings:controller="com.android.settings.applications.GmsCompatAppController"/>
+
 </PreferenceScreen>
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 4e52cf49092..cd51a3fb38e 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -165,6 +165,18 @@
             android:summary="@string/peak_refresh_rate_summary"
             settings:controller="com.android.settings.display.PeakRefreshRatePreferenceController"/>
 
+        <SwitchPreferenceCompat
+            android:key="touch_sensitivity"
+            android:title="@string/touch_sensitivity_title"
+            android:summary="@string/touch_sensitivity_summary"
+            settings:controller="com.android.settings.display.TouchSensitivityPreferenceController" />
+
+        <SwitchPreferenceCompat
+            android:key="alt_touchscreen_mode"
+            android:title="@string/alt_touchscreen_mode_title"
+            android:summary="@string/alt_touchscreen_mode_summary"
+            settings:controller="com.android.settings.display.AltTouchscreenModePrefController" />
+
         <SwitchPreferenceCompat
             android:key="show_operator_name"
             android:title="@string/show_operator_name_title"
diff --git a/res/xml/double_tap_power_settings.xml b/res/xml/double_tap_power_settings.xml
index fb5dd52b913..7896046d1cd 100644
--- a/res/xml/double_tap_power_settings.xml
+++ b/res/xml/double_tap_power_settings.xml
@@ -24,7 +24,7 @@
     <com.android.settingslib.widget.IllustrationPreference
         android:key="gesture_double_tap_power_video"
         settings:searchable="false"
-        app:lottie_rawRes="@drawable/quickly_open_camera"/>
+        app:lottie_rawRes="@raw/lottie_quickly_open_camera"/>
 
     <SwitchPreferenceCompat
         android:key="gesture_double_tap_power"
diff --git a/res/xml/exploit_protection_settings.xml b/res/xml/exploit_protection_settings.xml
new file mode 100644
index 00000000000..041c28690d3
--- /dev/null
+++ b/res/xml/exploit_protection_settings.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="exploit_protection_settings"
+    android:title="@string/exploit_protection_settings">
+
+    <Preference
+        android:key="auto_reboot"
+        android:title="@string/auto_reboot_title"
+        settings:controller="com.android.settings.security.AutoRebootPrefController" />
+
+    <Preference
+        android:key="usbc_port"
+        android:title="@string/usbc_port_title"
+        settings:controller="com.android.settings.security.UsbPortSecurityPrefController" />
+
+    <Preference
+        android:key="usbc_port_and_pogo_pins"
+        android:title="@string/usbc_port_and_pogo_pins_title"
+        settings:controller="com.android.settings.security.UsbPortSecurityPrefController" />
+
+    <Preference
+        android:key="deny_new_usb"
+        android:title="@string/deny_new_usb_title"
+        settings:controller="com.android.settings.security.DenyNewUsbPrefController" />
+
+    <Preference
+        android:key="wifi_auto_off"
+        android:title="@string/wifi_auto_off_title"
+        settings:controller="com.android.settings.wifi.WifiAutoOffPrefController"/>
+
+    <Preference
+        android:key="bluetooth_auto_off"
+        android:title="@string/bluetooth_auto_off_title"
+        settings:controller="com.android.settings.bluetooth.BluetoothAutoOffPrefController"/>
+
+    <PreferenceCategory
+        android:key="app_exploit_protection_settings"
+        android:title="@string/app_exploit_protection_category">
+
+        <Preference
+            android:key="aep_h_malloc_app_list"
+            android:title="@string/aep_hmalloc"
+            settings:controller="com.android.settings.applications.HardenedMallocAppListPrefController" />
+
+        <Preference
+            android:key="aep_memtag"
+            android:title="@string/aep_memtag"
+            android:fragment="com.android.settings.applications.AppDefaultMemtagFragment"
+            settings:controller="com.android.settings.applications.AppDefaultMemtagPrefController" />
+
+        <Preference
+            android:key="aep_memtag_app_list"
+            android:title="@string/aep_memtag"
+            settings:controller="com.android.settings.applications.MemtagAppListPrefController" />
+
+        <Preference
+            android:key="aep_extended_va_space_app_list"
+            android:title="@string/aep_ext_va_space"
+            settings:controller="com.android.settings.applications.ExtendedVaSpaceAppListPrefController" />
+
+        <Preference
+            android:key="aep_native_debugging"
+            android:title="@string/aep_native_debug_title"
+            android:fragment="com.android.settings.applications.AppDefaultNativeDebuggingFragment"
+            settings:controller="com.android.settings.applications.AppDefaultNativeDebuggingPrefController" />
+
+        <Preference
+            android:key="aep_native_debugging_app_list"
+            android:title="@string/aep_native_debug_title"
+            settings:controller="com.android.settings.applications.NativeDebuggingAppListPrefController" />
+
+        <Preference
+            android:key="aep_webview_jit"
+            android:title="@string/aep_webview_jit"
+            android:fragment="com.android.settings.applications.AppDefaultWebViewDynCodeLoadingFragment"
+            settings:controller="com.android.settings.applications.AppDefaultWebViewDynCodeLoadingPrefController" />
+
+        <Preference
+            android:key="aep_webview_jit_app_list"
+            android:title="@string/aep_webview_jit"
+            settings:controller="com.android.settings.applications.WebViewDynCodeLoadingAppListPrefController" />
+
+        <Preference
+            android:key="aep_memory_dcl"
+            android:title="@string/aep_memory_dcl"
+            android:fragment="com.android.settings.applications.AppDefaultMemoryDynCodeLoadingFragment"
+            settings:controller="com.android.settings.applications.AppDefaultMemoryDynCodeLoadingPrefController" />
+
+        <Preference
+            android:key="aep_memory_dcl_app_list"
+            android:title="@string/aep_memory_dcl"
+            settings:controller="com.android.settings.applications.MemoryDynCodeLoadingAppListPrefController" />
+
+        <Preference
+            android:key="aep_storage_dcl"
+            android:title="@string/aep_storage_dcl"
+            android:fragment="com.android.settings.applications.AppDefaultStorageDynCodeLoadingFragment"
+            settings:controller="com.android.settings.applications.AppDefaultStorageDynCodeLoadingPrefController" />
+
+        <Preference
+            android:key="aep_storage_dcl_app_list"
+            android:title="@string/aep_storage_dcl"
+            settings:controller="com.android.settings.applications.StorageDynCodeLoadingAppListPrefController" />
+
+        <Preference
+            android:key="exec_spawning"
+            android:title="@string/exec_spawning_title"
+            android:fragment="com.android.settings.security.ExecSpawningFragment"
+            settings:controller="com.android.settings.security.ExecSpawningPrefController" />
+
+    </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/res/xml/firmware_version.xml b/res/xml/firmware_version.xml
index 41f7733cfb2..cf9779a6988 100644
--- a/res/xml/firmware_version.xml
+++ b/res/xml/firmware_version.xml
@@ -37,14 +37,6 @@
         settings:enableCopying="true"
         settings:controller="com.android.settings.deviceinfo.firmwareversion.SecurityPatchLevelPreferenceController"/>
 
-    <!-- Mainline module version -->
-    <Preference
-        android:key="module_version"
-        android:title="@string/module_version"
-        android:summary="@string/summary_placeholder"
-        settings:enableCopying="true"
-        settings:controller="com.android.settings.deviceinfo.firmwareversion.MainlineModuleVersionPreferenceController"/>
-
     <!-- Baseband -->
     <Preference
         android:key="base_band"
@@ -54,6 +46,15 @@
         settings:enableCopying="true"
         settings:controller="com.android.settings.deviceinfo.firmwareversion.BasebandVersionPreferenceController"/>
 
+    <!-- Bootloader -->
+    <Preference
+        android:key="boot_loader"
+        android:title="@string/bootloader_version"
+        android:summary="@string/summary_placeholder"
+        android:selectable="false"
+        settings:enableCopying="true"
+        settings:controller="com.android.settings.deviceinfo.firmwareversion.BootloaderVersionPreferenceController"/>
+
     <!-- Kernel -->
     <Preference
         android:key="kernel_version"
diff --git a/res/xml/hardware_info.xml b/res/xml/hardware_info.xml
index e086a486ee0..8fef9371870 100644
--- a/res/xml/hardware_info.xml
+++ b/res/xml/hardware_info.xml
@@ -57,4 +57,13 @@
         settings:controller="com.android.settings.deviceinfo.hardwareinfo.ManufacturedYearPreferenceController"
         settings:enableCopying="true"/>
 
+    <!-- Device SKU -->
+    <Preference
+        android:key="hardware_info_device_sku"
+        android:title="@string/hardware_sku"
+        android:summary="@string/summary_placeholder"
+        android:selectable="false"
+        settings:controller="com.android.settings.deviceinfo.hardwareinfo.HardwareSkuPreferenceController"
+        settings:enableCopying="true"/>
+
 </PreferenceScreen>
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index 3f26d04287e..4c99a9ae6a6 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -69,6 +69,16 @@
             android:title="@string/location_services_preference_title"
             settings:controller="com.android.settings.location.LocationServicesPreferenceController"/>
 
+        <Preference
+            android:key="gnss_supl"
+            android:title="@string/pref_gnss_supl_title"
+            settings:controller="com.android.settings.location.GnssSuplPrefController"/>
+
+        <Preference
+            android:key="gnss_psds"
+            android:title="@string/pref_gnss_psds_title"
+            settings:controller="com.android.settings.location.GnssPsdsPrefController"/>
+
     </PreferenceCategory>
 
     <com.android.settingslib.widget.FooterPreference
diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml
index f2004937f60..342d8841755 100644
--- a/res/xml/more_security_privacy_settings.xml
+++ b/res/xml/more_security_privacy_settings.xml
@@ -91,6 +91,19 @@
             settings:controller=
                 "com.android.settings.sound.MediaControlsLockScreenPreferenceController" />
 
+        <SwitchPreferenceCompat
+            android:key="privacy_auto_grant_OTHER_SENSORS_permission"
+            android:title="@string/auto_grant_OTHER_SENSORS_permission_title"
+            android:summaryOn="@string/auto_grant_OTHER_SENSORS_permission_summary_on"
+            android:summaryOff="@string/auto_grant_OTHER_SENSORS_permission_summary_off"
+            settings:boolSettingField="android.ext.settings.ExtSettings AUTO_GRANT_OTHER_SENSORS_PERMISSION"/>
+
+        <SwitchPreferenceCompat
+            android:key="privacy_screenshot_timestamp_exif"
+            android:title="@string/screenshot_timestamp_exif_title"
+            android:summary="@string/screenshot_timestamp_exif_summary"
+            settings:boolSettingField="android.ext.settings.ExtSettings SCREENSHOT_TIMESTAMP_EXIF"/>
+
         <!-- Allow software fallback for camera extensions -->
         <SwitchPreferenceCompat
             android:key="privacy_camera_extensions_fallback"
@@ -218,6 +231,21 @@
         settings:keywords="@string/keywords_app_pinning"
         settings:controller="com.android.settings.security.ScreenPinningPreferenceController" />
 
+    <SwitchPreferenceCompat
+        android:order="281"
+        android:key="show_system_process_crash_notifs"
+        android:title="@string/show_system_process_crash_notifs_title"
+        android:summary="@string/show_system_process_crash_notifs_summary"
+        settings:boolSettingField=
+            "android.ext.settings.ExtSettings SHOW_SYSTEM_PROCESS_CRASH_NOTIFICATIONS" />
+
+    <SwitchPreferenceCompat
+        android:order="282"
+        android:key="allow_automatic_per_app_epcm"
+        android:title="@string/allow_automatic_per_app_epcm_title"
+        android:summary="@string/allow_automatic_per_app_epcm_summary"
+        settings:boolSettingField="android.ext.settings.ExtSettings ALLOW_DISABLING_HARDENING_VIA_APP_COMPAT_CONFIG" />
+
     <Preference
         android:order="300"
         android:id="@+id/memtag_page"
diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml
index 292f1824552..2975c643ffb 100644
--- a/res/xml/network_provider_internet.xml
+++ b/res/xml/network_provider_internet.xml
@@ -55,6 +55,14 @@
         settings:useAdminDisabledSummary="true"
         settings:controller="com.android.settings.network.MobileNetworkSummaryController" />
 
+    <com.android.settingslib.RestrictedSwitchPreference
+        android:key="google_euicc_lpa"
+        android:title="@string/g_euicc_lpa_title"
+        android:icon="@drawable/ic_sim_card"
+        android:order="-14"
+        settings:controller="com.android.settings.network.GoogleEuiccLpaController"
+        settings:userRestriction="no_config_mobile_networks"/>
+
     <com.android.settingslib.RestrictedSwitchPreference
         android:key="airplane_mode"
         android:title="@string/airplane_mode"
@@ -116,4 +124,22 @@
         android:summary="@string/cellular_security_summary"
         android:order="30"
         settings:controller="com.android.settings.network.CellularSecurityPreferenceController"/>
+
+    <Preference
+        android:key="connectivity_checks"
+        android:title="@string/conn_checks_title"
+        android:order="30"
+        settings:controller="com.android.settings.network.ConnectivityChecksPrefController"/>
+
+    <Preference
+        android:key="remote_provisioning_settings"
+        android:title="@string/remote_provisioning_title"
+        android:order="35"
+        settings:controller="com.android.settings.network.RemoteProvisioningPrefController" />
+    
+    <Preference
+        android:key="widevine_provisioning_settings"
+        android:title="@string/widevine_provisioning_title"
+        android:order="40"
+        settings:controller="com.android.settings.network.WidevineProvisioningPrefController" />
 </PreferenceScreen>
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index 77c6b7322c2..7245528bd47 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -64,6 +64,12 @@
         android:summary="@string/battery_percentage_description"
         settings:controller="com.android.settings.display.BatteryPercentagePreferenceController" />
 
+    <SwitchPreferenceCompat
+        android:key="battery_share"
+        android:title="@string/battery_share"
+        android:summary="@string/battery_share_description"
+        settings:controller="com.android.settings.display.BatterySharePreferenceController" />
+
     <com.android.settingslib.widget.FooterPreference
         android:key="power_usage_footer"
         android:title="@string/battery_footer_summary"
diff --git a/res/xml/private_space_hide_locked.xml b/res/xml/private_space_hide_locked.xml
index 56dd1514cad..ee7a2110aa5 100644
--- a/res/xml/private_space_hide_locked.xml
+++ b/res/xml/private_space_hide_locked.xml
@@ -18,12 +18,6 @@
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/private_space_hide_page_title">
 
-    <com.android.settingslib.widget.IllustrationPreference
-        android:key="private_space_hide_illustration"
-        settings:searchable="false"
-        settings:lottie_rawRes="@raw/private_space_hide_when_locked_illustration"
-        settings:controller="com.android.settings.privatespace.HidePrivateSpaceIllustrationController"/>
-
     <com.android.settingslib.widget.MainSwitchPreference
         android:key="hide_when_locked"
         android:title="@string/private_space_hide_when_locked"
@@ -35,32 +29,4 @@
         android:selectable="false"
         settings:searchable="false" />
 
-    <PreferenceCategory
-        android:key="private_space_access"
-        android:title="@string/private_space_access_header"
-        settings:controller="com.android.settings.privatespace.HidePrivateSpaceCategoryController">
-
-        <Preference
-        android:key="search_when_locked_footer"
-        android:icon="@drawable/counter_1_24dp"
-        android:title="@string/private_space_search_description"
-        android:selectable="false"
-        settings:searchable="false" />
-
-        <Preference
-            android:key="tap_tile_footer"
-            android:icon="@drawable/counter_2_24dp"
-            android:title="@string/private_space_tap_tile_description"
-            android:selectable="false"
-            settings:searchable="false" />
-
-        <Preference
-            android:key="unlock_profile_footer"
-            android:icon="@drawable/counter_3_24dp"
-            android:title="@string/private_space_unlock_description"
-            android:selectable="false"
-            settings:searchable="false" />
-
-    </PreferenceCategory>
-
 </PreferenceScreen>
diff --git a/res/xml/private_space_settings.xml b/res/xml/private_space_settings.xml
index 53bbc5727d4..3f404d0db6c 100644
--- a/res/xml/private_space_settings.xml
+++ b/res/xml/private_space_settings.xml
@@ -56,6 +56,11 @@
             settings:controller="com.android.settings.privatespace.HidePrivateSpaceSummaryController"
             settings:searchable="false" />
 
+        <Preference
+            android:key="sandboxed_google_play_private_space"
+            android:title="@string/sandboxed_google_play"
+            settings:controller="com.android.settings.applications.GmsCompatAppController"/>
+
     </PreferenceCategory>
 
     <PreferenceCategory
diff --git a/res/xml/screen_lock_settings.xml b/res/xml/screen_lock_settings.xml
index 19061d9b855..9b2f088244d 100644
--- a/res/xml/screen_lock_settings.xml
+++ b/res/xml/screen_lock_settings.xml
@@ -33,6 +33,11 @@
         android:title="@string/lock_screen_auto_pin_confirm_title"
         android:summary="@string/lock_screen_auto_pin_confirm_summary" />
 
+    <SwitchPreferenceCompat
+        android:key="scramble_pin_layout"
+        android:title="@string/scramble_pin_title"
+        settings:controller="com.android.settings.security.screenlock.PinScramblingPrefController" />
+
     <SwitchPreferenceCompat
         android:key="enhancedPinPrivacy"
         android:title="@string/lockpattern_settings_enhanced_pin_privacy_title"
@@ -52,4 +57,9 @@
         android:key="power_button_instantly_locks"
         android:title="@string/lockpattern_settings_enable_power_button_instantly_locks" />
 
+    <SwitchPreferenceCompat
+        android:key="allow_keyguard_camera"
+        android:title="@string/keyguard_camera_title"
+        settings:boolSettingField="android.ext.settings.ExtSettings ALLOW_KEYGUARD_CAMERA" />
+
 </PreferenceScreen>
diff --git a/res/xml/screen_pinning_settings.xml b/res/xml/screen_pinning_settings.xml
index 2c4402da89e..f06b42ceab1 100644
--- a/res/xml/screen_pinning_settings.xml
+++ b/res/xml/screen_pinning_settings.xml
@@ -30,7 +30,6 @@
 
     <com.android.settingslib.widget.FooterPreference
         android:key="screen_pinning_settings_screen_footer"
-        android:title="@string/screen_pinning_description"
         settings:searchable="false" />
 
 </PreferenceScreen>
diff --git a/res/xml/security_settings_fingerprint.xml b/res/xml/security_settings_fingerprint.xml
index 9c8b0a3f9ea..f6765590d54 100644
--- a/res/xml/security_settings_fingerprint.xml
+++ b/res/xml/security_settings_fingerprint.xml
@@ -32,8 +32,7 @@
     <PreferenceCategory
         android:key="security_settings_fingerprint_unlock_category"
         android:title="@string/security_settings_fingerprint_settings_preferences_category"
-        settings:controller="com.android.settings.biometrics.fingerprint.FingerprintUnlockCategoryController"
-        settings:isPreferenceVisible="false">
+        settings:controller="com.android.settings.biometrics.fingerprint.FingerprintUnlockCategoryController">
 
         <com.android.settingslib.RestrictedSwitchPreference
             android:key="@string/security_settings_require_screen_on_to_auth_key"
@@ -41,6 +40,13 @@
             android:summary="@string/security_settings_require_screen_on_to_auth_description"
             settings:keywords="@string/security_settings_require_screen_on_to_auth_keywords"
             settings:controller="com.android.settings.biometrics.fingerprint.FingerprintSettingsRequireScreenOnToAuthPreferenceController" />
+
+        <com.android.settingslib.RestrictedSwitchPreference
+            android:key="fingerprint_enable_keyguard_toggle"
+            android:title="@string/keyguard_fingerprint_title"
+            android:summary="@string/keyguard_fingerprint_summary"
+            settings:controller="com.android.settings.biometrics.fingerprint.FingerprintSettingsKeyguardPreferenceController" />
+
     </PreferenceCategory>
 
     <PreferenceCategory
diff --git a/res/xml/sim_lock_settings.xml b/res/xml/sim_lock_settings.xml
index 02db847aef5..baa0ad597b5 100644
--- a/res/xml/sim_lock_settings.xml
+++ b/res/xml/sim_lock_settings.xml
@@ -23,6 +23,11 @@
             android:summaryOn="@string/sim_lock_on"
             android:summaryOff="@string/sim_lock_off"/>
 
+    <SwitchPreferenceCompat
+            android:key="sim_scramble_pin_layout"
+            android:dependency="sim_toggle"
+            android:title="@string/scramble_pin_title"/>
+
     <com.android.settings.EditPinPreference
             android:key="sim_pin"
             android:dependency="sim_toggle"
diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml
index 7e8969de07d..cc630f79ff0 100644
--- a/res/xml/special_access.xml
+++ b/res/xml/special_access.xml
@@ -226,4 +226,10 @@
             android:name="classname"
             android:value="com.android.settings.Settings$ChangeNfcTagAppsActivity" />
     </Preference>
+
+    <Preference
+        android:key="Google_apps_special_accelerator_access"
+        android:title="@string/Google_apps_special_accelerator_access_title"
+        android:fragment="com.android.settings.applications.specialaccess.GoogleSpecialAcceleratorAccessFragment"
+        settings:controller="com.android.settings.applications.specialaccess.GoogleSpecialAcceleratorAccessPrefController" />
 </PreferenceScreen>
diff --git a/res/xml/system_dashboard_fragment.xml b/res/xml/system_dashboard_fragment.xml
index 621a3253a83..6d335097b1a 100644
--- a/res/xml/system_dashboard_fragment.xml
+++ b/res/xml/system_dashboard_fragment.xml
@@ -84,6 +84,13 @@
         <intent android:action="android.settings.SYSTEM_UPDATE_SETTINGS"/>
     </Preference>
 
+    <Preference
+        android:key="view_logs"
+        android:title="@string/view_logs"
+        android:icon="@drawable/ic_settings_development"
+        android:order="-39"
+        settings:controller="com.android.settings.system.LogcatLinkPrefController"/>
+
     <Preference
         android:key="system_multiuser"
         android:title="@string/user_settings_title"
diff --git a/res/xml/tether_prefs.xml b/res/xml/tether_prefs.xml
index 89bd631bcd2..c3fe5884bcc 100644
--- a/res/xml/tether_prefs.xml
+++ b/res/xml/tether_prefs.xml
@@ -49,6 +49,12 @@
         android:summary="@string/ethernet_tethering_subtext"
         settings:keywords="@string/keywords_hotspot_tethering" />
 
+    <SwitchPreferenceCompat
+        android:key="enable_data_saver_tethering"
+        android:title="@string/data_saver_tether_checkbox_text"
+        android:summary="@string/data_saver_tethering_subtext"
+        settings:keywords="@string/keywords_hotspot_tethering" />
+
     <com.android.settingslib.widget.FooterPreference
         android:key="disabled_on_data_saver"
         android:title="@string/tether_settings_disabled_on_data_saver"
diff --git a/res/xml/top_level_settings.xml b/res/xml/top_level_settings.xml
index 44fe7fcc3d3..fbbe0b28814 100644
--- a/res/xml/top_level_settings.xml
+++ b/res/xml/top_level_settings.xml
@@ -18,7 +18,8 @@
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
-    android:key="top_level_settings">
+    android:key="top_level_settings"
+    android:title="Settings">
 
     <com.android.settings.widget.HomepagePreference
         android:fragment="com.android.settings.network.NetworkDashboardFragment"
diff --git a/res/xml/user_details_settings.xml b/res/xml/user_details_settings.xml
index 8e15d14bf5a..5f6df097ec9 100644
--- a/res/xml/user_details_settings.xml
+++ b/res/xml/user_details_settings.xml
@@ -25,6 +25,10 @@
             android:key="user_grant_admin"
             android:icon="@drawable/ic_admin_panel_settings"
             android:title="@string/user_grant_admin" />
+    <SwitchPreferenceCompat
+            android:icon="@drawable/ic_sync"
+            android:key="allow_run_in_background"
+            android:title="@string/user_run_in_background" />
     <SwitchPreferenceCompat
             android:key="enable_calling"
             android:icon="@drawable/ic_phone"
@@ -33,6 +37,10 @@
             android:key="app_and_content_access"
             android:icon="@drawable/ic_lock_closed"
             android:title="@string/user_restrictions_title" />
+    <com.android.settingslib.RestrictedPreference
+            android:key="app_installs"
+            android:icon="@drawable/ic_settings_install"
+            android:title="@string/user_app_install" />
     <com.android.settingslib.RestrictedPreference
             android:key="app_copying"
             android:icon="@drawable/ic_apps"
diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml
index 59217226592..33a7adedb4f 100644
--- a/res/xml/user_settings.xml
+++ b/res/xml/user_settings.xml
@@ -100,4 +100,10 @@
         android:fragment="com.android.settings.users.TimeoutToDockUserSettings"
         settings:controller="com.android.settings.users.TimeoutToDockUserPreferenceController"/>
 
+    <SwitchPreferenceCompat
+            android:key="user_settings_send_censored_notifications_to_current"
+            android:title="@string/user_settings_send_censored_notifications_to_current"
+            android:summary="@string/user_settings_send_censored_notifications_to_current_summary"
+            android:order="106"/>
+
 </PreferenceScreen>
diff --git a/res/xml/wifi_network_details_fragment2.xml b/res/xml/wifi_network_details_fragment2.xml
index da4ea5a5e66..38e8f4b55eb 100644
--- a/res/xml/wifi_network_details_fragment2.xml
+++ b/res/xml/wifi_network_details_fragment2.xml
@@ -99,8 +99,8 @@
         android:key="privacy"
         android:icon="@drawable/ic_wifi_privacy_24dp"
         android:title="@string/wifi_privacy_settings"
-        android:entries="@array/wifi_privacy_entries"
-        android:entryValues="@array/wifi_privacy_values"/>
+        android:entries="@array/wifi_privacy_entries_ext"
+        android:entryValues="@array/wifi_privacy_values_ext"/>
 
     <com.android.settings.spa.preference.ComposePreference
         android:key="privacy_settings"
diff --git a/src/com/android/settings/IccLockSettings.java b/src/com/android/settings/IccLockSettings.java
index 422610a4856..4678ae96be4 100644
--- a/src/com/android/settings/IccLockSettings.java
+++ b/src/com/android/settings/IccLockSettings.java
@@ -23,6 +23,7 @@
 import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.ext.settings.ExtSettings;
 import android.graphics.PixelFormat;
 import android.os.AsyncTask;
 import android.os.Bundle;
@@ -124,6 +125,7 @@ public class IccLockSettings extends SettingsPreferenceFragment
 
     private EditPinPreference mPinDialog;
     private TwoStatePreference mPinToggle;
+    private TwoStatePreference mPinScramblingToggle;
 
     private Resources mRes;
 
@@ -195,6 +197,10 @@ public void onCreate(Bundle savedInstanceState) {
 
         mPinDialog = (EditPinPreference) findPreference(PIN_DIALOG);
         mPinToggle = (TwoStatePreference) findPreference(PIN_TOGGLE);
+        mPinScramblingToggle = (TwoStatePreference) findPreference("sim_scramble_pin_layout");
+        mPinScramblingToggle.setOnPreferenceChangeListener((preference, newValue) -> {
+            return ExtSettings.SCRAMBLE_SIM_PIN_LAYOUT.put(requireContext(), (boolean) newValue);
+        });
         if (savedInstanceState != null) {
             if (savedInstanceState.containsKey(DIALOG_STATE)
                     && restoreDialogStates(savedInstanceState)) {
@@ -358,6 +364,8 @@ private void updatePreferences() {
                 mPinToggle.setChecked(isIccLockEnabled());
             }
         }
+
+        mPinScramblingToggle.setChecked(ExtSettings.SCRAMBLE_SIM_PIN_LAYOUT.get(requireContext()));
     }
 
     @Override
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 7678338976a..b964d34ab53 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -515,4 +515,16 @@ public static class ResetMobileNetworkSettingsActivity extends SettingsActivity
 
     public static class HearingDevicesActivity extends SettingsActivity { /* empty */ }
     public static class HearingDevicesPairingActivity extends SettingsActivity { /* empty */ }
+
+    public static class AppMemtagActivity extends SettingsActivity {}
+
+    public static class AppHardenedMallocActivity extends SettingsActivity {}
+
+    public static class AppMemoryDynCodeLoadingActivity extends SettingsActivity {}
+
+    public static class AppNativeDebuggingActivity extends SettingsActivity {}
+
+    public static class AppStorageDynCodeLoadingActivity extends SettingsActivity {}
+
+    public static class ExploitProtectionActivity extends SettingsActivity {}
 }
diff --git a/src/com/android/settings/SettingsApplication.java b/src/com/android/settings/SettingsApplication.java
index b1177dd2d87..6399d20c02d 100644
--- a/src/com/android/settings/SettingsApplication.java
+++ b/src/com/android/settings/SettingsApplication.java
@@ -71,6 +71,8 @@ protected void attachBaseContext(Context base) {
     public void onCreate() {
         super.onCreate();
 
+        VanadiumLibraryCleanup.maybeRun(this);
+
         if (Flags.catalyst()) {
             PreferenceScreenRegistry.INSTANCE.setPreferenceScreensSupplier(
                     this::getPreferenceScreens);
diff --git a/src/com/android/settings/VanadiumLibraryCleanup.java b/src/com/android/settings/VanadiumLibraryCleanup.java
new file mode 100644
index 00000000000..79d44934827
--- /dev/null
+++ b/src/com/android/settings/VanadiumLibraryCleanup.java
@@ -0,0 +1,114 @@
+package com.android.settings;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.SigningInfo;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HexFormat;
+import java.util.List;
+
+// Due to a bug in boot-time package verification extensions (PackageVerityExt), Vanadium Trichrome
+// static shared library was removed in some cases in an incorrect way. Only the library APK was
+// removed, all library package state was left behind: package setting, per-user package state,
+// per-user permission state etc.
+//
+// PackageVerityExt bug is now fixed. This one-time cleanup task removes leftover package states.
+public class VanadiumLibraryCleanup {
+    private static final String TAG = VanadiumLibraryCleanup.class.getSimpleName();
+
+    private static final String MARKER_FILE_NAME = "vanadium_trichrome_library_cleanup_done2";
+
+    public static void maybeRun(Context ctx) {
+        if (ctx.getUserId() != UserHandle.USER_SYSTEM) {
+            return;
+        }
+
+        ThreadUtils.postOnBackgroundThread(() -> {
+            try {
+                run(ctx);
+            } catch (Throwable e) {
+                // don't crash, removing these leftovers is not that important
+                Log.e(TAG, "", e);
+            }
+        });
+    }
+
+    private static void run(Context ctx) {
+        File markerFile = new File(ctx.getFilesDir(), MARKER_FILE_NAME);
+        if (markerFile.isFile()) {
+            return;
+        }
+
+        // MATCH_ANY_USER is needed in case the user has manually uninstalled these entries in USER_SYSTEM
+        int baseFlags = PackageManager.MATCH_ANY_USER | PackageManager.MATCH_UNINSTALLED_PACKAGES;
+
+        PackageManager pm = ctx.getPackageManager();
+        List<ApplicationInfo> installedPkgs =
+                pm.getInstalledApplications(baseFlags);
+
+        byte[] vanadiumCertDigest = HexFormat.of()
+                .parseHex("c6adb8b83c6d4c17d292afde56fd488a51d316ff8f2c11c5410223bff8a7dbb3");
+
+        var deleteObserver = new DeleteObserver();
+
+        for (ApplicationInfo appInfo : installedPkgs) {
+            String pkgName = appInfo.packageName;
+            // Static shared libraries have a synthetic package name:
+            // <package name> <underscore> <package version>
+            if (!pkgName.startsWith("app.vanadium.trichromelibrary_")) {
+                continue;
+            }
+
+            Log.d(TAG, "processing " + pkgName);
+            PackageInfo pkgInfo;
+            try {
+                pkgInfo = pm.getPackageInfo(pkgName, baseFlags | PackageManager.GET_SIGNING_CERTIFICATES);
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.e(TAG, "", e);
+                continue;
+            }
+            SigningInfo signingInfo = pkgInfo.signingInfo;
+            if (signingInfo == null) {
+                Log.w(TAG, "signingInfo is null");
+                continue;
+            }
+            if (!signingInfo.getSigningDetails().hasSha256Certificate(vanadiumCertDigest)) {
+                Log.w(TAG, "unknown signing certificate");
+                continue;
+            }
+
+            if (appInfo.sourceDir != null) {
+                Log.w(TAG, "base APK is not null");
+                continue;
+            }
+            // there's no need to check whether this ApplicationInfo represents an actual static
+            // shared library, they are filtered out by default
+
+            pm.deletePackage(pkgName, deleteObserver, PackageManager.DELETE_ALL_USERS);
+        }
+
+        try {
+            if (!markerFile.createNewFile()) {
+                Log.w(TAG, "markerFile.createNewFile() returned false");
+            }
+        } catch (IOException e) {
+            Log.w(TAG, "unable to create markerFile", e);
+        }
+    }
+
+    static class DeleteObserver extends android.content.pm.IPackageDeleteObserver.Stub {
+        @Override
+        public void packageDeleted(String packageName, int returnCode) {
+            Log.d(TAG, "packageDeleted callback for " + packageName
+                    + ", result " + PackageManager.deleteStatusToString(returnCode));
+        }
+    }
+}
diff --git a/src/com/android/settings/applications/AppExtendedVaSpace.kt b/src/com/android/settings/applications/AppExtendedVaSpace.kt
new file mode 100644
index 00000000000..a44ca968cd6
--- /dev/null
+++ b/src/com/android/settings/applications/AppExtendedVaSpace.kt
@@ -0,0 +1,58 @@
+package com.android.settings.applications
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.ext.settings.app.AppSwitch
+import android.ext.settings.app.AswUseExtendedVaSpace
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import com.android.settings.R
+import com.android.settings.core.BasePreferenceController
+import com.android.settings.ext.ExtSettingControllerHelper
+import com.android.settings.spa.app.appinfo.AswPreference
+import com.android.settingslib.widget.FooterPreference
+
+object AswAdapterUseExtendedVaSpace : AswAdapter<AswUseExtendedVaSpace>() {
+
+    override fun getAppSwitch() = AswUseExtendedVaSpace.I
+
+    override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_ext_va_space)
+
+    override fun getDetailFragmentClass() = AppExtendedVaSpaceFragment::class
+}
+
+@Composable
+fun AppExtendedVaSpacePreference(app: ApplicationInfo) {
+    val context = LocalContext.current
+    if (ExtSettingControllerHelper.getDevModeSettingAvailability(context) != BasePreferenceController.AVAILABLE) {
+        return
+    }
+
+    AswPreference(context, app, AswAdapterUseExtendedVaSpace)
+}
+
+class AppExtendedVaSpaceFragment : AswExploitProtectionFragment<AswUseExtendedVaSpace>() {
+
+    override fun getAswAdapter() = AswAdapterUseExtendedVaSpace
+
+    override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? {
+        val id = when (ir) {
+            AppSwitch.IR_REQUIRED_BY_HARDENED_MALLOC -> R.string.aep_ext_va_space_ir_hardened_malloc
+            AppSwitch.IR_NON_64_BIT_NATIVE_CODE -> R.string.aep_ext_va_space_ir_32_bit_native_code
+            else -> return null
+        }
+        return getText(id)
+    }
+
+    override fun updateFooter(fp: FooterPreference) {
+        fp.setTitle(R.string.aep_ext_va_space_footer)
+    }
+}
+
+
+class ExtendedVaSpaceAppListPrefController(context: Context, preferenceKey: String) :
+    AswAppListPrefController(context, preferenceKey, AswAdapterUseExtendedVaSpace) {
+
+    override fun getAvailabilityStatus() = ExtSettingControllerHelper
+        .getDevModeSettingAvailability(mContext)
+}
diff --git a/src/com/android/settings/applications/AppHardenedMalloc.kt b/src/com/android/settings/applications/AppHardenedMalloc.kt
new file mode 100644
index 00000000000..aac49534220
--- /dev/null
+++ b/src/com/android/settings/applications/AppHardenedMalloc.kt
@@ -0,0 +1,54 @@
+package com.android.settings.applications
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.ext.settings.app.AppSwitch
+import android.ext.settings.app.AswUseHardenedMalloc
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import com.android.settings.R
+import com.android.settings.spa.app.appinfo.AswPreference
+import com.android.settingslib.widget.FooterPreference
+
+object AswAdapterUseHardenedMalloc : AswAdapter<AswUseHardenedMalloc>() {
+
+    override fun getAppSwitch() = AswUseHardenedMalloc.I
+
+    override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_hmalloc)
+
+    override fun getDetailFragmentClass() = AppHardenedMallocFragment::class
+}
+
+@Composable
+fun AppHardenedMallocPreference(app: ApplicationInfo) {
+    val context = LocalContext.current
+    AswPreference(context, app, AswAdapterUseHardenedMalloc)
+}
+
+class AppHardenedMallocFragment : AswExploitProtectionFragment<AswUseHardenedMalloc>() {
+
+    override fun getAswAdapter() = AswAdapterUseHardenedMalloc
+
+    override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? {
+        val id = when (ir) {
+            AppSwitch.IR_IS_SYSTEM_APP -> R.string.aep_hmalloc_ir_preinstalled_app
+            AppSwitch.IR_NO_NATIVE_CODE -> R.string.aep_hmalloc_ir_no_native_code
+            AppSwitch.IR_NON_64_BIT_NATIVE_CODE -> R.string.aep_hmalloc_ir_32_bit_native_code
+            AppSwitch.IR_IS_DEBUGGABLE_APP -> R.string.aep_hmalloc_ir_debuggable_app
+            else -> return null
+        }
+        return getText(id)
+    }
+
+    override fun updateFooter(fp: FooterPreference) {
+        fp.setTitle(R.string.aep_hmalloc_footer)
+        setLearnMoreLink(fp, "https://grapheneos.org/features#exploit-mitigations")
+    }
+}
+
+
+class HardenedMallocAppListPrefController(context: Context, preferenceKey: String) :
+    AswAppListPrefController(context, preferenceKey, AswAdapterUseHardenedMalloc) {
+
+    override fun getAvailabilityStatus() = AVAILABLE
+}
diff --git a/src/com/android/settings/applications/AppMemoryDynCodeLoading.kt b/src/com/android/settings/applications/AppMemoryDynCodeLoading.kt
new file mode 100644
index 00000000000..92444f2847f
--- /dev/null
+++ b/src/com/android/settings/applications/AppMemoryDynCodeLoading.kt
@@ -0,0 +1,92 @@
+package com.android.settings.applications
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.ext.settings.ExtSettings
+import android.ext.settings.app.AppSwitch
+import android.ext.settings.app.AswRestrictMemoryDynCodeLoading
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.preference.PreferenceScreen
+import com.android.settings.R
+import com.android.settings.ext.BoolSettingFragment
+import com.android.settings.ext.BoolSettingFragmentPrefController
+import com.android.settings.ext.ExtSettingControllerHelper
+import com.android.settings.spa.app.appinfo.AswPreference
+import com.android.settingslib.widget.FooterPreference
+
+object AswAdapterMemoryDynCodeLoading : AswAdapter<AswRestrictMemoryDynCodeLoading>() {
+
+    override fun getAppSwitch() = AswRestrictMemoryDynCodeLoading.I
+
+    override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_memory_dcl)
+    override fun getShortAswTitle(ctx: Context) = ctx.getText(R.string.aep_memory_dcl_short)
+
+    override fun getOnTitle(ctx: Context) = ctx.getText(R.string.aep_restricted)
+    override fun getOffTitle(ctx: Context) = ctx.getText(R.string.aep_allowed)
+
+    override fun getNotificationToggleTitle(ctx: Context) = ctx.getText(R.string.dcl_notif_toggle_title)
+
+    override fun getDetailFragmentClass() = AppMemoryDynCodeLoadingFragment::class
+}
+
+@Composable
+fun AppMemoryDynCodeLoadingPreference(app: ApplicationInfo) {
+    val context = LocalContext.current
+    AswPreference(context, app, AswAdapterMemoryDynCodeLoading)
+}
+
+class AppMemoryDynCodeLoadingFragment : AswExploitProtectionFragment<AswRestrictMemoryDynCodeLoading>() {
+
+    override fun getAswAdapter() = AswAdapterMemoryDynCodeLoading
+
+    override fun getTitle() = getText(R.string.aep_memory_dcl_short)
+
+    override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? {
+        val id = when (ir) {
+            AppSwitch.IR_IS_SYSTEM_APP -> R.string.aep_memory_dcl_dvr_is_system_app
+            else -> return null
+        }
+        return getText(id)
+    }
+
+    override fun updateFooter(fp: FooterPreference) {
+        fp.setTitle(R.string.aep_memory_dcl_footer)
+    }
+}
+
+class AppDefaultMemoryDynCodeLoadingPrefController(ctx: Context, key: String) :
+        BoolSettingFragmentPrefController(ctx, key,
+            ExtSettings.RESTRICT_MEMORY_DYN_CODE_LOADING_BY_DEFAULT
+        ) {
+
+    override fun getSummaryOn() = resText(R.string.aep_default_summary_restricted)
+    override fun getSummaryOff() = resText(R.string.aep_default_summary_allowed_for_3p_apps)
+}
+
+class AppDefaultMemoryDynCodeLoadingFragment : BoolSettingFragment() {
+
+    override fun getSetting() = ExtSettings.RESTRICT_MEMORY_DYN_CODE_LOADING_BY_DEFAULT
+
+    override fun getTitle() = resText(R.string.aep_memory_dcl_short)
+
+    override fun getMainSwitchTitle() = resText(R.string.aep_default_main_switch_restrict_for_3p_apps)
+
+    override fun addExtraPrefs(screen: PreferenceScreen) {
+        AswAdapterMemoryDynCodeLoading.addAppListPageLink(screen)
+    }
+
+    override fun makeFooterPref(builder: FooterPreference.Builder): FooterPreference {
+        val s = getString(R.string.app_exploit_protection_default_value_warning) + "\n\n" +
+                getString(R.string.aep_memory_dcl_footer) + "\n\n" +
+                getString(R.string.aep_default_dcl_footer_ending)
+        return builder.setTitle(s).build()
+    }
+}
+
+class MemoryDynCodeLoadingAppListPrefController(context: Context, preferenceKey: String) :
+    AswAppListPrefController(context, preferenceKey, AswAdapterMemoryDynCodeLoading) {
+
+    override fun getAvailabilityStatus() = ExtSettingControllerHelper
+        .getSecondaryUserOnlySettingAvailability(mContext)
+}
diff --git a/src/com/android/settings/applications/AppMemoryTagging.kt b/src/com/android/settings/applications/AppMemoryTagging.kt
new file mode 100644
index 00000000000..20ffbe0829e
--- /dev/null
+++ b/src/com/android/settings/applications/AppMemoryTagging.kt
@@ -0,0 +1,111 @@
+package com.android.settings.applications
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.ext.settings.ExtSettings
+import android.ext.settings.app.AppSwitch
+import android.ext.settings.app.AswUseMemoryTagging
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.preference.PreferenceScreen
+import com.android.internal.os.Zygote
+import com.android.settings.R
+import com.android.settings.ext.AppPrefUtils
+import com.android.settings.ext.BoolSettingFragment
+import com.android.settings.ext.BoolSettingFragmentPrefController
+import com.android.settings.ext.ExtSettingControllerHelper
+import com.android.settings.spa.app.appinfo.AswPreference
+import com.android.settingslib.widget.FooterPreference
+
+object AswAdapterUseMemoryTagging : AswAdapter<AswUseMemoryTagging>() {
+
+    override fun getAppSwitch() = AswUseMemoryTagging.I
+
+    override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_memtag)
+
+    override fun getNotificationToggleTitle(ctx: Context) = ctx.getText(R.string.aep_memtag_notif_toggle_time)
+
+    override fun getDetailFragmentClass() = AppMemtagFragment::class
+}
+
+private val isMemoryTaggingSupported = Zygote.nativeSupportsMemoryTagging()
+
+@Composable
+fun AppMemtagPreference(app: ApplicationInfo) {
+    if (!isMemoryTaggingSupported) {
+        return
+    }
+
+    val context = LocalContext.current
+    AswPreference(context, app, AswAdapterUseMemoryTagging)
+}
+
+class AppMemtagFragment : AswExploitProtectionFragment<AswUseMemoryTagging>() {
+
+    override fun getAswAdapter() = AswAdapterUseMemoryTagging
+
+    override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? {
+        val id = when (ir) {
+            AppSwitch.IR_IS_SYSTEM_APP -> R.string.aep_memtag_dvr_is_system_app
+            AppSwitch.IR_NO_NATIVE_CODE -> R.string.aep_memtag_dvr_no_native_code
+            AppSwitch.IR_OPTED_IN_VIA_MANIFEST -> R.string.aep_memtag_dvr_manifest_opt_in
+            else -> return null
+        }
+        return getText(id)
+    }
+
+    override fun updateFooter(fp: FooterPreference) {
+        fp.setTitle(R.string.aep_memtag_footer)
+    }
+}
+
+class AppDefaultMemtagPrefController(ctx: Context, key: String) :
+    BoolSettingFragmentPrefController(ctx, key, ExtSettings.FORCE_APP_MEMTAG_BY_DEFAULT) {
+
+    private val isSupported = Zygote.nativeSupportsMemoryTagging()
+
+    override fun getAvailabilityStatus(): Int {
+        if (!isSupported) {
+            return UNSUPPORTED_ON_DEVICE
+        }
+
+        return super.getAvailabilityStatus()
+    }
+
+    override fun getSummaryOn() = resText(R.string.aep_default_memtag_summary_on)
+    override fun getSummaryOff() = resText(R.string.aep_default_memtag_summary_off)
+}
+
+class AppDefaultMemtagFragment : BoolSettingFragment() {
+
+    override fun getSetting() = ExtSettings.FORCE_APP_MEMTAG_BY_DEFAULT
+
+    override fun getTitle() = resText(R.string.aep_memtag)
+
+    override fun getMainSwitchTitle() = resText(R.string.aep_default_memtag_main_switch_title)
+    override fun getMainSwitchSummary() = resText(R.string.aep_default_memtag_main_switch_summary)
+
+    override fun addExtraPrefs(screen: PreferenceScreen) {
+        AswAdapterUseMemoryTagging.addAppListPageLink(screen)
+    }
+
+    override fun makeFooterPref(builder: FooterPreference.Builder): FooterPreference {
+        val text = AppPrefUtils.getFooterForDefaultHardeningSetting(requireContext(),
+                R.string.aep_default_memtag_footer)
+        return builder.setTitle(text).build()
+    }
+}
+
+class MemtagAppListPrefController(context: Context, preferenceKey: String) :
+    AswAppListPrefController(context, preferenceKey, AswAdapterUseMemoryTagging) {
+
+    private val isSupported = Zygote.nativeSupportsMemoryTagging()
+
+    override fun getAvailabilityStatus(): Int {
+        if (!isSupported) {
+            return UNSUPPORTED_ON_DEVICE
+        }
+        return ExtSettingControllerHelper
+            .getSecondaryUserOnlySettingAvailability(mContext)
+    }
+}
diff --git a/src/com/android/settings/applications/AppNativeDebugging.kt b/src/com/android/settings/applications/AppNativeDebugging.kt
new file mode 100644
index 00000000000..52ab5b94c62
--- /dev/null
+++ b/src/com/android/settings/applications/AppNativeDebugging.kt
@@ -0,0 +1,94 @@
+package com.android.settings.applications
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.ext.settings.BoolSetting
+import android.ext.settings.ExtSettings
+import android.ext.settings.app.AppSwitch
+import android.ext.settings.app.AswDenyNativeDebug
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.preference.PreferenceScreen
+import com.android.settings.R
+import com.android.settings.ext.AppPrefUtils
+import com.android.settings.ext.BoolSettingFragment
+import com.android.settings.ext.BoolSettingFragmentPrefController
+import com.android.settings.ext.ExtSettingControllerHelper
+import com.android.settings.spa.app.appinfo.AswPreference
+import com.android.settingslib.widget.FooterPreference
+
+object AswAdapterNativeDebugging : AswAdapter<AswDenyNativeDebug>() {
+
+    override fun getAppSwitch() = AswDenyNativeDebug.I
+
+    override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_native_debug_title)
+
+    override fun getOnTitle(ctx: Context) = ctx.getText(R.string.aep_blocked)
+    override fun getOffTitle(ctx: Context) = ctx.getText(R.string.aep_allowed)
+
+    override fun getNotificationToggleTitle(ctx: Context) = ctx.getText(R.string.aep_native_debug_notif_toggle_title)
+
+    override fun getDetailFragmentClass() = AppNativeDebuggingFragment::class
+}
+
+@Composable
+fun AppNativeDebuggingPreference(app: ApplicationInfo) {
+    val context = LocalContext.current
+    AswPreference(context, app, AswAdapterNativeDebugging)
+}
+
+class AppNativeDebuggingFragment : AswExploitProtectionFragment<AswDenyNativeDebug>() {
+
+    override fun getAswAdapter() = AswAdapterNativeDebugging
+
+    override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? {
+        val id = when (ir) {
+            AppSwitch.IR_IS_SYSTEM_APP -> R.string.aep_native_debug_dvr_is_system_app
+            else -> return null
+        }
+        return getText(id)
+    }
+
+    override fun updateFooter(fp: FooterPreference) {
+        fp.setTitle(R.string.aep_native_debug_footer)
+    }
+}
+
+class AppDefaultNativeDebuggingPrefController(ctx: Context, key: String) :
+    BoolSettingFragmentPrefController(ctx, key, ExtSettings.ALLOW_NATIVE_DEBUG_BY_DEFAULT) {
+
+    override fun getSummary(): CharSequence {
+        return resText(if (setting.get(mContext)) R.string.aep_default_summary_allowed_for_3p_apps else R.string.aep_default_summary_blocked)
+    }
+}
+
+class AppDefaultNativeDebuggingFragment : BoolSettingFragment() {
+
+    override fun getSetting(): BoolSetting {
+        invertSetting = true
+        return ExtSettings.ALLOW_NATIVE_DEBUG_BY_DEFAULT
+    }
+
+    override fun getTitle() = getText(R.string.aep_native_debug_title)
+
+    override fun getMainSwitchTitle() = getText(R.string.aep_default_main_switch_block_for_3p_apps)
+
+    override fun addExtraPrefs(screen: PreferenceScreen) {
+        AswAdapterNativeDebugging.addAppListPageLink(screen)
+    }
+
+    override fun makeFooterPref(builder: FooterPreference.Builder): FooterPreference {
+        val text = AppPrefUtils.getFooterForDefaultHardeningSetting(
+            requireContext(),
+            R.string.aep_native_debug_footer
+        )
+        return builder.setTitle(text).build()
+    }
+}
+
+class NativeDebuggingAppListPrefController(context: Context, preferenceKey: String) :
+    AswAppListPrefController(context, preferenceKey, AswAdapterNativeDebugging) {
+
+    override fun getAvailabilityStatus() = ExtSettingControllerHelper
+        .getSecondaryUserOnlySettingAvailability(mContext)
+}
diff --git a/src/com/android/settings/applications/AppStorageDynCodeLoading.kt b/src/com/android/settings/applications/AppStorageDynCodeLoading.kt
new file mode 100644
index 00000000000..5e9076bb051
--- /dev/null
+++ b/src/com/android/settings/applications/AppStorageDynCodeLoading.kt
@@ -0,0 +1,98 @@
+package com.android.settings.applications
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.ext.settings.ExtSettings
+import android.ext.settings.app.AppSwitch
+import android.ext.settings.app.AswRestrictStorageDynCodeLoading
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.preference.PreferenceScreen
+import com.android.settings.R
+import com.android.settings.ext.BoolSettingFragment
+import com.android.settings.ext.BoolSettingFragmentPrefController
+import com.android.settings.ext.ExtSettingControllerHelper
+import com.android.settings.spa.app.appinfo.AswPreference
+import com.android.settingslib.widget.FooterPreference
+
+object AswAdapterStorageDynCodeLoading : AswAdapter<AswRestrictStorageDynCodeLoading>() {
+
+    override fun getAppSwitch() = AswRestrictStorageDynCodeLoading.I
+
+    override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_storage_dcl)
+    override fun getShortAswTitle(ctx: Context) = ctx.getText(R.string.aep_storage_dcl_short)
+
+    override fun getOnTitle(ctx: Context) = ctx.getText(R.string.aep_restricted)
+    override fun getOffTitle(ctx: Context) = ctx.getText(R.string.aep_allowed)
+
+    override fun getNotificationToggleTitle(ctx: Context) = ctx.getText(R.string.dcl_notif_toggle_title)
+
+    override fun getDetailFragmentClass() = AppStorageDynCodeLoadingFragment::class
+}
+
+@Composable
+fun AppStorageDynCodeLoadingPreference(app: ApplicationInfo) {
+    val context = LocalContext.current
+    AswPreference(context, app, AswAdapterStorageDynCodeLoading)
+}
+
+class AppStorageDynCodeLoadingFragment : AswExploitProtectionFragment<AswRestrictStorageDynCodeLoading>() {
+
+    override fun getAswAdapter() = AswAdapterStorageDynCodeLoading
+
+    override fun getTitle() = getText(R.string.aep_storage_dcl_short)
+
+    override fun getSummaryForDefaultValueReason(dvr: Int): CharSequence? {
+        if (dvr == AppSwitch.DVR_DEFAULT_SETTING) {
+            return ""
+        }
+        return super.getSummaryForDefaultValueReason(dvr)
+    }
+
+    override fun getSummaryForImmutabilityReason(ir: Int): CharSequence? {
+        val id = when (ir) {
+            AppSwitch.IR_IS_SYSTEM_APP -> R.string.aep_storage_dcl_dvr_is_system_app
+            else -> return null
+        }
+        return getText(id)
+    }
+
+    override fun updateFooter(fp: FooterPreference) {
+        fp.setTitle(R.string.aep_storage_dcl_footer)
+    }
+}
+
+class AppDefaultStorageDynCodeLoadingPrefController(ctx: Context, key: String) :
+        BoolSettingFragmentPrefController(ctx, key, ExtSettings.RESTRICT_STORAGE_DYN_CODE_LOADING_BY_DEFAULT) {
+
+    override fun getSummaryOn() = resText(R.string.aep_default_summary_restricted)
+    override fun getSummaryOff() = resText(R.string.aep_default_summary_allowed_for_3p_apps)
+
+    override fun getAvailabilityStatus() = CONDITIONALLY_UNAVAILABLE
+}
+
+class AppDefaultStorageDynCodeLoadingFragment : BoolSettingFragment() {
+
+    override fun getSetting() = ExtSettings.RESTRICT_STORAGE_DYN_CODE_LOADING_BY_DEFAULT
+
+    override fun getTitle() = resText(R.string.aep_storage_dcl_short)
+
+    override fun getMainSwitchTitle() = resText(R.string.aep_default_main_switch_restrict_for_3p_apps)
+
+    override fun addExtraPrefs(screen: PreferenceScreen) {
+        AswAdapterStorageDynCodeLoading.addAppListPageLink(screen)
+    }
+
+    override fun makeFooterPref(builder: FooterPreference.Builder): FooterPreference {
+        val s = getString(R.string.app_exploit_protection_default_value_warning) + "\n\n" +
+                getString(R.string.aep_storage_dcl_footer) + "\n\n" +
+                getString(R.string.aep_default_dcl_footer_ending)
+        return builder.setTitle(s).build()
+    }
+}
+
+class StorageDynCodeLoadingAppListPrefController(context: Context, preferenceKey: String) :
+    AswAppListPrefController(context, preferenceKey, AswAdapterStorageDynCodeLoading) {
+
+    override fun getAvailabilityStatus() = AVAILABLE
+}
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 0f52053b336..a4bec5e69bb 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -207,10 +207,14 @@ void handleClearCacheClick() {
 
     @VisibleForTesting
     void handleClearDataClick() {
+        handleClearDataClick(false);
+    }
+
+    private void handleClearDataClick(boolean ignoreAppActivity) {
         if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) {
             RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
                     getActivity(), mAppsControlDisallowedAdmin);
-        } else if (mAppEntry.info.manageSpaceActivityName != null) {
+        } else if (!ignoreAppActivity && mAppEntry.info.manageSpaceActivityName != null) {
             if (!Utils.isMonkeyRunning()) {
                 Intent intent = new Intent(Intent.ACTION_DEFAULT);
                 intent.setClassName(mAppEntry.info.packageName,
@@ -296,15 +300,7 @@ private void initDataButtons() {
                 (mAppEntry.info.flags & (FLAG_SYSTEM | FLAG_ALLOW_CLEAR_USER_DATA)) == FLAG_SYSTEM;
         final boolean appRestrictsClearingData = isNonClearableSystemApp || appHasActiveAdmins;
 
-        final Intent intent = new Intent(Intent.ACTION_DEFAULT);
-        if (appHasSpaceManagementUI) {
-            intent.setClassName(mAppEntry.info.packageName, mAppEntry.info.manageSpaceActivityName);
-        }
-        final boolean isManageSpaceActivityAvailable =
-                getPackageManager().resolveActivity(intent, 0) != null;
-
-        if ((!appHasSpaceManagementUI && appRestrictsClearingData)
-                || !isManageSpaceActivityAvailable) {
+        if (appRestrictsClearingData) {
             mButtonsPref
                     .setButton1Text(R.string.clear_user_data_text)
                     .setButton1Icon(R.drawable.ic_settings_delete)
@@ -313,11 +309,25 @@ private void initDataButtons() {
         } else {
             mButtonsPref.setButton1Text(R.string.clear_user_data_text);
             mButtonsPref.setButton1Icon(R.drawable.ic_settings_delete)
-                    .setButton1OnClickListener(v -> handleClearDataClick());
+                    .setButton1OnClickListener(v -> handleClearDataClick(true));
+        }
+
+        if (appHasSpaceManagementUI) {
+            final Intent intent = new Intent(Intent.ACTION_DEFAULT);
+            intent.setClassName(mAppEntry.info.packageName, mAppEntry.info.manageSpaceActivityName);
+            final boolean isManageSpaceActivityAvailable = getPackageManager().resolveActivity(intent, 0) != null;
+
+            if (isManageSpaceActivityAvailable) {
+                ActionButtonsPreference bp = mButtonsPref;
+                bp.setButton3Text(R.string.manage_storage_text);
+                bp.setButton3Icon(R.drawable.ic_settings_open);
+                bp.setButton3OnClickListener(v -> handleClearDataClick(false));
+            }
         }
 
         if (mAppsControlDisallowedBySystem || AppUtils.isMainlineModule(mPm, mPackageName)) {
             mButtonsPref.setButton1Enabled(false);
+            mButtonsPref.setButton3Enabled(false);
         }
     }
 
@@ -574,7 +584,7 @@ void updateUiWithSize(AppStorageStats result) {
                 mButtonsPref.setButton1Enabled(false);
             } else {
                 mButtonsPref.setButton1Enabled(true)
-                        .setButton1OnClickListener(v -> handleClearDataClick());
+                        .setButton1OnClickListener(v -> handleClearDataClick(true));
             }
             if (cacheSize <= 0 || mCacheCleared) {
                 mButtonsPref.setButton2Enabled(false);
diff --git a/src/com/android/settings/applications/AppWebViewDynCodeLoading.kt b/src/com/android/settings/applications/AppWebViewDynCodeLoading.kt
new file mode 100644
index 00000000000..f1e2894b933
--- /dev/null
+++ b/src/com/android/settings/applications/AppWebViewDynCodeLoading.kt
@@ -0,0 +1,75 @@
+package com.android.settings.applications
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.ext.settings.ExtSettings
+import android.ext.settings.app.AswRestrictWebViewDynCodeLoading
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.preference.PreferenceScreen
+import com.android.settings.R
+import com.android.settings.ext.BoolSettingFragment
+import com.android.settings.ext.BoolSettingFragmentPrefController
+import com.android.settings.ext.ExtSettingControllerHelper
+import com.android.settings.spa.app.appinfo.AswPreference
+import com.android.settingslib.widget.FooterPreference
+
+object AswAdapterWebViewDynCodeLoading : AswAdapter<AswRestrictWebViewDynCodeLoading>() {
+
+    override fun getAppSwitch() = AswRestrictWebViewDynCodeLoading.I
+
+    override fun getAswTitle(ctx: Context) = ctx.getText(R.string.aep_webview_jit)
+
+    override fun getOnTitle(ctx: Context) = ctx.getText(R.string.aep_disabled)
+    override fun getOffTitle(ctx: Context) = ctx.getText(R.string.aep_enabled)
+
+    override fun getDetailFragmentClass() = AppWebViewDynCodeLoadingFragment::class
+}
+
+@Composable
+fun AppWebViewDynCodeLoadingPreference(app: ApplicationInfo) {
+    val context = LocalContext.current
+    AswPreference(context, app, AswAdapterWebViewDynCodeLoading)
+}
+
+class AppWebViewDynCodeLoadingFragment : AswExploitProtectionFragment<AswRestrictWebViewDynCodeLoading>() {
+
+    override fun getAswAdapter() = AswAdapterWebViewDynCodeLoading
+
+    override fun getTitle() = getText(R.string.aep_webview_jit)
+
+    override fun updateFooter(fp: FooterPreference) {
+        fp.setTitle(R.string.aep_webview_jit_footer)
+    }
+}
+
+class AppDefaultWebViewDynCodeLoadingPrefController(ctx: Context, key: String) :
+        BoolSettingFragmentPrefController(ctx, key, ExtSettings.RESTRICT_WEBVIEW_DYN_CODE_LOADING_BY_DEFAULT) {
+
+    override fun getSummaryOn() = resText(R.string.aep_default_summary_disabled)
+    override fun getSummaryOff() = resText(R.string.aep_default_summary_enabled_for_3p_apps)
+}
+
+class AppDefaultWebViewDynCodeLoadingFragment : BoolSettingFragment() {
+
+    override fun getSetting() = ExtSettings.RESTRICT_WEBVIEW_DYN_CODE_LOADING_BY_DEFAULT
+
+    override fun getTitle() = resText(R.string.aep_webview_jit)
+
+    override fun getMainSwitchTitle() = resText(R.string.aep_default_main_switch_disable_for_3p_apps)
+
+    override fun addExtraPrefs(screen: PreferenceScreen) {
+        AswAdapterWebViewDynCodeLoading.addAppListPageLink(screen)
+    }
+
+    override fun makeFooterPref(builder: FooterPreference.Builder): FooterPreference {
+        return builder.setTitle(R.string.aep_webview_jit_footer).build()
+    }
+}
+
+class WebViewDynCodeLoadingAppListPrefController(context: Context, preferenceKey: String) :
+    AswAppListPrefController(context, preferenceKey, AswAdapterWebViewDynCodeLoading) {
+
+    override fun getAvailabilityStatus() = ExtSettingControllerHelper
+        .getSecondaryUserOnlySettingAvailability(mContext)
+}
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
index 851d763ea94..9b8de55caf3 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
@@ -24,12 +24,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
+import android.ext.PackageId;
 import android.location.LocationManager;
 import android.os.RemoteException;
 import android.os.SystemConfigManager;
@@ -205,6 +207,39 @@ private Set<String> getEnabledPackageAllowlist() {
         if (mPm.getWellbeingPackageName() != null) {
             keepEnabledPackages.add(mPm.getWellbeingPackageName());
         }
+
+        ArraySet<String> systemPkgs = new ArraySet<>(new String[] {
+                // Bundled keyboard, needed for text input in Direct Boot mode if the selected 3rd
+                // party keyboard doesn't support it
+                "com.android.inputmethod.latin",
+
+                // Replacing WebView is not supported
+                "app.vanadium.webview",
+
+                // Only bundled camera can handle some of camera intents
+                "app.grapheneos.camera",
+
+                // Disabling GmsCompat app breaks the GmsCompat layer
+                com.android.internal.gmscompat.GmsCompatApp.PKG_NAME,
+
+                // EuiccSupportPixel handles firmware updates of embedded secure element that is
+                // used for eSIM, NFC, Felica etc
+                PackageId.EUICC_SUPPORT_PIXEL_NAME,
+
+                // CameraX extensions break when it's disabled, which breaks apps that use the
+                // CameraX library
+                PackageId.PIXEL_CAMERA_SERVICES_NAME,
+        });
+
+        PackageManager pm = mContext.getPackageManager();
+
+        for (ApplicationInfo ai : pm.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY)) {
+            String pkgName = ai.packageName;
+            if (systemPkgs.contains(pkgName)) {
+                keepEnabledPackages.add(pkgName);
+            }
+        }
+
         return keepEnabledPackages;
     }
 
diff --git a/src/com/android/settings/applications/AswAdapter.kt b/src/com/android/settings/applications/AswAdapter.kt
new file mode 100644
index 00000000000..57749a8b2f5
--- /dev/null
+++ b/src/com/android/settings/applications/AswAdapter.kt
@@ -0,0 +1,86 @@
+package com.android.settings.applications
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import android.ext.settings.app.AppSwitch
+import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
+import com.android.settings.R
+import com.android.settings.SettingsPreferenceFragment
+import com.android.settings.applications.appinfo.AppInfoDashboardFragment
+import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
+import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
+import com.android.settings.spa.app.appinfo.AswAppListPageProvider
+import com.android.settingslib.spaprivileged.model.app.userId
+import kotlin.reflect.KClass
+
+abstract class AswAdapter<T : AppSwitch> {
+    abstract fun getAppSwitch(): T
+
+    enum class Category {
+        ExploitProtection,
+    }
+
+    fun getCategory(): Category = Category.ExploitProtection
+
+    fun getPreferenceSummary(ctx: Context, appInfo: ApplicationInfo): CharSequence {
+        val asw = getAppSwitch()
+        val si = AppSwitch.StateInfo()
+        val userId = appInfo.userId
+        val isOn = asw.get(ctx, userId, appInfo, GosPackageState.get(appInfo.packageName, userId), si)
+        return if (si.isUsingDefaultValue) {
+            getDefaultTitle(ctx, isOn)
+        } else {
+            if (isOn) getOnTitle(ctx) else getOffTitle(ctx)
+        }
+    }
+
+    open fun getNotificationToggleTitle(ctx: Context): CharSequence? = null
+    open fun getNotificationToggleSummary(ctx: Context): CharSequence? = null
+
+    abstract fun getAswTitle(ctx: Context): CharSequence
+
+    open fun getShortAswTitle(ctx: Context) = getAswTitle(ctx)
+
+    fun getDefaultTitle(ctx: Context, isOn: Boolean): CharSequence {
+        return ctx.getString(R.string.aep_default,
+            if (isOn) getOnTitle(ctx) else getOffTitle(ctx)
+        )
+    }
+
+    open fun getOnTitle(ctx: Context): CharSequence = ctx.getText(R.string.aep_enabled)
+
+    open fun getOffTitle(ctx: Context): CharSequence = ctx.getText(R.string.aep_disabled)
+
+    abstract fun getDetailFragmentClass(): KClass<out SettingsPreferenceFragment>
+
+    fun openAppPage(context: Context, app: ApplicationInfo) {
+        AppInfoDashboardFragment.startAppInfoFragment(
+            getDetailFragmentClass().java,
+            app, context, AppInfoSettingsProvider.METRICS_CATEGORY,
+        )
+    }
+
+    fun makeAppListPageProvider() = AswAppListPageProvider(this)
+
+    fun getAppListPageProviderName() = this::class.simpleName!!
+
+    fun openAppListPage(ctx: Context) {
+        ctx.startSpaActivity(getAppListPageProviderName())
+    }
+
+    @JvmOverloads
+    fun addAppListPageLink(screen: PreferenceScreen,
+                           title: CharSequence = screen.context.getText(R.string.default_see_all_apps_title)) {
+        val ctx = screen.context
+        val pref = Preference(ctx).apply {
+            this.title = title
+            setOnPreferenceClickListener { p ->
+                p.context.startSpaActivity(getAppListPageProviderName())
+                true
+            }
+        }
+        screen.addPreference(pref)
+    }
+}
diff --git a/src/com/android/settings/applications/AswAppInfoFragment.java b/src/com/android/settings/applications/AswAppInfoFragment.java
new file mode 100644
index 00000000000..4d1fd861abe
--- /dev/null
+++ b/src/com/android/settings/applications/AswAppInfoFragment.java
@@ -0,0 +1,224 @@
+package com.android.settings.applications;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.GosPackageState;
+import android.ext.settings.app.AppSwitch;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+
+import com.android.settings.R;
+import com.android.settings.applications.appinfo.RadioButtonAppInfoFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class AswAppInfoFragment<T extends AppSwitch>
+        extends RadioButtonAppInfoFragment {
+
+    protected static final int ID_DEFAULT = 0;
+    protected static final int ID_ON = 1;
+    protected static final int ID_OFF = 2;
+
+    public abstract AswAdapter<T> getAswAdapter();
+
+    protected AswAdapter<T> adapter;
+    private final ArrayList<PrefModel> extraPrefs = new ArrayList<>();
+    @Nullable
+    private TogglePrefModel notifTogglePref;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        adapter = getAswAdapter();
+        super.onCreate(savedInstanceState);
+
+        if (adapter.getAppSwitch().hasNotification()) {
+            Context ctx = requireContext();
+            var p = new TogglePrefModel();
+            p.title = adapter.getNotificationToggleTitle(ctx);
+            p.summary = adapter.getNotificationToggleSummary(ctx);
+            p.onChangeListener = (pref, state) -> {
+                var ed = GosPackageState.edit(mPackageName, mUserId);
+                adapter.getAppSwitch().setNotificationEnabled(ed, (boolean) state);
+                return ed.apply();
+            };
+            extraPrefs.add(p);
+            notifTogglePref = p;
+        }
+        {
+            var p = new LinkPrefModel();
+            p.title = getText(R.string.default_see_all_apps_title);
+            p.onClick = () -> adapter.openAppListPage(requireContext());
+            extraPrefs.add(p);
+        }
+    }
+
+    @Override
+    protected CharSequence getTitle() {
+        return adapter.getAswTitle(requireContext());
+    }
+
+    @Override
+    public Entry[] getEntries() {
+        Context ctx = requireContext();
+        AppSwitch asw = adapter.getAppSwitch();
+
+        int userId = mUserId;
+        GosPackageState ps = GosPackageState.get(mPackageName, userId);
+        ApplicationInfo appInfo = getAppInfo();
+        var si = new AppSwitch.StateInfo();
+        boolean state = asw.get(ctx, userId, appInfo, ps, si);
+
+        boolean isDefault = si.isUsingDefaultValue();
+        boolean isImmutable = si.isImmutable();
+
+        var defaultSi = new AppSwitch.StateInfo();
+        boolean defaultValue = asw.getDefaultValue(ctx, userId, appInfo, ps, defaultSi);
+
+        var def = createEntry(ID_DEFAULT, adapter.getDefaultTitle(ctx, defaultValue));
+        def.isChecked = isDefault;
+        def.isEnabled = !isImmutable;
+        if (def.isEnabled) {
+            int dvr = defaultSi.getDefaultValueReason();
+            CharSequence summary = getSummaryForDefaultValueReason(dvr);
+            if (summary == null) {
+                summary = switch (dvr) {
+                    case AppSwitch.DVR_DEFAULT_SETTING -> {
+                        if (!ctx.getUser().isSystem()) {
+                            yield null;
+                        }
+                        yield getString(R.string.aep_dvr_default_security_setting,
+                                getAppDefaultSettingPathForCategory(adapter.getCategory()));
+                    }
+                    case AppSwitch.DVR_APP_COMPAT_CONFIG_HARDENING_OPT_IN ->
+                        getText(R.string.aep_dvr_compat_config_hardening_opt_in);
+                    case AppSwitch.DVR_APP_COMPAT_CONFIG_HARDENING_OPT_OUT -> {
+                        if (!ctx.getUser().isSystem()) {
+                            yield null;
+                        }
+                        var s = defaultValue ? adapter.getOnTitle(ctx) : adapter.getOffTitle(ctx);
+                        yield getString(R.string.aep_dvr_compat_config_hardening_opt_out,
+                                s.toString(), getSettingPath(R.string.safety_center_title,
+                                                  R.string.more_security_privacy_settings));
+                    }
+                    default -> null;
+                };
+            }
+            def.summary = summary;
+        }
+
+        var enabled = createEntry(ID_ON, adapter.getOnTitle(ctx));
+        enabled.isChecked = !isDefault && state;
+        enabled.isEnabled = enabled.isChecked || !isImmutable;
+
+        var disabled = createEntry(ID_OFF, adapter.getOffTitle(ctx));
+        disabled.isChecked = !isDefault && !state;
+        disabled.isEnabled = disabled.isChecked || !isImmutable;
+
+        if (isImmutable) {
+            int immutabilityReason = si.getImmutabilityReason();
+            CharSequence summary = getSummaryForImmutabilityReason(immutabilityReason);
+            if (summary == null) {
+                if (immutabilityReason == AppSwitch.IR_EXPLOIT_PROTECTION_COMPAT_MODE) {
+                    summary = getString(R.string.aep_ir_exploit_protection_compat_mode,
+                            getString(R.string.aep_compat_mode_title));
+                }
+            }
+            if (enabled.isChecked) {
+                enabled.summary = summary;
+            }
+            if (disabled.isChecked) {
+                disabled.summary = summary;
+            }
+        }
+
+        if (notifTogglePref != null) {
+            notifTogglePref.isChecked = adapter.getAppSwitch().isNotificationEnabled(ps);
+            notifTogglePref.isEnabled = state;
+        }
+
+        return new Entry[] { def, enabled, disabled };
+    }
+
+    private String getAppDefaultSettingPathForCategory(AswAdapter.Category category) {
+        switch (category) {
+            case ExploitProtection:
+                return getSettingPath(R.string.safety_center_title, R.string.exploit_protection_settings);
+            default:
+                throw new IllegalArgumentException(category.toString());
+        }
+    }
+
+    private String getSettingPath(int... parts) {
+        var sb = new StringBuilder();
+        for (int i = 0; i < parts.length; ++i) {
+            if (i != 0) {
+                sb.append(" > ");
+            }
+            sb.append(getString(parts[i]));
+        }
+        return sb.toString();
+    }
+
+    @Nullable
+    protected CharSequence getSummaryForDefaultValueReason(int dvr) {
+        return null;
+    }
+
+    @Nullable
+    protected CharSequence getSummaryForImmutabilityReason(int ir) {
+        return null;
+    }
+
+    @Override
+    protected List<PrefModel> getExtraPrefModels() {
+        return extraPrefs;
+    }
+
+    @Override
+    public final void onEntrySelected(int id) {
+        Context ctx = requireContext();
+        AppSwitch asw = adapter.getAppSwitch();
+        int userId = mUserId;
+        String pkgName = mPackageName;
+        GosPackageState ps = GosPackageState.get(pkgName, userId);
+        ApplicationInfo appInfo = getAppInfo();
+
+        boolean isImmutable = asw.isImmutable(ctx, userId, appInfo, ps);
+
+        if (isImmutable) {
+            return;
+        }
+
+        Runnable r = () -> {
+            GosPackageState.Editor ed = GosPackageState.edit(pkgName, userId);
+
+            switch (id) {
+                case ID_DEFAULT -> asw.setUseDefaultValue(ed);
+                case ID_ON, ID_OFF -> asw.set(ed, id == ID_ON);
+                default -> throw new IllegalStateException();
+            }
+
+            ed.setKillUidAfterApply(shouldKillUidAfterChange());
+
+            if (!ed.apply()) {
+                finish();
+            }
+
+            if (!refreshUi()) {
+                setIntentAndFinish(true);
+            }
+        };
+
+        completeStateChange(id, asw.get(ctx, userId, appInfo, ps), r);
+    }
+
+    protected void completeStateChange(int newEntryId, boolean curValue, Runnable stateChangeAction) {
+        stateChangeAction.run();
+    }
+
+    protected boolean shouldKillUidAfterChange() {
+        return true;
+    }
+}
diff --git a/src/com/android/settings/applications/AswAppListPrefController.java b/src/com/android/settings/applications/AswAppListPrefController.java
new file mode 100644
index 00000000000..c6d9fa7260a
--- /dev/null
+++ b/src/com/android/settings/applications/AswAppListPrefController.java
@@ -0,0 +1,27 @@
+package com.android.settings.applications;
+
+import android.content.Context;
+
+import androidx.preference.Preference;
+
+import com.android.settings.applications.AswAdapter;
+import com.android.settings.core.BasePreferenceController;
+
+public abstract class AswAppListPrefController extends BasePreferenceController {
+
+    protected final AswAdapter aswAdapter;
+
+    public AswAppListPrefController(Context context, String preferenceKey, AswAdapter adapter) {
+        super(context, preferenceKey);
+        aswAdapter = adapter;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!getPreferenceKey().equals(preference.getKey())) {
+            return false;
+        }
+        aswAdapter.openAppListPage(preference.getContext());
+        return true;
+    }
+}
diff --git a/src/com/android/settings/applications/AswExploitProtectionFragment.java b/src/com/android/settings/applications/AswExploitProtectionFragment.java
new file mode 100644
index 00000000000..19d0a470433
--- /dev/null
+++ b/src/com/android/settings/applications/AswExploitProtectionFragment.java
@@ -0,0 +1,44 @@
+package com.android.settings.applications;
+
+import android.content.Context;
+import android.content.pm.GosPackageState;
+import android.ext.settings.app.AppSwitch;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settings.R;
+
+public abstract class AswExploitProtectionFragment<T extends AppSwitch> extends AswAppInfoFragment<T> {
+
+    @Override
+    protected void completeStateChange(int newEntryId, boolean curValue, Runnable stateChangeAction) {
+        Context ctx = requireContext();
+
+        boolean showWarning = false;
+        if (curValue) {
+            if (newEntryId == ID_OFF) {
+                showWarning = true;
+            } else if (newEntryId == ID_DEFAULT) {
+                AppSwitch asw = adapter.getAppSwitch();
+                int userId = mUserId;
+                var ps = GosPackageState.get(mPackageName, userId);
+                showWarning = !asw.getDefaultValue(ctx, userId, getAppInfo(), ps);
+            }
+        }
+        if (showWarning) {
+            var d = getExploitProtectionWarningOnDisable(ctx, stateChangeAction);
+            d.show();
+        } else {
+            stateChangeAction.run();
+        }
+    }
+
+    public static AlertDialog.Builder getExploitProtectionWarningOnDisable(Context ctx, Runnable action) {
+        var b = new AlertDialog.Builder(ctx);
+        b.setTitle(R.string.aep_confirm_disable_title);
+        b.setMessage(R.string.aep_confirm_disable_warning_msg);
+        b.setNegativeButton(R.string.cancel, null);
+        b.setPositiveButton(R.string.aep_confirm_disable_proceed_btn, (d, w) -> action.run());
+        return b;
+    }
+}
diff --git a/src/com/android/settings/applications/GmsCompatAppController.java b/src/com/android/settings/applications/GmsCompatAppController.java
new file mode 100644
index 00000000000..4b978a66287
--- /dev/null
+++ b/src/com/android/settings/applications/GmsCompatAppController.java
@@ -0,0 +1,65 @@
+package com.android.settings.applications;
+
+import android.annotation.Nullable;
+import android.app.compat.gms.GmsCompat;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.preference.Preference;
+
+import com.android.internal.gmscompat.GmsCompatApp;
+import com.android.internal.gmscompat.GmsInfo;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.privatespace.PrivateSpaceMaintainer;
+
+public class GmsCompatAppController extends BasePreferenceController {
+
+    public GmsCompatAppController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Nullable
+    private UserHandle getUser() {
+        if ("sandboxed_google_play_private_space".equals(getPreferenceKey())) {
+            return PrivateSpaceMaintainer.getInstance(mContext).getPrivateProfileHandle();
+        }
+
+        UserHandle workProfileUser = getWorkProfileUser();
+        if (workProfileUser != null) {
+            return workProfileUser;
+        }
+
+        return mContext.getUser();
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        UserHandle user = getUser();
+        if (user == null) {
+            return DISABLED_FOR_USER;
+        }
+
+        return GmsCompat.isEnabledFor(GmsInfo.PACKAGE_GMS_CORE, user.getIdentifier()) ?
+                AVAILABLE : DISABLED_FOR_USER;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+            return false;
+        }
+
+        UserHandle user = getUser();
+        if (user == null) {
+            throw new IllegalStateException("getUser() returned null, key: " + getPreferenceKey());
+        }
+
+        Intent intent = new Intent(GmsCompatApp.PKG_NAME + ".SETTINGS_LINK");
+        intent.setPackage(GmsCompatApp.PKG_NAME);
+        mContext.startActivityAsUser(intent, user);
+        return true;
+    }
+}
diff --git a/src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java b/src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java
new file mode 100644
index 00000000000..26fa78beb4d
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/RadioButtonAppInfoFragment.java
@@ -0,0 +1,228 @@
+package com.android.settings.applications.appinfo;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.TypedValue;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreferenceCompat;
+
+import com.android.settings.applications.AppInfoWithHeader;
+import com.android.settings.applications.SpacePreference;
+import com.android.settingslib.widget.FooterPreference;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import java.util.Collections;
+import java.util.List;
+
+public abstract class RadioButtonAppInfoFragment extends AppInfoWithHeader implements SelectorWithWidgetPreference.OnClickListener {
+
+    public static class Entry {
+        public final int id;
+        public CharSequence title;
+        @Nullable
+        public CharSequence summary;
+        public boolean isChecked;
+        public boolean isEnabled;
+
+        public Entry(int id, CharSequence title, @Nullable CharSequence summary, boolean isChecked, boolean isEnabled) {
+            this.id = id;
+            this.title = title;
+            this.summary = summary;
+            this.isChecked = isChecked;
+            this.isEnabled = isEnabled;
+        }
+    }
+
+    public static Entry createEntry(int id, CharSequence title) {
+        return new Entry(id, title, null, false, true);
+    }
+
+    public Entry createEntry(int id, @StringRes int title) {
+        return createEntry(id, getText(title));
+    }
+
+    public Entry createEntry(@StringRes int title) {
+        return createEntry(title, title);
+    }
+
+    public abstract Entry[] getEntries();
+
+    public boolean hasFooter() {
+        return true;
+    }
+
+    public abstract void updateFooter(FooterPreference fp);
+
+    public void setLearnMoreLink(FooterPreference p, String url) {
+        p.setLearnMoreAction(v -> {
+            var i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+            startActivity(i);
+        });
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getPrefContext());
+        setPreferenceScreen(screen);
+        requireActivity().setTitle(getTitle());
+    }
+
+    protected abstract CharSequence getTitle();
+
+    @Nullable
+    private SelectorWithWidgetPreference[] radioButtons;
+    @Nullable
+    private FooterPreference footer;
+
+    private Preference[] extraPrefs;
+
+    @Override
+    protected boolean refreshUi() {
+        Entry[] entries = getEntries();
+        int entryCnt = entries.length;
+
+        Context ctx = getPrefContext();
+        PreferenceScreen screen = getPreferenceScreen();
+
+        if (radioButtons == null || radioButtons.length != entryCnt) {
+            if (radioButtons != null) {
+                for (Preference p : radioButtons) {
+                    screen.removePreference(p);
+                }
+            }
+
+            radioButtons = new SelectorWithWidgetPreference[entryCnt];
+
+            for (int i = 0; i < entryCnt; ++i) {
+                var p = new SelectorWithWidgetPreference(ctx);
+                p.setOnClickListener(this);
+                screen.addPreference(p);
+                radioButtons[i] = p;
+            }
+        }
+
+        for (int i = 0; i < entryCnt; ++i) {
+            SelectorWithWidgetPreference p = radioButtons[i];
+            Entry e = entries[i];
+            p.setKey(Integer.toString(e.id));
+            p.setTitle(e.title);
+            p.setSummary(e.summary);
+            p.setEnabled(e.isEnabled);
+            p.setChecked(e.isChecked);
+        }
+
+        List<PrefModel> extraPrefModels = getExtraPrefModels();
+
+        if (extraPrefs == null) {
+            if (extraPrefModels.isEmpty()) {
+                extraPrefs = new Preference[0];
+            } else {
+                var spacer = new SpacePreference(ctx, null);
+                int h = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 48f, ctx.getResources().getDisplayMetrics());
+                spacer.setHeight(h);
+                screen.addPreference(spacer);
+
+                extraPrefs = new Preference[extraPrefModels.size()];
+                for (int i = 0; i < extraPrefs.length; ++i) {
+                    PrefModel pm = extraPrefModels.get(i);
+                    Preference p;
+                    if (pm instanceof LinkPrefModel lpm) {
+                        p = new Preference(ctx);
+                        p.setOnPreferenceClickListener(pref -> {
+                            lpm.onClick.run();
+                            return true;
+                        });
+                    } else if (pm instanceof TogglePrefModel tpm) {
+                        p = new SwitchPreferenceCompat(ctx);
+                        p.setOnPreferenceChangeListener(tpm.onChangeListener);
+                    } else {
+                        throw new IllegalArgumentException(pm.toString());
+                    }
+                    p.setKey("extra_pref_" + i);
+                    screen.addPreference(p);
+                    extraPrefs[i] = p;
+                }
+            }
+        }
+        for (int i = 0; i < extraPrefs.length; ++i) {
+            PrefModel pm = extraPrefModels.get(i);
+            Preference p = extraPrefs[i];
+            if (pm instanceof TogglePrefModel tpm) {
+                var sp = (SwitchPreferenceCompat) p;
+                sp.setChecked(tpm.isChecked);
+            }
+            p.setTitle(pm.title);
+            p.setSummary(pm.summary);
+            p.setEnabled(pm.isEnabled);
+        }
+
+        if (hasFooter()) {
+            if (footer == null) {
+                footer = new FooterPreference(ctx);
+                screen.addPreference(footer);
+            }
+            updateFooter(footer);
+        } else {
+            if (footer != null) {
+                screen.removePreference(footer);
+                footer = null;
+            }
+        }
+
+        return true;
+    }
+
+    public static class PrefModel {
+        public CharSequence title;
+        public CharSequence summary;
+        public boolean isEnabled = true;
+    }
+
+    public static class LinkPrefModel extends PrefModel {
+        public Runnable onClick;
+    }
+
+    public static class TogglePrefModel extends PrefModel {
+        public boolean isChecked;
+        public Preference.OnPreferenceChangeListener onChangeListener;
+    }
+
+    protected List<PrefModel> getExtraPrefModels() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public final void onRadioButtonClicked(SelectorWithWidgetPreference emiter) {
+        int id = Integer.parseInt(emiter.getKey());
+        onEntrySelected(id);
+        if (!refreshUi()) {
+            setIntentAndFinish(true);
+        }
+    }
+
+    public abstract void onEntrySelected(int id);
+
+    @Override
+    protected AlertDialog createDialog(int id, int errorCode) {
+        return null;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return METRICS_CATEGORY_UNKNOWN;
+    }
+
+    protected ApplicationInfo getAppInfo() {
+        return mPackageInfo.applicationInfo;
+    }
+}
diff --git a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
index f07241a2fe4..cfe0bb67ed5 100644
--- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
+++ b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
@@ -120,6 +120,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
     private Optional<Boolean> mSimulateHiddenForTests = Optional.empty();
     private boolean mIsWorkProfile = false;
     private boolean mSimulateConnectedForTests = false;
+    private boolean mIsPrivateSpace;
 
     public CredentialManagerPreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
@@ -207,6 +208,7 @@ public void init(
         fragment.getSettingsLifecycle().addObserver(this);
         mFragmentManager = fragmentManager;
         mIsWorkProfile = isWorkProfile;
+        mIsPrivateSpace = fragment instanceof com.android.settings.accounts.AccountPrivateDashboardFragment;
 
         setDelegate(delegate);
         verifyReceivedIntent(launchIntent);
@@ -892,6 +894,15 @@ protected int getUser() {
                 return workProfile.getIdentifier();
             }
         }
+
+        if (mIsPrivateSpace) {
+            UserHandle user = com.android.settings.privatespace.PrivateSpaceMaintainer
+                    .getInstance(mContext).getPrivateProfileHandle();
+            if (user != null) {
+                return user.getIdentifier();
+            }
+        }
+
         return UserHandle.myUserId();
     }
 
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 6c16d94a51d..4fae58ace18 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -863,9 +863,11 @@ void updateOptionsMenu() {
         }
         mOptionsMenu.findItem(R.id.advanced).setVisible(false);
 
-        mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible(mListType == LIST_TYPE_STORAGE
+        mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible(
+                (mListType == LIST_TYPE_STORAGE || mListType == LIST_TYPE_MAIN)
                 && mSortOrder != R.id.sort_order_alpha);
-        mOptionsMenu.findItem(R.id.sort_order_size).setVisible(mListType == LIST_TYPE_STORAGE
+        mOptionsMenu.findItem(R.id.sort_order_size).setVisible(
+                (mListType == LIST_TYPE_STORAGE || mListType == LIST_TYPE_MAIN)
                 && mSortOrder != R.id.sort_order_size);
 
         mOptionsMenu.findItem(R.id.show_system).setVisible(!mShowSystem
diff --git a/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessFragment.java b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessFragment.java
new file mode 100644
index 00000000000..d681703f4cd
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessFragment.java
@@ -0,0 +1,46 @@
+package com.android.settings.applications.specialaccess;
+
+import android.app.ActivityThread;
+import android.ext.settings.BoolSetting;
+import android.ext.settings.ExtSettings;
+import android.os.RemoteException;
+
+import com.android.internal.util.GoogleCameraUtils;
+import com.android.settings.R;
+import com.android.settings.ext.BoolSettingFragment;
+import com.android.settingslib.widget.FooterPreference;
+
+public class GoogleSpecialAcceleratorAccessFragment extends BoolSettingFragment {
+    private static final String TAG = GoogleSpecialAcceleratorAccessFragment.class.getSimpleName();
+
+    @Override
+    protected BoolSetting getSetting() {
+        return ExtSettings.ALLOW_GOOGLE_APPS_SPECIAL_ACCESS_TO_ACCELERATORS;
+    }
+
+    @Override
+    protected CharSequence getTitle() {
+        return resText(R.string.Google_apps_special_accelerator_access_title);
+    }
+
+    @Override
+    protected CharSequence getMainSwitchTitle() {
+        return resText(R.string.Google_apps_special_accelerator_access_main_switch);
+    }
+
+    @Override
+    protected void onMainSwitchChanged(boolean state) {
+        if (GoogleCameraUtils.isCustomSeInfoNeededForAccessToAccelerators(requireContext())) {
+            try {
+                ActivityThread.getPackageManager().updateSeInfo(GoogleCameraUtils.PACKAGE_NAME);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    @Override
+    protected FooterPreference makeFooterPref(FooterPreference.Builder builder) {
+        return builder.setTitle(R.string.Google_apps_special_accelerator_access_footer).build();
+    }
+}
diff --git a/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessPrefController.java b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessPrefController.java
new file mode 100644
index 00000000000..ac7d84fcbb0
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/GoogleSpecialAcceleratorAccessPrefController.java
@@ -0,0 +1,34 @@
+package com.android.settings.applications.specialaccess;
+
+import android.content.Context;
+import android.ext.settings.ExtSettings;
+
+import com.android.settings.R;
+import com.android.settings.ext.BoolSettingFragmentPrefController;
+
+public class GoogleSpecialAcceleratorAccessPrefController extends BoolSettingFragmentPrefController {
+
+    public GoogleSpecialAcceleratorAccessPrefController(Context ctx, String key) {
+        super(ctx, key, ExtSettings.ALLOW_GOOGLE_APPS_SPECIAL_ACCESS_TO_ACCELERATORS);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (!mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_Google_apps_can_have_special_access_to_accelerators)) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
+
+        return super.getAvailabilityStatus();
+    }
+
+    @Override
+    protected CharSequence getSummaryOn() {
+        return resText(R.string.Google_apps_special_accelerator_access_summary_granted);
+    }
+
+    @Override
+    protected CharSequence getSummaryOff() {
+        return resText(R.string.Google_apps_special_accelerator_access_summary_not_granted);
+    }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index d3f75195305..648cb18a241 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -365,34 +365,34 @@ protected boolean generateChallengeOnCreate() {
 
     @StringRes
     protected int getInfoMessageGlasses() {
-        return R.string.security_settings_face_enroll_introduction_info_glasses;
+        return R.string.security_settings_face_enroll_introduction_info_glasses_en;
     }
 
     @StringRes
     protected int getInfoMessageLooking() {
         return isPrivateProfile()
                 ? R.string.private_space_face_enroll_introduction_info_looking
-                : R.string.security_settings_face_enroll_introduction_info_looking;
+                : R.string.security_settings_face_enroll_introduction_info_looking_en;
     }
 
     @StringRes
     protected int getInfoMessageRequireEyes() {
-        return R.string.security_settings_face_enroll_introduction_info_gaze;
+        return R.string.security_settings_face_enroll_introduction_info_gaze_en;
     }
 
     @StringRes
     protected int getHowMessage() {
-        return R.string.security_settings_face_enroll_introduction_how_message;
+        return R.string.security_settings_face_enroll_introduction_how_message_en;
     }
 
     @StringRes
     protected int getInControlTitle() {
-        return R.string.security_settings_face_enroll_introduction_control_title;
+        return R.string.security_settings_face_enroll_introduction_control_title_en;
     }
 
     @StringRes
     protected int getInControlMessage() {
-        return R.string.security_settings_face_enroll_introduction_control_message;
+        return R.string.security_settings_face_enroll_introduction_control_message_en;
     }
 
     @StringRes
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index adb6700de9b..ea46fccf53d 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -196,12 +196,11 @@ private static List<AbstractPreferenceController> createThePreferenceControllers
             if (manager == null || !manager.isHardwareDetected()) {
                 return null;
             }
+
+            controllers.add(new FingerprintUnlockCategoryController(context,
+                    KEY_FINGERPRINT_UNLOCK_CATEGORY));
+
             if (manager.isPowerbuttonFps()) {
-                controllers.add(
-                        new FingerprintUnlockCategoryController(
-                                context,
-                                KEY_FINGERPRINT_UNLOCK_CATEGORY
-                        ));
                 controllers.add(
                         new FingerprintSettingsRequireScreenOnToAuthPreferenceController(
                                 context,
@@ -210,6 +209,8 @@ private static List<AbstractPreferenceController> createThePreferenceControllers
             }
             controllers.add(new FingerprintsEnrolledCategoryPreferenceController(context,
                     KEY_FINGERPRINTS_ENROLLED_CATEGORY));
+            controllers.add(new FingerprintSettingsKeyguardPreferenceController(context,
+                    KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE));
             return controllers;
         }
 
@@ -615,16 +616,17 @@ private void addFingerprintPreferences(PreferenceGroup root) {
                     ((FingerprintSettingsPreferenceController) controller).setUserId(mUserId);
                 } else if (controller instanceof FingerprintUnlockCategoryController) {
                     ((FingerprintUnlockCategoryController) controller).setUserId(mUserId);
+                } else if (controller instanceof FingerprintSettingsKeyguardPreferenceController c) {
+                    c.setUserId(mUserId);
                 }
             }
 
             // This needs to be after setting ids, otherwise
             // |mRequireScreenOnToAuthPreferenceController.isChecked| is always checking the primary
             // user instead of the user with |mUserId|.
-            if (isSfps()) {
-                scrollToPreference(fpPrefKey);
-                addFingerprintUnlockCategory();
-            }
+            scrollToPreference(fpPrefKey);
+            addFingerprintUnlockCategory();
+
             createFooterPreference(root);
         }
 
@@ -697,16 +699,30 @@ private void updateFingerprintUnlockCategoryVisibility() {
             }
         }
 
+        private FingerprintSettingsKeyguardPreferenceController mFingerprintKeyguardController;
+
         private void setupFingerprintUnlockCategoryPreferences() {
             mRequireScreenOnToAuthPreference = findPreference(KEY_REQUIRE_SCREEN_ON_TO_AUTH);
-            mRequireScreenOnToAuthPreference.setChecked(
-                    mRequireScreenOnToAuthPreferenceController.isChecked());
-            mRequireScreenOnToAuthPreference.setOnPreferenceChangeListener(
-                    (preference, newValue) -> {
-                        final boolean isChecked = ((TwoStatePreference) preference).isChecked();
-                        mRequireScreenOnToAuthPreferenceController.setChecked(!isChecked);
-                        return true;
-                    });
+            if (mRequireScreenOnToAuthPreferenceController != null) {
+                mRequireScreenOnToAuthPreference.setVisible(mRequireScreenOnToAuthPreferenceController.isAvailable());
+                mRequireScreenOnToAuthPreference.setChecked(
+                        mRequireScreenOnToAuthPreferenceController.isChecked());
+                mRequireScreenOnToAuthPreference.setOnPreferenceChangeListener(
+                        (preference, newValue) -> {
+                            final boolean isChecked = ((TwoStatePreference) preference).isChecked();
+                            mRequireScreenOnToAuthPreferenceController.setChecked(!isChecked);
+                            return true;
+                        });
+            } else {
+                mRequireScreenOnToAuthPreference.setVisible(false);
+            }
+
+            RestrictedSwitchPreference keyguardFingerprintPref = findPreference(KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE);
+            keyguardFingerprintPref.setChecked(mFingerprintKeyguardController.isChecked());
+            keyguardFingerprintPref.setOnPreferenceChangeListener((p, value) -> {
+                mFingerprintKeyguardController.setChecked((boolean) value);
+                return true;
+            });
         }
 
         private void updatePreferencesAfterFingerprintRemoved() {
@@ -943,19 +959,20 @@ protected List<AbstractPreferenceController> createPreferenceControllers(Context
         private List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
             final List<AbstractPreferenceController> controllers =
                     createThePreferenceControllers(context);
-            if (isSfps()) {
-                for (AbstractPreferenceController controller : controllers) {
-                    if (controller.getPreferenceKey() == KEY_FINGERPRINT_UNLOCK_CATEGORY) {
-                        mFingerprintUnlockCategoryPreferenceController =
-                                (FingerprintUnlockCategoryController) controller;
-                    } else if (controller.getPreferenceKey() == KEY_REQUIRE_SCREEN_ON_TO_AUTH) {
-                        mRequireScreenOnToAuthPreferenceController =
-                                (FingerprintSettingsRequireScreenOnToAuthPreferenceController)
-                                        controller;
-                    }
 
+            for (AbstractPreferenceController controller : controllers) {
+                if (controller.getPreferenceKey() == KEY_FINGERPRINT_UNLOCK_CATEGORY) {
+                    mFingerprintUnlockCategoryPreferenceController =
+                        (FingerprintUnlockCategoryController) controller;
+                } else if (controller.getPreferenceKey() == KEY_REQUIRE_SCREEN_ON_TO_AUTH) {
+                    mRequireScreenOnToAuthPreferenceController =
+                        (FingerprintSettingsRequireScreenOnToAuthPreferenceController) controller;
+                } else if (controller.getPreferenceKey() == KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE) {
+                    mFingerprintKeyguardController =
+                        (FingerprintSettingsKeyguardPreferenceController) controller;
                 }
             }
+
             return controllers;
         }
 
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardPreferenceController.java
new file mode 100644
index 00000000000..87b10aa23ba
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsKeyguardPreferenceController.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.biometrics.fingerprint;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import com.android.settings.Utils;
+import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+
+import static android.provider.Settings.Secure.BIOMETRIC_KEYGUARD_ENABLED;
+
+// based on src/com/android/settings/biometrics/combination/BiometricSettingsKeyguardPreferenceController.java
+// from android-14.0.0_r1
+public class FingerprintSettingsKeyguardPreferenceController extends TogglePreferenceController {
+    private static final int ON = 1;
+    private static final int OFF = 0;
+    private static final int DEFAULT = ON;
+
+    private int mUserId;
+
+    public FingerprintSettingsKeyguardPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    protected RestrictedLockUtils.EnforcedAdmin getRestrictingAdmin() {
+        return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(mContext,
+                DevicePolicyManager.KEYGUARD_DISABLE_BIOMETRICS, mUserId);
+    }
+
+    public void setUserId(int userId) {
+        mUserId = userId;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                BIOMETRIC_KEYGUARD_ENABLED, DEFAULT, mUserId) == ON;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        return Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                BIOMETRIC_KEYGUARD_ENABLED, isChecked ? ON : OFF, mUserId);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (UserManager.get(mContext).isManagedProfile(mUserId)) {
+            return DISABLED_FOR_USER;
+        }
+
+        return getAvailabilityFromRestrictingAdmin();
+    }
+
+    private int getAvailabilityFromRestrictingAdmin() {
+        return getRestrictingAdmin() != null ? DISABLED_FOR_USER : AVAILABLE;
+    }
+
+    @Override
+    public final boolean isSliceable() {
+        return false;
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        // not needed since it's not sliceable
+        return NO_RES;
+    }
+}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintUnlockCategoryController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintUnlockCategoryController.java
index 674a0dfa758..acca88fc0af 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintUnlockCategoryController.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintUnlockCategoryController.java
@@ -41,8 +41,7 @@ public FingerprintUnlockCategoryController(Context context, String key) {
     @Override
     public int getAvailabilityStatus() {
         if (mFingerprintManager != null
-                && mFingerprintManager.isHardwareDetected()
-                && mFingerprintManager.isPowerbuttonFps()) {
+                && mFingerprintManager.isHardwareDetected()) {
             return mFingerprintManager.hasEnrolledTemplates(getUserId())
                     ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
         } else {
diff --git a/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java b/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java
index bf97478feef..a70144d47e7 100644
--- a/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java
+++ b/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java
@@ -25,21 +25,34 @@
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
+import android.app.AlertDialog;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.hardware.biometrics.BiometricFingerprintConstants;
 import android.hardware.fingerprint.FingerprintManager;
+import android.os.Build;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
 import android.view.View;
 import android.view.animation.AccelerateInterpolator;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.core.util.Preconditions;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling;
+import com.google.hardware.biometrics.sidefps.IFingerprintExt;
 
 import java.util.function.Function;
+import java.util.function.Supplier;
 
 public class SfpsEnrollmentFeatureImpl implements SfpsEnrollmentFeature {
+    static final String TAG = SfpsEnrollmentFeatureImpl.class.getSimpleName();
+
     @VisibleForTesting
     public static final int HELP_ANIMATOR_DURATION = 550;
 
@@ -89,8 +102,31 @@ public int getSfpsEnrollLottiePerStage(int stage) {
         };
     }
 
+    private final boolean isGoogleDevice = "google".equals(Build.BRAND);
+    private float[] mEnrollStageThresholds;
+
     @Override
     public float getEnrollStageThreshold(@NonNull Context context, int index) {
+        if (isGoogleDevice) {
+            Log.d(TAG, "getEnrollStageThreshold " + index);
+            if (mEnrollStageThresholds == null) {
+                // TODO: extract these values automatically from SettingsGoogle resource:
+                //  com.google.android.settings.R.array.config_sfps_enroll_stage_thresholds
+                mEnrollStageThresholds = new float[] {
+                        0f, 0.04f, 0.48f, 0.52f
+                };
+            }
+
+            // this logic was copied from FingerprintManager.getEnrollStageThreshold()
+
+            if (index < 0 || index > mEnrollStageThresholds.length) {
+                Log.w(TAG, "Unsupported enroll stage index: " + index);
+                return index < 0 ? 0f : 1f;
+            }
+
+            return index == mEnrollStageThresholds.length ? 1f : mEnrollStageThresholds[index];
+        }
+
         if (mFingerprintManager == null) {
             mFingerprintManager = context.getSystemService(FingerprintManager.class);
         }
@@ -113,4 +149,93 @@ public Animator getHelpAnimator(@NonNull View target) {
     public boolean shouldAdjustHeaderText(@NonNull Configuration conf, boolean isFolded) {
         return conf.orientation == Configuration.ORIENTATION_LANDSCAPE;
     }
+
+    @Override
+    public void handleOnEnrollmentHelp(int helpMsgId, CharSequence helpString, Supplier<FingerprintEnrollEnrolling> enrollingSupplier) {
+        if (isGoogleDevice) {
+            Log.d(TAG, "handleOnEnrollmentHelp, helpMsgId: " + helpMsgId + ", helpString: " + helpString, new Throwable());
+            if (helpMsgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR_BASE ||
+                    helpMsgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_IMMOBILE) {
+                Context ctx = enrollingSupplier.get();
+                Log.d(TAG, "getVendorString: " + getVendorString(ctx, 0));
+
+                if (getGoogleFingerprintExt() == null) {
+                    return;
+                }
+
+                if (mHelpDialog != null) {
+                    mHelpDialog.dismiss();
+                    mHelpDialog = null;
+                }
+
+                var d = new AlertDialog.Builder(ctx);
+                d.setMessage(getVendorString(ctx, VENDOR_STRING_FINGERPRINT_ACQUIRED_IMMOBILE));
+                d.setPositiveButton(android.R.string.ok, (dialog, which) -> {
+                    resumeEnroll();
+                });
+                mHelpDialog = d.show();
+            }
+        }
+    }
+
+    private AlertDialog mHelpDialog;
+
+    @Override
+    public CharSequence getFeaturedVendorString(Context context, int id, CharSequence msg) {
+        if (!isGoogleDevice) {
+            return msg;
+        }
+
+        Log.d(TAG, "getFeaturedVendorString, id: " + id + ", msg: " + msg, new Throwable());
+
+        if (id == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR_BASE ||
+                id == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_IMMOBILE) {
+            return getVendorString(context, VENDOR_STRING_FINGERPRINT_ACQUIRED_IMMOBILE);
+        }
+
+       return msg;
+    }
+
+    private static final int VENDOR_STRING_FINGERPRINT_ACQUIRED_IMMOBILE = 0;
+
+    private static String getVendorString(Context ctx, int index) {
+        String[] strings = ctx.getResources().getStringArray(R.array.fingerprint_acquired_vendor);
+        Preconditions.checkArgumentInRange(index, 0, strings.length - 1, "vendor string index");
+        return strings[index];
+    }
+
+    @Nullable
+    private static IFingerprintExt getGoogleFingerprintExt() {
+        String fpServiceName = android.hardware.biometrics.fingerprint.IFingerprint.class.getName() + "/default";
+        IBinder fpService = ServiceManager.getService(fpServiceName);
+        if (fpService == null) {
+            throw new IllegalStateException(fpServiceName + " is null");
+        }
+
+        IBinder fpServiceExt;
+        try {
+            fpServiceExt = fpService.getExtension();
+        } catch (RemoteException e) {
+            throw new IllegalStateException(e);
+        }
+
+        if (fpServiceExt == null) {
+            Log.e(TAG, "no IFingerprintExt");
+            return null;
+        }
+
+        return IFingerprintExt.Stub.asInterface(fpServiceExt);
+    }
+
+    private static void resumeEnroll() {
+        IFingerprintExt fpExt = getGoogleFingerprintExt();
+        if (fpExt == null) {
+            return;
+        }
+        try {
+            fpExt.resumeEnroll();
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
+    }
 }
diff --git a/src/com/android/settings/bluetooth/BluetoothAutoOffPrefController.java b/src/com/android/settings/bluetooth/BluetoothAutoOffPrefController.java
new file mode 100644
index 00000000000..14791951802
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothAutoOffPrefController.java
@@ -0,0 +1,39 @@
+package com.android.settings.bluetooth;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.ext.settings.ExtSettings;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.ext.AutoOffSetting;
+import com.android.settings.ext.IntSettingPrefController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+public class BluetoothAutoOffPrefController extends IntSettingPrefController {
+
+    public BluetoothAutoOffPrefController(Context ctx, String key) {
+        super(ctx, key, ExtSettings.BLUETOOTH_AUTO_OFF);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        int r = super.getAvailabilityStatus();
+        if (r == AVAILABLE) {
+            return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH) ?
+                    AVAILABLE : UNSUPPORTED_ON_DEVICE;
+        }
+        return r;
+    }
+
+    @Override
+    public void addPrefsBeforeList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+        addFooterPreference(screen, R.string.bluetooth_auto_off_footer);
+    }
+
+    @Override
+    protected void getEntries(Entries entries) {
+        AutoOffSetting.getEntries(entries);
+    }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingController.java b/src/com/android/settings/bluetooth/BluetoothPairingController.java
index f141bccd594..e54837b1313 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingController.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingController.java
@@ -117,11 +117,8 @@ public BluetoothPairingController(Intent intent, Context context) {
 
     @Override
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-        if (isChecked) {
-            mPbapAllowed = true;
-        } else {
-            mPbapAllowed = false;
-        }
+        mPbapAllowed = isChecked;
+        Log.d(TAG, "phonebook access permission toggle isChecked: " + isChecked);
     }
 
     @Override
@@ -227,37 +224,18 @@ public boolean isContactSharingVisible() {
      * contacts
      */
     public boolean getContactSharingState() {
-        switch (mDevice.getPhonebookAccessPermission()) {
+        int permission = mDevice.getPhonebookAccessPermission();
+        switch (permission) {
             case BluetoothDevice.ACCESS_ALLOWED:
                 return true;
             case BluetoothDevice.ACCESS_REJECTED:
+            case BluetoothDevice.ACCESS_UNKNOWN:
                 return false;
             default:
-                if (BluetoothUtils.isDeviceClassMatched(
-                        mDevice, BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE)) {
-                    return BluetoothDevice.EXTRA_PAIRING_INITIATOR_FOREGROUND == mInitiator;
-                }
-                return false;
+                throw new IllegalStateException("getPhonebookAccessPermission returned " + permission);
         }
     }
 
-    /**
-     * Update Phone book permission
-     *
-     */
-     public void setContactSharingState() {
-         final int permission = mDevice.getPhonebookAccessPermission();
-         if (permission == BluetoothDevice.ACCESS_ALLOWED
-                 || (permission == BluetoothDevice.ACCESS_UNKNOWN
-                 && BluetoothUtils.isDeviceClassMatched(mDevice,
-                 BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE))) {
-             onCheckedChanged(null, true);
-         } else {
-             onCheckedChanged(null, false);
-         }
-
-     }
-
     /**
      * A method for querying if the provided editable is a valid passkey/pin format for this device.
      *
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
index e6b197c4d81..3db85d74a17 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
@@ -260,7 +260,7 @@ private View createPinEntryView() {
 
         contactSharing.setVisibility(
                 mPairingController.isContactSharingVisible() ? View.VISIBLE : View.GONE);
-        mPairingController.setContactSharingState();
+        // OnCheckedChangeListener has to be registered before the initial setChecked()
         contactSharing.setOnCheckedChangeListener(mPairingController);
         contactSharing.setChecked(mPairingController.getContactSharingState());
 
@@ -350,9 +350,9 @@ private View createView() {
                 view.findViewById(R.id.phonebook_sharing_message_confirm_pin);
         view.findViewById(R.id.phonebook_sharing).setVisibility(
                 mPairingController.isContactSharingVisible() ? View.VISIBLE : View.GONE);
-        mPairingController.setContactSharingState();
-        contactSharing.setChecked(mPairingController.getContactSharingState());
+        // OnCheckedChangeListener has to be registered before the initial setChecked()
         contactSharing.setOnCheckedChangeListener(mPairingController);
+        contactSharing.setChecked(mPairingController.getContactSharingState());
 
         messagePairing.setVisibility(mPairingController.isDisplayPairingKeyVariant()
                 ? View.VISIBLE : View.GONE);
diff --git a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java
index 2855f0ab16a..2f7dd6ff789 100644
--- a/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java
+++ b/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceController.java
@@ -34,7 +34,6 @@ public class AdvancedConnectedDeviceController extends BasePreferenceController
 
     private static final String DRIVING_MODE_SETTINGS_ENABLED =
             "gearhead:driving_mode_settings_enabled";
-    private static final String GEARHEAD_PACKAGE = "com.google.android.projection.gearhead";
 
     public AdvancedConnectedDeviceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
@@ -59,7 +58,7 @@ public static int getConnectedDevicesSummaryResourceId(Context context) {
                 new NfcPreferenceController(context, NfcPreferenceController.KEY_TOGGLE_NFC);
 
         return getConnectedDevicesSummaryResourceId(nfcPreferenceController,
-                isDrivingModeAvailable(context), isAndroidAutoSettingAvailable(context));
+                isDrivingModeAvailable(context), false);
     }
 
     @VisibleForTesting
@@ -68,13 +67,6 @@ static boolean isDrivingModeAvailable(Context context) {
                 getInt(context.getContentResolver(), DRIVING_MODE_SETTINGS_ENABLED, 0) == 1;
     }
 
-    @VisibleForTesting
-    static boolean isAndroidAutoSettingAvailable(Context context) {
-        final Intent intent = new Intent(IA_SETTINGS_ACTION);
-        intent.setPackage(GEARHEAD_PACKAGE);
-        return intent.resolveActivity(context.getPackageManager()) != null;
-    }
-
     @VisibleForTesting
     static int getConnectedDevicesSummaryResourceId(NfcPreferenceController
             nfcPreferenceController,
diff --git a/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentController.java b/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentController.java
index ee0021ec951..f16dd378db5 100644
--- a/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentController.java
+++ b/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentController.java
@@ -16,21 +16,47 @@
 
 package com.android.settings.connecteddevice;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.nfc.NfcAdapter;
 import android.os.UserManager;
 
+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.OnResume;
+import com.android.settingslib.core.lifecycle.events.OnStop;
 
 /**
  * Controller that used to show NFC and payment features
  */
-public class NfcAndPaymentFragmentController extends BasePreferenceController {
+public class NfcAndPaymentFragmentController extends BasePreferenceController
+        implements LifecycleObserver, OnResume, OnStop {
     private final NfcAdapter mNfcAdapter;
     private final PackageManager mPackageManager;
     private final UserManager mUserManager;
+    private final IntentFilter mIntentFilter;
+    private Preference mPreference;
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (mPreference == null) {
+                return;
+            }
+
+            final String action = intent.getAction();
+            if (NfcAdapter.ACTION_ADAPTER_STATE_CHANGED.equals(action)) {
+                refreshSummary(mPreference);
+            }
+        }
+    };
 
     public NfcAndPaymentFragmentController(Context context, String preferenceKey) {
         super(context, preferenceKey);
@@ -38,6 +64,15 @@ public NfcAndPaymentFragmentController(Context context, String preferenceKey) {
         mPackageManager = context.getPackageManager();
         mUserManager = context.getSystemService(UserManager.class);
         mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
+
+        mIntentFilter = isNfcAvailable()
+                ? new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED) : null;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
     }
 
     @Override
@@ -61,4 +96,26 @@ public CharSequence getSummary() {
         }
         return null;
     }
+
+    @Override
+    public void onStop() {
+        if (!isNfcAvailable()) {
+            return;
+        }
+
+        mContext.unregisterReceiver(mReceiver);
+    }
+
+    @Override
+    public void onResume() {
+        if (!isNfcAvailable()) {
+            return;
+        }
+
+        mContext.registerReceiver(mReceiver, mIntentFilter);
+    }
+
+    private boolean isNfcAvailable() {
+        return mNfcAdapter != null;
+    }
 }
diff --git a/src/com/android/settings/core/PreferenceControllerListHelper.java b/src/com/android/settings/core/PreferenceControllerListHelper.java
index dea8c971c49..30d41d88c3e 100644
--- a/src/com/android/settings/core/PreferenceControllerListHelper.java
+++ b/src/com/android/settings/core/PreferenceControllerListHelper.java
@@ -31,6 +31,7 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag;
+import com.android.settings.ext.BoolSettingPrefController;
 import com.android.settingslib.core.AbstractPreferenceController;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -59,6 +60,7 @@ public static List<BasePreferenceController> getPreferenceControllersFromXml(Con
         try {
             preferenceMetadata = PreferenceXmlParserUtils.extractMetadata(context, xmlResId,
                     MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_PREF_CONTROLLER
+                            | MetadataFlag.FLAG_NEED_BOOL_SETTING_FIELD
                             | MetadataFlag.FLAG_INCLUDE_PREF_SCREEN  | MetadataFlag.FLAG_FOR_WORK);
         } catch (IOException | XmlPullParserException e) {
             Log.e(TAG, "Failed to parse preference xml for getting controllers", e);
@@ -68,13 +70,16 @@ public static List<BasePreferenceController> getPreferenceControllersFromXml(Con
         for (Bundle metadata : preferenceMetadata) {
             final String controllerName = metadata.getString(METADATA_CONTROLLER);
             if (TextUtils.isEmpty(controllerName)) {
+                BoolSettingPrefController.maybeAdd(context, metadata, controllers);
                 continue;
             }
             BasePreferenceController controller;
             try {
                 controller = BasePreferenceController.createInstance(context, controllerName);
             } catch (IllegalStateException e) {
-                Log.d(TAG, "Could not find Context-only controller for pref: " + controllerName);
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Could not find Context-only controller for pref: " + controllerName);
+                }
                 final String key = metadata.getString(METADATA_KEY);
                 final boolean isWorkProfile = metadata.getBoolean(METADATA_FOR_WORK, false);
                 if (TextUtils.isEmpty(key)) {
diff --git a/src/com/android/settings/core/PreferenceXmlParserUtils.java b/src/com/android/settings/core/PreferenceXmlParserUtils.java
index df3cd922752..478a79e74e6 100644
--- a/src/com/android/settings/core/PreferenceXmlParserUtils.java
+++ b/src/com/android/settings/core/PreferenceXmlParserUtils.java
@@ -64,6 +64,7 @@ public class PreferenceXmlParserUtils {
             MetadataFlag.FLAG_NEED_KEY,
             MetadataFlag.FLAG_NEED_PREF_TYPE,
             MetadataFlag.FLAG_NEED_PREF_CONTROLLER,
+            MetadataFlag.FLAG_NEED_BOOL_SETTING_FIELD,
             MetadataFlag.FLAG_NEED_PREF_TITLE,
             MetadataFlag.FLAG_NEED_PREF_SUMMARY,
             MetadataFlag.FLAG_NEED_PREF_ICON,
@@ -91,11 +92,14 @@ public class PreferenceXmlParserUtils {
         int FLAG_FOR_WORK = 1 << 12;
         int FLAG_NEED_HIGHLIGHTABLE_MENU_KEY = 1 << 13;
         int FLAG_NEED_USER_RESTRICTION = 1 << 14;
+
+        int FLAG_NEED_BOOL_SETTING_FIELD = 1 << 30;
     }
 
     public static final String METADATA_PREF_TYPE = "type";
     public static final String METADATA_KEY = "key";
     public static final String METADATA_CONTROLLER = "controller";
+    public static final String METADATA_BOOL_SETTING_FIELD = "bool_setting_field";
     public static final String METADATA_TITLE = "title";
     public static final String METADATA_SUMMARY = "summary";
     public static final String METADATA_ICON = "icon";
@@ -162,6 +166,10 @@ public static List<Bundle> extractMetadata(Context context, @XmlRes int xmlResId
                 preferenceMetadata.putString(METADATA_CONTROLLER,
                         getController(preferenceAttributes));
             }
+            if (hasFlag(flags, MetadataFlag.FLAG_NEED_BOOL_SETTING_FIELD)) {
+                preferenceMetadata.putString(METADATA_BOOL_SETTING_FIELD,
+                        getBoolSettingField(preferenceAttributes));
+            }
             if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TITLE)) {
                 preferenceMetadata.putString(METADATA_TITLE, getTitle(preferenceAttributes));
             }
@@ -230,6 +238,10 @@ private static String getController(TypedArray styledAttributes) {
         return styledAttributes.getString(R.styleable.Preference_controller);
     }
 
+    private static String getBoolSettingField(TypedArray styledAttributes) {
+        return styledAttributes.getString(R.styleable.Preference_boolSettingField);
+    }
+
     private static String getHighlightableMenuKey(TypedArray styledAttributes) {
         return styledAttributes.getString(R.styleable.Preference_highlightableMenuKey);
     }
@@ -269,4 +281,4 @@ private static String getUserRestriction(Context context, AttributeSet attrs) {
         preferenceAttributes.recycle();
         return userRestriction;
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 734bddcbb2a..dac5c46fa47 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -214,6 +214,12 @@ public class SettingsGateway {
      * security exception if the fragment it needs to display is not in this list.
      */
     public static final String[] ENTRY_FRAGMENTS = {
+            com.android.settings.applications.AppNativeDebuggingFragment.class.getName(),
+            com.android.settings.applications.AppMemtagFragment.class.getName(),
+            com.android.settings.applications.AppHardenedMallocFragment.class.getName(),
+            com.android.settings.applications.AppMemoryDynCodeLoadingFragment.class.getName(),
+            com.android.settings.applications.AppStorageDynCodeLoadingFragment.class.getName(),
+            com.android.settings.safetycenter.ExploitProtectionFragment.class.getName(),
             AdvancedConnectedDeviceDashboardFragment.class.getName(),
             CreateShortcut.class.getName(),
             BluetoothPairingDetail.class.getName(),
diff --git a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
index 849a80b3592..02e42d4c6a2 100644
--- a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
+++ b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
@@ -43,6 +43,7 @@
 import com.android.settings.notification.SoundSettings;
 import com.android.settings.notification.zen.ZenModeSettings;
 import com.android.settings.privacy.PrivacyDashboardFragment;
+import com.android.settings.safetycenter.ExploitProtectionFragment;
 import com.android.settings.safetycenter.MoreSecurityPrivacyFragment;
 import com.android.settings.security.LockscreenDashboardFragment;
 import com.android.settings.security.SecurityAdvancedSettings;
@@ -71,6 +72,8 @@ public class DashboardFragmentRegistry {
 
     static {
         PARENT_TO_CATEGORY_KEY_MAP = new ArrayMap<>();
+        PARENT_TO_CATEGORY_KEY_MAP.put(ExploitProtectionFragment.class.getName(),
+                CategoryKey.CATEGORY_EXPLOIT_PROTECTION_SETTINGS);
         PARENT_TO_CATEGORY_KEY_MAP.put(TopLevelSettings.class.getName(),
                 CategoryKey.CATEGORY_HOMEPAGE);
         PARENT_TO_CATEGORY_KEY_MAP.put(
diff --git a/src/com/android/settings/development/DSULoader.java b/src/com/android/settings/development/DSULoader.java
index fede67a7766..957e3d79e6f 100644
--- a/src/com/android/settings/development/DSULoader.java
+++ b/src/com/android/settings/development/DSULoader.java
@@ -305,7 +305,7 @@ Date getDeviceSPL() {
         }
 
         boolean isSupported() {
-            boolean supported = true;
+            boolean supported = false;
             String cpu = getDeviceCpu();
             if (!mCpuAbi.equals(cpu)) {
                 Slog.i(TAG, mCpuAbi + " != " + cpu);
diff --git a/src/com/android/settings/deviceinfo/firmwareversion/BootloaderVersionPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/BootloaderVersionPreferenceController.java
new file mode 100644
index 00000000000..32b1cb64de0
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/firmwareversion/BootloaderVersionPreferenceController.java
@@ -0,0 +1,28 @@
+package com.android.settings.deviceinfo.firmwareversion;
+
+import android.content.Context;
+import android.os.SystemProperties;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.core.BasePreferenceController;
+
+public class BootloaderVersionPreferenceController extends BasePreferenceController {
+
+    static final String BOOTLOADER_PROPERTY = "ro.bootloader";
+
+    public BootloaderVersionPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        return SystemProperties.get(BOOTLOADER_PROPERTY,
+                mContext.getString(R.string.device_info_default));
+    }
+}
diff --git a/src/com/android/settings/deviceinfo/hardwareinfo/HardwareSkuPreferenceController.java b/src/com/android/settings/deviceinfo/hardwareinfo/HardwareSkuPreferenceController.java
new file mode 100644
index 00000000000..4be09710e8c
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/hardwareinfo/HardwareSkuPreferenceController.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.hardwareinfo;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.text.TextUtils;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.slices.Sliceable;
+
+public class HardwareSkuPreferenceController extends BasePreferenceController {
+
+    public HardwareSkuPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mContext.getResources().getBoolean(R.bool.config_show_device_model) &&
+                !TextUtils.isEmpty(getSummary()) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public boolean useDynamicSliceSummary() {
+        return true;
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        return SystemProperties.get("ro.boot.hardware.sku");
+    }
+}
diff --git a/src/com/android/settings/display/AltTouchscreenModePrefController.java b/src/com/android/settings/display/AltTouchscreenModePrefController.java
new file mode 100644
index 00000000000..70a27cbe814
--- /dev/null
+++ b/src/com/android/settings/display/AltTouchscreenModePrefController.java
@@ -0,0 +1,52 @@
+package com.android.settings.display;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.ext.settings.AltTouchscreenMode;
+import android.os.Handler;
+import android.os.PowerManager;
+
+import com.android.settings.ext.BoolSettingPrefController;
+import com.android.settings.R;
+
+public class AltTouchscreenModePrefController extends BoolSettingPrefController {
+
+    public AltTouchscreenModePrefController(Context ctx, String key) {
+        super(ctx, key, AltTouchscreenMode.getSetting());
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (!AltTouchscreenMode.isAvailable(mContext)) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
+
+        return super.getAvailabilityStatus();
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        super.setChecked(isChecked);
+        if (!isChecked) {
+            return true;
+        }
+
+        Handler handler = mContext.getMainThreadHandler();
+        Runnable undo = () -> {
+            super.setChecked(false);
+            mContext.getSystemService(PowerManager.class).reboot(null);
+        };
+        // disable the alt mode after a delay unless the user confirms that the touchscreen is
+        // still working
+        handler.postDelayed(undo, 10_000);
+
+        var b = new AlertDialog.Builder(mContext);
+        b.setMessage(R.string.alt_touchscreen_mode_confirm_message);
+        b.setPositiveButton(R.string.alt_touchscreen_mode_confirm_button, (d, btn) -> {
+            handler.removeCallbacks(undo);
+        });
+        b.show();
+
+        return true;
+    }
+}
diff --git a/src/com/android/settings/display/BatterySharePreferenceController.java b/src/com/android/settings/display/BatterySharePreferenceController.java
new file mode 100644
index 00000000000..39b9066cdb9
--- /dev/null
+++ b/src/com/android/settings/display/BatterySharePreferenceController.java
@@ -0,0 +1,99 @@
+package com.android.settings.display;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
+import com.android.internal.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+import vendor.google.wireless_charger.ReverseWirelessCharger;
+
+public class BatterySharePreferenceController extends BasePreferenceController implements
+        PreferenceControllerMixin, Preference.OnPreferenceChangeListener, LifecycleObserver,
+        OnStart, OnStop {
+
+    private static final String KEY_BATTERY_SHARE = "battery_share";
+    private final ReverseWirelessCharger wirelessCharger;
+    private final Context mContext;
+    private Preference mPreference;
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            ((Activity) mContext).runOnUiThread(() -> update());
+        }
+    };
+
+
+    public BatterySharePreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+        mContext = context;
+        wirelessCharger = ReverseWirelessCharger.getInstance();
+    }
+
+    public boolean isPlugged(Context context) {
+        Intent intent = context.registerReceiver(null,
+                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+        int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
+        return plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+        update();
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_BATTERY_SHARE;
+    }
+
+    private void update() {
+        if (mPreference == null) return;
+        boolean enabled = !isPlugged(mContext) && wirelessCharger.isRtxSupported();
+        mPreference.setEnabled(enabled);
+        ((TwoStatePreference) mPreference).setChecked(wirelessCharger.isRtxModeOn());
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return wirelessCharger.isRtxSupported() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        update();
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        wirelessCharger.setRtxMode((Boolean) newValue);
+        return true;
+    }
+
+    @Override
+    public void onStart() {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+        mContext.registerReceiver(mBroadcastReceiver, filter);
+    }
+
+    @Override
+    public void onStop() {
+        mContext.unregisterReceiver(mBroadcastReceiver);
+    }
+}
diff --git a/src/com/android/settings/display/ScreenResolutionFragment.java b/src/com/android/settings/display/ScreenResolutionFragment.java
index a2ad25ff96d..b2971a7d1e6 100644
--- a/src/com/android/settings/display/ScreenResolutionFragment.java
+++ b/src/com/android/settings/display/ScreenResolutionFragment.java
@@ -101,9 +101,6 @@ protected int getPreferenceScreenResId() {
 
     @Override
     protected void addStaticPreferences(PreferenceScreen screen) {
-        updateIllustrationImage(mImagePreference);
-        screen.addPreference(mImagePreference);
-
         final FooterPreference footerPreference = new FooterPreference(screen.getContext());
         footerPreference.setTitle(R.string.screen_resolution_footer);
         footerPreference.setSelectable(false);
@@ -223,7 +220,6 @@ protected boolean setDefaultKey(final String key) {
         }
 
         setDisplayMode(width);
-        updateIllustrationImage(mImagePreference);
 
         return true;
     }
diff --git a/src/com/android/settings/display/TouchSensitivityPreferenceController.java b/src/com/android/settings/display/TouchSensitivityPreferenceController.java
new file mode 100755
index 00000000000..a6f90f593f0
--- /dev/null
+++ b/src/com/android/settings/display/TouchSensitivityPreferenceController.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Proton AOSP Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.display;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.provider.Settings;
+
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.R;
+
+public class TouchSensitivityPreferenceController extends TogglePreferenceController {
+
+    // Settings can only set the debug.* property, so we need to persist it
+    // in system settings. Match the stock setting name for backup compatibility.
+    private static final String SETTINGS_KEY = "touch_sensitivity_enabled";
+    private static final String PROP_NAME = "debug.touch_sensitivity_mode";
+
+    public TouchSensitivityPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mContext.getResources().getBoolean(com.android.internal.R.bool.config_supportGloveMode)
+            ? AVAILABLE
+            : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public boolean setChecked(boolean value) {
+        Settings.Secure.putInt(mContext.getContentResolver(), SETTINGS_KEY, value ? 1 : 0);
+        SystemProperties.set(PROP_NAME, value ? "1" : "0");
+        return true;
+    }
+
+    @Override
+    public boolean isChecked() {
+        // debug prop isn't persistent
+        return Settings.Secure.getInt(mContext.getContentResolver(), SETTINGS_KEY, 0) == 1;
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        return R.string.menu_key_display;
+    }
+}
diff --git a/src/com/android/settings/ext/AbstractListPreferenceController.java b/src/com/android/settings/ext/AbstractListPreferenceController.java
new file mode 100644
index 00000000000..a5686e370ee
--- /dev/null
+++ b/src/com/android/settings/ext/AbstractListPreferenceController.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2022 GrapheneOS
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.android.settings.ext;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.util.SparseIntArray;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.utils.CandidateInfoExtra;
+import com.android.settingslib.widget.CandidateInfo;
+import com.android.settingslib.widget.FooterPreference;
+
+import java.util.ArrayList;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+public abstract class AbstractListPreferenceController extends BasePreferenceController
+    implements DefaultLifecycleObserver {
+
+    private Preference preference;
+    private Entries entries;
+
+    @Nullable
+    public RadioButtonPickerFragment2 fragment;
+
+    protected AbstractListPreferenceController(Context ctx, String key) {
+        super(ctx, key);
+    }
+
+    // call entries.add(entryName, entryValue) to add entries.
+    // entryValues can be mapped from other values or sets of values, as long as getCurrentValue()
+    // and setValue() methods are consistent
+    protected abstract void getEntries(Entries entries);
+
+    public void getEntriesAsCandidates(ArrayList<CandidateInfo> dst) {
+        Entries e = new Entries(mContext);
+        getEntries(e);
+
+        dst.addAll(e.list);
+    }
+
+    protected abstract int getCurrentValue();
+    protected abstract boolean setValue(int val);
+
+    @Override
+    public void updateState(Preference p) {
+        if (entries == null) {
+            entries = new Entries(mContext);
+            getEntries(entries);
+        }
+
+        if (p != preference) {
+            p.setSingleLineTitle(false);
+            p.setPersistent(false);
+            this.preference = p;
+        }
+
+        updatePreference();
+    }
+
+    void updatePreference() {
+        if (fragment != null) {
+            fragment.updateCandidates();
+        }
+
+        Preference p = preference;
+        if (p == null) {
+            return;
+        }
+
+        int idx = entries.getIndexForValue(getCurrentValue());
+        if (idx >= 0) {
+            p.setSummary(entries.list.get(idx).loadLabel());
+        } else {
+            p.setSummary(null);
+        }
+    }
+
+    public static class Entries {
+        private final Context context;
+        private final ArrayList<CandidateInfoExtra> list = new ArrayList<>();
+        private final SparseIntArray valueToIndexMap = new SparseIntArray();
+
+        Entries(Context context) {
+            this.context = context;
+        }
+
+        public void add(@StringRes int title, int value) {
+            add(context.getText(title), value);
+        }
+
+        public void add(@StringRes int title, @StringRes int summary, int value) {
+            add(context.getText(title), context.getText(summary), value);
+        }
+
+        public void add(int duration, TimeUnit timeUnit) {
+            long durationMillis = timeUnit.toMillis(duration);
+            if (durationMillis > Integer.MAX_VALUE) {
+                throw new IllegalArgumentException();
+            }
+
+            add(DateUtils.formatDuration(durationMillis), (int) durationMillis);
+        }
+
+        public void add(CharSequence title, int value) {
+            add(title, null, value, true);
+        }
+
+        public void add(CharSequence title, CharSequence summary, int value) {
+            add(title, summary, value, true);
+        }
+
+        public void add(CharSequence title, @Nullable CharSequence summary, int value, boolean enabled) {
+            String prefKey = Integer.toString(value);
+            list.add(new CandidateInfoExtra(title, summary, prefKey, enabled));
+            valueToIndexMap.put(value, list.size() - 1);
+        }
+
+        public int getIndexForValue(int val) {
+            return valueToIndexMap.get(val, -1);
+        }
+    }
+
+    @Override
+    public boolean isSliceable() {
+        return false;
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        return NO_RES;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+            return super.handlePreferenceTreeClick(preference);
+        }
+
+        if (this.preference instanceof ListPreference) {
+            return super.handlePreferenceTreeClick(preference);
+        }
+
+        UserHandle workProfileUser = getWorkProfileUser();
+        boolean isForWork = workProfileUser != null;
+
+        RadioButtonPickerFragment2.fillArgs(preference, this, isForWork);
+
+        new SubSettingLauncher(preference.getContext())
+                .setDestination(RadioButtonPickerFragment2.class.getName())
+                .setSourceMetricsCategory(preference.getExtras().getInt(DashboardFragment.CATEGORY,
+                                                                        SettingsEnums.PAGE_UNKNOWN))
+                .setTitleText(preference.getTitle())
+                .setArguments(preference.getExtras())
+                .setUserHandle(workProfileUser)
+                .launch();
+        return true;
+    }
+
+    public void addPrefsBeforeList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+
+    }
+
+    public void addPrefsAfterList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+
+    }
+
+    public FooterPreference addFooterPreference(PreferenceScreen screen, @StringRes int text) {
+        Context ctx = screen.getContext();
+        return addFooterPreference(screen, ctx.getText(text), null, null);
+    }
+
+    public FooterPreference addFooterPreference(PreferenceScreen screen,
+                                                @StringRes int text, String learnMoreUrl) {
+        return addFooterPreference(screen, text, R.string.learn_more, learnMoreUrl);
+    }
+
+    public FooterPreference addFooterPreference(
+            PreferenceScreen screen, @StringRes int text,
+            @StringRes int learnMoreText, String learnMoreUrl) {
+        Context ctx = screen.getContext();
+        Runnable learnMoreAction = () -> {
+            var intent = new Intent(Intent.ACTION_VIEW, Uri.parse(learnMoreUrl));
+            ctx.startActivity(intent);
+        };
+        return addFooterPreference(screen, ctx.getText(text),
+                ctx.getText(learnMoreText), learnMoreAction);
+    }
+
+    public FooterPreference addFooterPreference(
+            PreferenceScreen screen, @StringRes int text,
+            @StringRes int learnMoreText, Runnable learnMoreAction) {
+        Context ctx = screen.getContext();
+        return addFooterPreference(screen, ctx.getText(text), ctx.getText(learnMoreText), learnMoreAction);
+    }
+
+    public FooterPreference addFooterPreference(PreferenceScreen screen, CharSequence text,
+                                                @Nullable CharSequence learnMoreText,
+                                                @Nullable Runnable learnMoreAction) {
+        var p = new FooterPreference(screen.getContext());
+        p.setSelectable(false);
+        p.setSummary(text);
+        if (learnMoreText != null) {
+            p.setLearnMoreText(learnMoreText);
+            Objects.requireNonNull(learnMoreAction);
+            p.setLearnMoreAction(v -> learnMoreAction.run());
+        }
+        p.setOrder(Preference.DEFAULT_ORDER);
+        screen.addPreference(p);
+        return p;
+    }
+
+    protected final CharSequence getText(@StringRes int resId) {
+        return mContext.getText(resId);
+    }
+
+    /**
+     * Returns whether to require user credential confirmation before changing this preference.
+     */
+    protected boolean isCredentialConfirmationRequired() {
+        return false;
+    }
+}
diff --git a/src/com/android/settings/ext/AbstractTogglePrefController.java b/src/com/android/settings/ext/AbstractTogglePrefController.java
new file mode 100644
index 00000000000..ceee6984bfd
--- /dev/null
+++ b/src/com/android/settings/ext/AbstractTogglePrefController.java
@@ -0,0 +1,38 @@
+package com.android.settings.ext;
+
+import android.content.Context;
+
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+
+import com.android.settings.core.TogglePreferenceController;
+
+public abstract class AbstractTogglePrefController extends TogglePreferenceController {
+
+    protected AbstractTogglePrefController(Context ctx, String key) {
+        super(ctx, key);
+    }
+
+    @Nullable protected Preference preference;
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+
+        if (preference != this.preference) {
+            preference.setSingleLineTitle(false);
+            preference.setPersistent(false);
+            this.preference = preference;
+        }
+    }
+
+    @Override
+    public boolean isSliceable() {
+        return false;
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        return NO_RES;
+    }
+}
diff --git a/src/com/android/settings/ext/AppPrefUtils.java b/src/com/android/settings/ext/AppPrefUtils.java
new file mode 100644
index 00000000000..3ae426bf36f
--- /dev/null
+++ b/src/com/android/settings/ext/AppPrefUtils.java
@@ -0,0 +1,14 @@
+package com.android.settings.ext;
+
+import android.content.Context;
+
+import com.android.settings.R;
+
+import androidx.annotation.StringRes;
+
+public class AppPrefUtils {
+
+    public static String getFooterForDefaultHardeningSetting(Context ctx, @StringRes int baseText) {
+        return ctx.getString(R.string.app_exploit_protection_default_value_warning) + "\n\n" + ctx.getString(baseText);
+    }
+}
diff --git a/src/com/android/settings/ext/AutoOffSetting.java b/src/com/android/settings/ext/AutoOffSetting.java
new file mode 100644
index 00000000000..98be94b8589
--- /dev/null
+++ b/src/com/android/settings/ext/AutoOffSetting.java
@@ -0,0 +1,25 @@
+package com.android.settings.ext;
+
+import com.android.settings.R;
+
+import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+public class AutoOffSetting {
+
+    public static void getEntries(AbstractListPreferenceController.Entries entries) {
+        entries.add(R.string.auto_off_never, 0);
+        entries.add(15, SECONDS);
+        entries.add(30, SECONDS);
+        entries.add(1,  MINUTES);
+        entries.add(2,  MINUTES);
+        entries.add(5,  MINUTES);
+        entries.add(10, MINUTES);
+        entries.add(30, MINUTES);
+        entries.add(1,  HOURS);
+        entries.add(2,  HOURS);
+        entries.add(4,  HOURS);
+        entries.add(8,  HOURS);
+    }
+}
diff --git a/src/com/android/settings/ext/BoolSettingFragment.java b/src/com/android/settings/ext/BoolSettingFragment.java
new file mode 100644
index 00000000000..e342faa688d
--- /dev/null
+++ b/src/com/android/settings/ext/BoolSettingFragment.java
@@ -0,0 +1,157 @@
+package com.android.settings.ext;
+
+import android.content.Context;
+import android.content.Intent;
+import android.ext.settings.BoolSetting;
+import android.net.Uri;
+import android.os.Bundle;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreferenceCompat;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.widget.FooterPreference;
+
+public abstract class BoolSettingFragment extends DashboardFragment implements ExtSettingPrefController<BoolSetting> {
+
+    private static final String TAG = BoolSettingFragment.class.getSimpleName();
+
+    protected SwitchPreferenceCompat mainSwitch;
+    protected boolean invertSetting;
+
+    private ExtSettingControllerHelper<BoolSetting> helper;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        helper = new ExtSettingControllerHelper<>(requireContext(), getSetting());
+
+        getActivity().setTitle(getTitle());
+
+        Context ctx = requireContext();
+
+        PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(ctx);
+
+        var mainSwitch = new SwitchPreferenceCompat(ctx);
+        mainSwitch.setTitle(getMainSwitchTitle());
+
+        this.mainSwitch = mainSwitch;
+        refreshMainSwitch();
+
+        mainSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
+            boolean state = (boolean) newValue;
+
+            if (invertSetting) {
+                state = !state;
+            }
+
+            if (interceptMainSwitchChange(state)) {
+                return false;
+            }
+
+            if (!getSetting().put(requireContext(), state)) {
+                return false;
+            }
+
+            onMainSwitchChanged(state);
+
+            return true;
+        });
+
+        screen.addPreference(mainSwitch);
+
+        addExtraPrefs(screen);
+
+        FooterPreference footer = makeFooterPref(new FooterPreference.Builder(ctx));
+
+        if (footer != null) {
+            screen.addPreference(footer);
+        }
+
+        setPreferenceScreen(screen);
+    }
+
+    protected abstract BoolSetting getSetting();
+
+    protected abstract CharSequence getTitle();
+
+    protected CharSequence getMainSwitchTitle() {
+        return getText(R.string.bool_setting_enable);
+    }
+
+    protected CharSequence getMainSwitchSummary() {
+        return null;
+    }
+
+    protected void addExtraPrefs(PreferenceScreen screen) {}
+
+    protected FooterPreference makeFooterPref(FooterPreference.Builder builder) {
+        return null;
+    }
+
+    protected static void setFooterPrefLearnMoreUri(FooterPreference p, Uri uri) {
+        p.setLearnMoreAction(v -> {
+            var intent = new Intent(Intent.ACTION_VIEW, uri);
+            p.getContext().startActivity(intent);
+        });
+    }
+
+    protected boolean interceptMainSwitchChange(boolean newValue) {
+        return false;
+    }
+
+    protected void onMainSwitchChanged(boolean state) {}
+
+    protected void refreshMainSwitch() {
+        boolean state = getSetting().get(requireContext());
+        if (invertSetting) {
+            state = !state;
+        }
+        mainSwitch.setChecked(state);
+
+        CharSequence mainSwitchSummary = getMainSwitchSummary();
+        if (mainSwitchSummary != null) {
+            mainSwitch.setSummary(mainSwitchSummary);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        helper.onResume(this);
+        refreshMainSwitch();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        helper.onPause(this);
+    }
+
+    @Override
+    public void accept(BoolSetting setting) {
+        refreshMainSwitch();
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return METRICS_CATEGORY_UNKNOWN;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return 0;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    protected final CharSequence resText(int res) {
+        return requireContext().getText(res);
+    }
+}
diff --git a/src/com/android/settings/ext/BoolSettingFragmentPrefController.java b/src/com/android/settings/ext/BoolSettingFragmentPrefController.java
new file mode 100644
index 00000000000..3f9223b800a
--- /dev/null
+++ b/src/com/android/settings/ext/BoolSettingFragmentPrefController.java
@@ -0,0 +1,26 @@
+package com.android.settings.ext;
+
+import android.content.Context;
+import android.ext.settings.BoolSetting;
+
+import com.android.settings.R;
+
+public abstract class BoolSettingFragmentPrefController extends ExtSettingFragmentPrefController<BoolSetting> {
+
+    protected BoolSettingFragmentPrefController(Context ctx, String key, BoolSetting setting) {
+        super(ctx, key, setting);
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        return setting.get(mContext) ? getSummaryOn() : getSummaryOff();
+    }
+
+    protected CharSequence getSummaryOn() {
+        return resText(R.string.bool_setting_enabled);
+    }
+
+    protected CharSequence getSummaryOff() {
+        return resText(R.string.bool_setting_disabled);
+    }
+}
diff --git a/src/com/android/settings/ext/BoolSettingPrefController.java b/src/com/android/settings/ext/BoolSettingPrefController.java
new file mode 100644
index 00000000000..00d69fdfd2c
--- /dev/null
+++ b/src/com/android/settings/ext/BoolSettingPrefController.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 GrapheneOS
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.android.settings.ext;
+
+import android.content.Context;
+import android.ext.settings.BoolSetting;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+
+import com.android.settings.core.BasePreferenceController;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Objects;
+
+import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_BOOL_SETTING_FIELD;
+import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
+
+public class BoolSettingPrefController extends AbstractTogglePrefController
+        implements ExtSettingPrefController<BoolSetting> {
+    private final BoolSetting setting;
+    private final ExtSettingControllerHelper<BoolSetting> helper;
+
+    protected BoolSettingPrefController(Context ctx, String key, BoolSetting setting) {
+        super(ctx, key);
+        helper = new ExtSettingControllerHelper(ctx, setting);
+        this.setting = setting;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return helper.getAvailabilityStatus();
+    }
+
+    @Override
+    public final boolean isChecked() {
+        return setting.get(mContext);
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        return setting.put(mContext, isChecked);
+    }
+
+    @Override
+    public void onResume(@NonNull LifecycleOwner owner) {
+        helper.onResume(this);
+    }
+
+    @Override
+    public void onPause(@NonNull LifecycleOwner owner) {
+        helper.onPause(this);
+    }
+
+    // called by the setting observer
+    @Override
+    public void accept(BoolSetting boolSetting) {
+        if (preference != null) {
+            updateState(preference);
+        }
+    }
+
+    // called when PreferenceScreen XML is parsed
+    public static void maybeAdd(Context context, Bundle metadata,
+                                List<BasePreferenceController> dest) {
+        String boolSettingField = metadata.getString(METADATA_BOOL_SETTING_FIELD);
+        if (boolSettingField == null) {
+            return;
+        }
+        String[] split = boolSettingField.split(" ");
+
+        BoolSetting boolSetting;
+        try {
+            Class c = Class.forName(split[0]);
+            Field field = c.getField(split[1]);
+            boolSetting = (BoolSetting) Objects.requireNonNull(field.get(null));
+        } catch (Exception e) {
+            throw new IllegalStateException("Invalid BoolSetting field " + boolSettingField);
+        }
+
+        String key = Objects.requireNonNull(metadata.getString(METADATA_KEY));
+
+        dest.add(new BoolSettingPrefController(context, key, boolSetting));
+    }
+}
diff --git a/src/com/android/settings/ext/ExtSettingControllerHelper.java b/src/com/android/settings/ext/ExtSettingControllerHelper.java
new file mode 100644
index 00000000000..250ccb6e29e
--- /dev/null
+++ b/src/com/android/settings/ext/ExtSettingControllerHelper.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 GrapheneOS
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.android.settings.ext;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.ext.settings.Setting;
+import android.provider.Settings;
+
+import java.util.function.Consumer;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
+
+public class ExtSettingControllerHelper<T extends Setting> {
+    private final Context context;
+    private final T setting;
+
+    ExtSettingControllerHelper(Context context, T setting) {
+        this.context = context;
+        this.setting = setting;
+    }
+
+    public static int getGlobalSettingAvailability(Context ctx) {
+        return ctx.getUser().isSystem() ? AVAILABLE : DISABLED_FOR_USER;
+    }
+
+    public static int getSecondaryUserOnlySettingAvailability(Context ctx) {
+        return ctx.getUser().isSystem() ? DISABLED_FOR_USER : AVAILABLE;
+    }
+
+    public static int getDevModeSettingAvailability(Context ctx) {
+        ContentResolver cr = ctx.getContentResolver();
+        String key = Settings.Global.DEVELOPMENT_SETTINGS_ENABLED;
+
+        return (Settings.Global.getInt(cr, key, 0) == 0) ?
+            CONDITIONALLY_UNAVAILABLE : AVAILABLE;
+    }
+
+    int getAvailabilityStatus() {
+        if (setting.getScope() != Setting.Scope.PER_USER) {
+            return getGlobalSettingAvailability(context);
+        }
+        return AVAILABLE;
+    }
+
+    private Object observer;
+
+    void onResume(ExtSettingPrefController espc) {
+        registerObserver(espc);
+    }
+
+    void onPause(ExtSettingPrefController espc) {
+        unregisterObserver();
+    }
+
+    void registerObserver(Consumer<T> settingObserver) {
+        if (setting.canObserveState()) {
+            observer = setting.registerObserver(context, context.getMainThreadHandler(), settingObserver);
+        }
+    }
+
+    void unregisterObserver() {
+        if (setting.canObserveState()) {
+            setting.unregisterObserver(context, observer);
+        }
+    }
+}
diff --git a/src/com/android/settings/ext/ExtSettingFragmentPrefController.java b/src/com/android/settings/ext/ExtSettingFragmentPrefController.java
new file mode 100644
index 00000000000..2d87635e0d2
--- /dev/null
+++ b/src/com/android/settings/ext/ExtSettingFragmentPrefController.java
@@ -0,0 +1,42 @@
+package com.android.settings.ext;
+
+import android.content.Context;
+import android.ext.settings.Setting;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+
+public abstract class ExtSettingFragmentPrefController<T extends Setting> extends FragmentPrefController
+        implements ExtSettingPrefController<T> {
+    protected final T setting;
+    protected final ExtSettingControllerHelper<T> helper;
+
+    protected ExtSettingFragmentPrefController(Context ctx, String key, T setting) {
+        super(ctx, key);
+        this.setting = setting;
+        helper = new ExtSettingControllerHelper<T>(ctx, setting);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return helper.getAvailabilityStatus();
+    }
+
+    @Override
+    public void onResume(@NonNull LifecycleOwner owner) {
+        helper.onResume(this);
+    }
+
+    @Override
+    public void onPause(@NonNull LifecycleOwner owner) {
+        helper.onPause(this);
+    }
+
+    // called by the setting observer
+    @Override
+    public void accept(T setting) {
+        if (preference != null) {
+            updateState(preference);
+        }
+    }
+}
diff --git a/src/com/android/settings/ext/ExtSettingPrefController.java b/src/com/android/settings/ext/ExtSettingPrefController.java
new file mode 100644
index 00000000000..f641e344b50
--- /dev/null
+++ b/src/com/android/settings/ext/ExtSettingPrefController.java
@@ -0,0 +1,12 @@
+package com.android.settings.ext;
+
+import android.ext.settings.Setting;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+
+import java.util.function.Consumer;
+
+interface ExtSettingPrefController<T extends Setting> extends DefaultLifecycleObserver, Consumer<T> {
+}
diff --git a/src/com/android/settings/ext/FragmentPrefController.java b/src/com/android/settings/ext/FragmentPrefController.java
new file mode 100644
index 00000000000..b09ab9615c2
--- /dev/null
+++ b/src/com/android/settings/ext/FragmentPrefController.java
@@ -0,0 +1,36 @@
+package com.android.settings.ext;
+
+import android.content.Context;
+
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+
+import com.android.settings.core.BasePreferenceController;
+
+public abstract class FragmentPrefController<FragmentType extends PreferenceFragmentCompat>
+        extends BasePreferenceController {
+
+    protected FragmentPrefController(Context ctx, String key) {
+        super(ctx, key);
+    }
+
+    @Nullable
+    protected Preference preference;
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+
+        if (preference != this.preference) {
+            preference.setSingleLineTitle(false);
+            preference.setPersistent(false);
+
+            this.preference = preference;
+        }
+    }
+
+    protected final CharSequence resText(int res) {
+        return mContext.getText(res);
+    }
+}
diff --git a/src/com/android/settings/ext/IntSettingPrefController.java b/src/com/android/settings/ext/IntSettingPrefController.java
new file mode 100644
index 00000000000..1660f54bf0b
--- /dev/null
+++ b/src/com/android/settings/ext/IntSettingPrefController.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 GrapheneOS
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.android.settings.ext;
+
+import android.content.Context;
+import android.ext.settings.IntSetting;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+
+public abstract class IntSettingPrefController extends AbstractListPreferenceController
+        implements ExtSettingPrefController<IntSetting>
+{
+    private final IntSetting setting;
+
+    private final ExtSettingControllerHelper<IntSetting> helper;
+
+    protected IntSettingPrefController(Context ctx, String key, IntSetting setting) {
+        super(ctx, key);
+        this.setting = setting;
+        helper = new ExtSettingControllerHelper(ctx, setting);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return helper.getAvailabilityStatus();
+    }
+
+    @Override
+    protected final int getCurrentValue() {
+        return setting.get(mContext);
+    }
+
+    @Override
+    protected boolean setValue(int val) {
+        return setting.put(mContext, val);
+    }
+
+    @Override
+    public void onResume(@NonNull LifecycleOwner owner) {
+        helper.onResume(this);
+    }
+
+    @Override
+    public void onPause(@NonNull LifecycleOwner owner) {
+        helper.onPause(this);
+    }
+
+    // called by the setting observer
+    @Override
+    public void accept(IntSetting intSetting) {
+        updatePreference();
+    }
+}
diff --git a/src/com/android/settings/ext/RadioButtonPickerFragment2.java b/src/com/android/settings/ext/RadioButtonPickerFragment2.java
new file mode 100644
index 00000000000..a44c9280af7
--- /dev/null
+++ b/src/com/android/settings/ext/RadioButtonPickerFragment2.java
@@ -0,0 +1,208 @@
+package com.android.settings.ext;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.utils.CandidateInfoExtra;
+import com.android.settings.widget.RadioButtonPickerFragment;
+import com.android.settingslib.widget.CandidateInfo;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RadioButtonPickerFragment2 extends RadioButtonPickerFragment {
+
+    private final ArrayList<CandidateInfo> candidates = new ArrayList<>();
+
+    static final String KEY_PREF_CONTROLLER_CLASS = "pref_controller";
+    static final String KEY_PREF_KEY = "pref_key";
+
+    private AbstractListPreferenceController prefController;
+
+    public static void fillArgs(Preference pref, AbstractListPreferenceController pc, boolean isForWork) {
+        Bundle args = pref.getExtras();
+        args.putString(KEY_PREF_CONTROLLER_CLASS, pc.getClass().getName());
+        args.putString(KEY_PREF_KEY, pc.getPreferenceKey());
+        args.putBoolean(EXTRA_FOR_WORK, isForWork);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        Bundle args = requireArguments();
+        String prefControllerClass = args.getString(KEY_PREF_CONTROLLER_CLASS);
+        String prefKey = args.getString(KEY_PREF_KEY);
+        boolean forWork = args.getBoolean(EXTRA_FOR_WORK);
+
+        Context ctx = requireContext();
+
+        prefController = (AbstractListPreferenceController) BasePreferenceController
+                .createInstance(ctx,prefControllerClass, prefKey, forWork);
+        prefController.fragment = this;
+
+        super.onCreate(savedInstanceState);
+    }
+
+    private static final String KEY_USER_CREDENTIAL_CONFIRMED = "user_credential_confirmed";
+    private boolean userCredentialConfirmed;
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        PreferenceScreen ps = getPreferenceManager().createPreferenceScreen(requireContext());
+        setPreferenceScreen(ps);
+
+        if (savedInstanceState != null) {
+            userCredentialConfirmed = savedInstanceState.getBoolean(
+                    KEY_USER_CREDENTIAL_CONFIRMED, false);
+        }
+
+        updateCandidates();
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putBoolean(KEY_USER_CREDENTIAL_CONFIRMED, userCredentialConfirmed);
+    }
+
+    private Runnable onAfterCredentialConfirmed;
+
+    private void runAfterCredentialConfirmation(Runnable runnable) {
+        if (userCredentialConfirmed) {
+            throw new IllegalStateException();
+        }
+
+        if (onAfterCredentialConfirmed != null) {
+            throw new IllegalStateException();
+        }
+
+        onAfterCredentialConfirmed = runnable;
+
+        var b = new ChooseLockSettingsHelper.Builder(requireActivity());
+        b.setActivityResultLauncher(credentialConfirmationLauncher);
+        b.setForegroundOnly(true);
+        b.show();
+    }
+
+    private final ActivityResultLauncher<Intent> credentialConfirmationLauncher =
+            registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
+                this::onCredentialConfirmationResult);
+
+    private void onCredentialConfirmationResult(@Nullable ActivityResult result) {
+        Runnable r = onAfterCredentialConfirmed;
+        onAfterCredentialConfirmed = null;
+
+        if (result != null && result.getResultCode() == Activity.RESULT_OK) {
+            userCredentialConfirmed = true;
+            if (r != null) {
+                r.run();
+            }
+        }
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        if (!requireActivity().isChangingConfigurations()) {
+            userCredentialConfirmed = false;
+        }
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return -1;
+    }
+
+    @Override
+    protected List<? extends CandidateInfo> getCandidates() {
+        candidates.clear();
+        prefController.getEntriesAsCandidates(candidates);
+        return candidates;
+    }
+
+    @Override
+    protected void addPrefsBeforeList(PreferenceScreen screen) {
+        prefController.addPrefsBeforeList(this, screen);
+    }
+
+    @Override
+    protected void addPrefsAfterList(PreferenceScreen screen) {
+        prefController.addPrefsAfterList(this, screen);
+    }
+
+    @Override
+    protected String getDefaultKey() {
+        return Integer.toString(prefController.getCurrentValue());
+    }
+
+    @Override
+    protected boolean setDefaultKey(String key) {
+        if (key.equals(getDefaultKey())) {
+            return true;
+        }
+
+        if (!userCredentialConfirmed && prefController.isCredentialConfirmationRequired()) {
+            Context ctx = requireContext();
+            LockPatternUtils lpu = FeatureFactory.getFeatureFactory()
+                .getSecurityFeatureProvider()
+                .getLockPatternUtils(ctx);
+
+            if (lpu.isSecure(ctx.getUserId())) {
+                runAfterCredentialConfirmation(() -> prefController.setValue(Integer.parseInt(key)));
+                return false;
+            }
+        }
+
+        return prefController.setValue(Integer.parseInt(key));
+    }
+
+    @Override
+    public void bindPreferenceExtra(SelectorWithWidgetPreference pref, String key, CandidateInfo info,
+                                    String defaultKey, String systemDefaultKey) {
+        pref.setSingleLineTitle(false);
+
+        if (info instanceof CandidateInfoExtra) {
+            var cie = (CandidateInfoExtra) info;
+            pref.setSummary(cie.loadSummary());
+        }
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return METRICS_CATEGORY_UNKNOWN;
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        prefController.onPause(this);
+    }
+
+    private boolean updateCandidatesOnResume;
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        prefController.onResume(this);
+
+        if (updateCandidatesOnResume) {
+            updateCandidates();
+        } else {
+            // updateCandidates() is called from onCreatePrefences() right before the first onResume()
+            updateCandidatesOnResume = true;
+        }
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java
index 4b5d9526f16..acc67ecb639 100644
--- a/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/BatterySettingsFeatureProviderImpl.java
@@ -32,17 +32,17 @@ public class BatterySettingsFeatureProviderImpl implements BatterySettingsFeatur
 
     @Override
     public boolean isManufactureDateAvailable(Context context, long manufactureDateMs) {
-        return false;
+        return manufactureDateMs > 1_609_459_200_000L; // 2021-01-01
     }
 
     @Override
     public boolean isFirstUseDateAvailable(Context context, long firstUseDateMs) {
-        return false;
+        return firstUseDateMs > 1_609_459_200_000L; // 2021-01-01
     }
 
     @Override
     public boolean isBatteryInfoEnabled(Context context) {
-        return false;
+        return true;
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
index fef30563fe2..6b057484c9f 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
@@ -616,14 +616,10 @@ public static NameAndIcon getNameAndIconFromPowerComponent(
                 iconId = R.drawable.ic_settings_aod;
                 break;
             default:
-                Log.w(
-                        TAG,
-                        "unknown attribute:"
-                                + DebugUtils.constantToString(
-                                        BatteryConsumer.class,
-                                        "POWER_COMPONENT_",
-                                        powerComponentId));
-                name = null;
+                String fieldName = DebugUtils.constantToString(
+                        BatteryConsumer.class, "POWER_COMPONENT_", powerComponentId);
+                Log.w(TAG, "unknown attribute:" + fieldName);
+                name = context.getResources().getString(R.string.header_category_system) + " (" + fieldName + ")";
                 iconId = R.drawable.ic_power_system;
                 break;
         }
diff --git a/src/com/android/settings/location/GnssPsdsPrefController.java b/src/com/android/settings/location/GnssPsdsPrefController.java
new file mode 100644
index 00000000000..8350d8264b3
--- /dev/null
+++ b/src/com/android/settings/location/GnssPsdsPrefController.java
@@ -0,0 +1,58 @@
+package com.android.settings.location;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.ext.settings.GnssSettings;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.ext.IntSettingPrefController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+public class GnssPsdsPrefController extends IntSettingPrefController {
+    private final String psdsType;
+    private final boolean hasGpsFeature;
+
+    public GnssPsdsPrefController(Context ctx, String key) {
+        super(ctx, key, GnssSettings.getPsdsSetting(ctx));
+        psdsType = ctx.getString(com.android.internal.R.string.config_gnssPsdsType);
+        hasGpsFeature = ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (!hasGpsFeature) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
+
+        int result = super.getAvailabilityStatus();
+        if (result == AVAILABLE) {
+            if (psdsType.isEmpty()) {
+                result = UNSUPPORTED_ON_DEVICE;
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public void addPrefsAfterList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+        addFooterPreference(screen, R.string.gnss_psds_footer);
+    }
+
+    @Override
+    protected void getEntries(Entries entries) {
+        entries.add(R.string.psds_enabled_grapheneos_server, GnssSettings.PSDS_SERVER_GRAPHENEOS);
+        int standardServerString;
+        switch (psdsType) {
+            case GnssSettings.PSDS_TYPE_QUALCOMM_XTRA:
+                standardServerString = R.string.psds_enabled_qualcomm_server;
+                break;
+            default:
+                standardServerString = R.string.psds_enabled_standard_server;
+                break;
+        }
+        entries.add(standardServerString, GnssSettings.PSDS_SERVER_STANDARD);
+        entries.add(R.string.psds_disabled, R.string.psds_disabled_summary, GnssSettings.PSDS_DISABLED);
+    }
+}
diff --git a/src/com/android/settings/location/GnssSuplPrefController.java b/src/com/android/settings/location/GnssSuplPrefController.java
new file mode 100644
index 00000000000..95be474c9de
--- /dev/null
+++ b/src/com/android/settings/location/GnssSuplPrefController.java
@@ -0,0 +1,40 @@
+package com.android.settings.location;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.ext.settings.GnssSettings;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.ext.IntSettingPrefController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+public class GnssSuplPrefController extends IntSettingPrefController {
+    private final boolean hasGpsFeature;
+
+    public GnssSuplPrefController(Context ctx, String key) {
+        super(ctx, key, GnssSettings.SUPL_SETTING);
+        hasGpsFeature = ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);
+    }
+
+    @Override
+    public void addPrefsAfterList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+        addFooterPreference(screen, R.string.pref_gnss_supl_footer);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (!hasGpsFeature) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
+        return super.getAvailabilityStatus();
+    }
+
+    @Override
+    protected void getEntries(Entries entries) {
+        entries.add(R.string.supl_enabled_grapheneos_proxy, GnssSettings.SUPL_SERVER_GRAPHENEOS_PROXY);
+        entries.add(R.string.supl_enabled_standard_server, GnssSettings.SUPL_SERVER_STANDARD);
+        entries.add(R.string.supl_disabled, R.string.supl_disabled_summary, GnssSettings.SUPL_DISABLED);
+    }
+}
diff --git a/src/com/android/settings/location/LocationIndicatorsPreferenceController.java b/src/com/android/settings/location/LocationIndicatorsPreferenceController.java
index 75ffb3a9286..1b1af8f8f73 100644
--- a/src/com/android/settings/location/LocationIndicatorsPreferenceController.java
+++ b/src/com/android/settings/location/LocationIndicatorsPreferenceController.java
@@ -34,7 +34,7 @@ public LocationIndicatorsPreferenceController(Context context, String preference
     @Override
     public boolean isChecked() {
         return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
-                Utils.PROPERTY_LOCATION_INDICATORS_ENABLED, false);
+                Utils.PROPERTY_LOCATION_INDICATORS_ENABLED, true);
     }
 
     @Override
diff --git a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
index 3cb30251c51..7b3294fabed 100644
--- a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
@@ -48,7 +48,7 @@ public class RecentLocationAccessPreferenceController extends LocationBasePrefer
     RecentAppOpsAccess mRecentLocationApps;
     private PreferenceCategory mCategoryRecentLocationRequests;
     private int mType = ProfileSelectFragment.ProfileType.ALL;
-    private boolean mShowSystem = false;
+    private boolean mShowSystem = true;
     private boolean mSystemSettingChanged = false;
 
     private static class PackageEntryClickedListener implements
@@ -86,9 +86,9 @@ public RecentLocationAccessPreferenceController(Context context, String key,
         super(context, key);
         mRecentLocationApps = recentLocationApps;
         mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
-                SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false)
+                SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true)
                 ? Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1
+                Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1
                 : false;
     }
 
diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java b/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java
index 0ea9ffbdacb..b45bca51c4f 100644
--- a/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java
+++ b/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java
@@ -40,7 +40,7 @@ public class RecentLocationAccessSeeAllFragment extends DashboardFragment {
     private static final int MENU_SHOW_SYSTEM = Menu.FIRST + 1;
     private static final int MENU_HIDE_SYSTEM = Menu.FIRST + 2;
 
-    private boolean mShowSystem = false;
+    private boolean mShowSystem = true;
     private MenuItem mShowSystemMenu;
     private MenuItem mHideSystemMenu;
     private RecentLocationAccessSeeAllPreferenceController mController;
@@ -61,9 +61,9 @@ public void onAttach(Context context) {
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
-            SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false)
+            SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true)
             ? Settings.Secure.getInt(getContentResolver(),
-            Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1
+            Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1
             : false;
     }
 
diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java
index 998e6f3f541..f5f0c5c6b00 100644
--- a/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationAccessSeeAllPreferenceController.java
@@ -51,9 +51,9 @@ public class RecentLocationAccessSeeAllPreferenceController
     public RecentLocationAccessSeeAllPreferenceController(Context context, String key) {
         super(context, key);
         mShowSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
-            SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false)
+            SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true)
             ? Settings.Secure.getInt(mContext.getContentResolver(),
-            Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1
+            Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1
             : false;
 
         mRecentLocationAccesses = RecentAppOpsAccess.createForLocation(context);
diff --git a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java b/src/com/android/settings/location/RecentLocationRequestPreferenceController.java
index 39211ee5202..bee904efdc4 100644
--- a/src/com/android/settings/location/RecentLocationRequestPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationRequestPreferenceController.java
@@ -87,9 +87,9 @@ public void displayPreference(PreferenceScreen screen) {
         final List<RecentLocationApps.Request> recentLocationRequests = new ArrayList<>();
         final UserManager userManager = UserManager.get(mContext);
         final boolean showSystem = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
-                SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false)
+                SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, true)
                 ? Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1
+                Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 1) == 1
                 : false;
 
         for (RecentLocationApps.Request request : mRecentLocationApps.getAppListSorted(
diff --git a/src/com/android/settings/network/ConnectivityChecksPrefController.java b/src/com/android/settings/network/ConnectivityChecksPrefController.java
new file mode 100644
index 00000000000..ef2ee6c12ee
--- /dev/null
+++ b/src/com/android/settings/network/ConnectivityChecksPrefController.java
@@ -0,0 +1,29 @@
+package com.android.settings.network;
+
+import android.content.Context;
+import android.ext.settings.ConnChecksSetting;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.ext.IntSettingPrefController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+public class ConnectivityChecksPrefController extends IntSettingPrefController {
+
+    public ConnectivityChecksPrefController(Context ctx, String key) {
+        super(ctx, key, ConnChecksSetting.SYS_PROP);
+    }
+
+    @Override
+    protected void getEntries(Entries entries) {
+        entries.add(R.string.conn_checks_grapheneos_server, ConnChecksSetting.VAL_GRAPHENEOS);
+        entries.add(R.string.conn_checks_google_server, ConnChecksSetting.VAL_STANDARD);
+        entries.add(R.string.conn_checks_disabled, ConnChecksSetting.VAL_DISABLED);
+    }
+
+    @Override
+    public void addPrefsAfterList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+        addFooterPreference(screen, R.string.conn_checks_footer);
+    }
+}
diff --git a/src/com/android/settings/network/GoogleEuiccLpaController.java b/src/com/android/settings/network/GoogleEuiccLpaController.java
new file mode 100644
index 00000000000..d697c3b97f1
--- /dev/null
+++ b/src/com/android/settings/network/GoogleEuiccLpaController.java
@@ -0,0 +1,108 @@
+package com.android.settings.network;
+
+import android.Manifest;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.ext.PackageId;
+import android.os.PowerManager;
+import android.os.UserHandle;
+import android.permission.PermissionManager;
+
+import com.android.settings.R;
+import com.android.settings.ext.AbstractTogglePrefController;
+import com.android.settings.ext.ExtSettingControllerHelper;
+
+import static java.util.Objects.requireNonNull;
+
+public class GoogleEuiccLpaController extends AbstractTogglePrefController {
+    private static final String PKG_NAME = PackageId.G_EUICC_LPA_NAME;
+
+    private final PackageManager packageManager;
+    private final boolean isPresent;
+
+    public GoogleEuiccLpaController(Context context, String key) {
+        super(context, key);
+        packageManager = context.getPackageManager();
+
+        boolean isPresent = false;
+        try {
+            var ai = packageManager.getApplicationInfo(PKG_NAME, 0);
+            isPresent = ai.isSystemApp();
+        } catch (PackageManager.NameNotFoundException ignored) {}
+
+        this.isPresent = isPresent;
+    }
+
+    @Override
+    public boolean isChecked() {
+        try {
+            return isPresent && packageManager.getApplicationInfo(PKG_NAME, 0).enabled;
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (!isPresent) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
+        return ExtSettingControllerHelper.getGlobalSettingAvailability(mContext);
+    }
+    
+    private void setEnabled(boolean isEnabled) {
+        String pkg = PKG_NAME;
+
+        if (isEnabled) {
+            var permManager = mContext.getSystemService(PermissionManager.class);
+            UserHandle user = mContext.getUser();
+
+            String perm = Manifest.permission.CAMERA;
+            permManager.revokeRuntimePermission(pkg, perm, user, null);
+            // Previously, Camera permission was auto-granted with the FLAG_PERMISSION_SYSTEM_FIXED,
+            // which made it unchangeable by the user.
+            // Removing FLAG_PERMISSION_USER_FIXED is needed to make sure that the app is always
+            // able to show a permission request dialog after being enabled
+            int permFlagsToRemove = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
+                    | PackageManager.FLAG_PERMISSION_USER_FIXED;
+            permManager.updatePermissionFlags(pkg, perm, permFlagsToRemove, 0, user);
+        }
+
+        var powerManager = requireNonNull(mContext.getSystemService(PowerManager.class));
+
+        int ces = isEnabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
+                              PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+        packageManager.setApplicationEnabledSetting(pkg, ces, 0);
+
+        // Reboot is required in both cases:
+        // - OS code doesn't expect LPA to become unavailable at runtime and starts to poll for it
+        // with a high frequency
+        // - EuiccGoogle performs initialization in response to "(locked) boot completed" broadcasts
+        // - also, if current boot count is 1 (i.e. if this is the first boot), EuiccGoogle expects to
+        // be interacted with by Google's SetupWizard. Boot count will be at least 2 after reboot.
+        powerManager.reboot(null);
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        var b = new AlertDialog.Builder(mContext);
+
+        int msg;
+        int btnText;
+        if (isChecked) {
+            msg = R.string.g_euicc_lpa_enable_dialog_msg;
+            btnText = R.string.g_euicc_lpa_restart_button;
+        } else {
+            b.setTitle(R.string.g_euicc_lpa_disable_dialog_title);
+            msg = R.string.g_euicc_lpa_disable_dialog_msg;
+            btnText = R.string.g_euicc_lpa_proceed_button;
+        }
+
+        b.setMessage(msg);
+        b.setPositiveButton(btnText, (d, btn) -> setEnabled(isChecked));
+        b.show();
+
+        return false;
+    }
+}
diff --git a/src/com/android/settings/network/InternetSetupActivity.java b/src/com/android/settings/network/InternetSetupActivity.java
new file mode 100644
index 00000000000..4e36accb886
--- /dev/null
+++ b/src/com/android/settings/network/InternetSetupActivity.java
@@ -0,0 +1,52 @@
+package com.android.settings.network;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.preference.PreferenceFragmentCompat;
+
+import com.android.settings.ButtonBarHandler;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.SetupWizardUtils;
+
+import com.google.android.setupdesign.util.ThemeHelper;
+
+public class InternetSetupActivity extends SettingsActivity {
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        setTheme(SetupWizardUtils.getTheme(this, getIntent()));
+        ThemeHelper.trySetDynamicColor(this);
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    protected void createUiFromIntent(Bundle savedState, Intent intent) {
+        intent.putExtra("extra_prefs_show_button_bar", false);
+        super.createUiFromIntent(savedState, intent);
+    }
+
+    @Override
+    protected boolean isToolbarEnabled() {
+        // Hide the action bar from this page.
+        return false;
+    }
+
+    private static final String FRAGMENT_CLASS_NAME = NetworkProviderSetup.class.getName();
+
+    @Override
+    public Intent getIntent() {
+        Intent modIntent = new Intent(super.getIntent());
+        modIntent.putExtra(EXTRA_SHOW_FRAGMENT, FRAGMENT_CLASS_NAME);
+        return modIntent;
+    }
+
+    @Override
+    protected boolean isValidFragment(String fragmentName) {
+        return FRAGMENT_CLASS_NAME.equals(fragmentName);
+    }
+}
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index 69183ff25c0..70ccc5c4780 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -250,8 +250,8 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment
     /**
      * Mobile networks list for provider model
      */
-    private static final String PREF_KEY_PROVIDER_MOBILE_NETWORK = "provider_model_mobile_network";
-    private NetworkMobileProviderController mNetworkMobileProviderController;
+    static final String PREF_KEY_PROVIDER_MOBILE_NETWORK = "provider_model_mobile_network";
+    NetworkMobileProviderController mNetworkMobileProviderController;
 
     /**
      * Tracks whether the user initiated a connection via clicking in order to autoscroll to the
diff --git a/src/com/android/settings/network/NetworkProviderSetup.java b/src/com/android/settings/network/NetworkProviderSetup.java
new file mode 100644
index 00000000000..ae3c01a70a3
--- /dev/null
+++ b/src/com/android/settings/network/NetworkProviderSetup.java
@@ -0,0 +1,155 @@
+package com.android.settings.network;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.settings.R;
+
+import com.google.android.setupcompat.template.FooterBarMixin;
+import com.google.android.setupcompat.template.FooterButton;
+import com.google.android.setupdesign.GlifPreferenceLayout;
+
+/**
+ * UI for Mobile network and Wi-Fi network setup.
+ */
+public class NetworkProviderSetup extends NetworkProviderSettings {
+    public static final String EXTRA_SETUP_WIZARD_MODE_WIFI = "setup_wizard_mode_wifi";
+    public static final String EXTRA_SETUP_WIZARD_TITLE = "setup_wizard_title";
+    public static final String EXTRA_SETUP_WIZARD_DESCRIPTION = "setup_wizard_description";
+    private static final String PREF_KEY_CONNECTED_ETHERNET_NETWORK = "connected_ethernet_network";
+    private static final String EXTRA_PREFS_SET_SKIP_TEXT = "extra_prefs_set_skip_text";
+
+    /**
+     * Don't show media other than wifi, even if they might be available.
+     */
+    private boolean isSetupWizardModeWifi;
+    private FooterButton nextButton;
+    private FooterButton skipButton;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        isSetupWizardModeWifi = getIntent().getBooleanExtra(
+                EXTRA_SETUP_WIZARD_MODE_WIFI, false);
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        Activity activity = getActivity();
+        if (activity == null) return;
+        GlifPreferenceLayout layout = (GlifPreferenceLayout) view;
+        layout.setDividerInsets(Integer.MAX_VALUE, 0);
+        if (isSetupWizardModeWifi) {
+            layout.setIcon(activity.getDrawable(R.drawable.baseline_wifi_glif));
+            Intent intent = activity.getIntent();
+            layout.setHeaderText(intent.getStringExtra(EXTRA_SETUP_WIZARD_TITLE));
+            layout.setDescriptionText(intent.getStringExtra(EXTRA_SETUP_WIZARD_DESCRIPTION));
+        }
+        FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
+        // setup next button
+        nextButton = new FooterButton.Builder(activity)
+                .setButtonType(FooterButton.ButtonType.NEXT)
+                .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
+                .setText(R.string.next_label)
+                .build();
+        mixin.setPrimaryButton(nextButton);
+        nextButton.setOnClickListener(v -> finish());
+        // setup skip button
+        skipButton = new FooterButton.Builder(activity)
+                .setButtonType(FooterButton.ButtonType.SKIP)
+                .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
+                .setText(R.string.skip_label)
+                .build();
+        String buttonText = getIntent().getStringExtra(EXTRA_PREFS_SET_SKIP_TEXT);
+        if (!TextUtils.isEmpty(buttonText)) {
+            skipButton.setText(buttonText);
+        }
+        mixin.setSecondaryButton(skipButton);
+        skipButton.setOnClickListener(v -> finish());
+    }
+
+    @Override
+    public void finish() {
+        Activity activity = getActivity();
+        if (activity == null) return;
+        activity.setResult(Activity.RESULT_OK);
+        activity.finish();
+    }
+
+    @Override
+    void changeNextButtonState(boolean enabled) {
+        nextButton.setEnabled(enabled);
+        skipButton.setVisibility(enabled ? View.GONE : View.VISIBLE);
+    }
+
+    @Override
+    public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
+            Bundle savedInstanceState) {
+        GlifPreferenceLayout layout = (GlifPreferenceLayout) parent;
+        return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
+    }
+
+    private static void maybeSetVisible(@Nullable Preference p, boolean visible) {
+        if (p != null) {
+            p.setVisible(visible);
+        }
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        maybeSetVisible(mConfigureWifiSettingsPreference, false);
+        maybeSetVisible(mDataUsagePreference, false);
+        maybeSetVisible(mAirplaneModeMsgPreference, false);
+        maybeSetVisible(mResetInternetPreference, false);
+        if (isSetupWizardModeWifi) {
+            maybeSetVisible(findPreference(PREF_KEY_CONNECTED_ETHERNET_NETWORK), false);
+            maybeSetVisible(findPreference(PREF_KEY_PROVIDER_MOBILE_NETWORK), false);
+            if (mNetworkMobileProviderController != null) {
+                mNetworkMobileProviderController.hidePreference(true, false);
+            }
+        }
+    }
+
+    @Override
+    protected void setProgressBarVisible(boolean visible) {
+        GlifPreferenceLayout glif = (GlifPreferenceLayout) getView();
+        if (glif == null) return;
+        glif.setProgressBarShown(visible);
+    }
+
+    @Override
+    public void setHasOptionsMenu(boolean hasMenu) {
+        // do nothing
+    }
+
+    @Override
+    public void scrollToPreference(String key) {
+        // do nothing
+    }
+
+    @Override
+    public void scrollToPreference(Preference preference) {
+        // do nothing
+    }
+
+    @Override
+    public View setPinnedHeaderView(int layoutResId) {
+        return null; // result unused
+    }
+
+    @Override
+    public void setLoading(boolean loading, boolean animate) {
+        // do nothing
+    }
+}
diff --git a/src/com/android/settings/network/RemoteProvisioningPrefController.java b/src/com/android/settings/network/RemoteProvisioningPrefController.java
new file mode 100644
index 00000000000..8617d6bd98c
--- /dev/null
+++ b/src/com/android/settings/network/RemoteProvisioningPrefController.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.ext.settings.RemoteKeyProvisioningSettings;
+
+import com.android.settings.R;
+import com.android.settings.ext.IntSettingPrefController;
+
+public class RemoteProvisioningPrefController extends IntSettingPrefController {
+
+    public RemoteProvisioningPrefController(Context ctx, String key) {
+        super(ctx, key, RemoteKeyProvisioningSettings.SERVER_SETTING);
+    }
+
+    @Override
+    protected void getEntries(Entries entries) {
+        entries.add(R.string.remote_provisioning_enabled_grapheneos_proxy, RemoteKeyProvisioningSettings.GRAPHENEOS_PROXY);
+        entries.add(R.string.remote_provisioning_enabled_google_server, RemoteKeyProvisioningSettings.STANDARD_SERVER);
+    }
+}
diff --git a/src/com/android/settings/network/WidevineProvisioningPrefController.java b/src/com/android/settings/network/WidevineProvisioningPrefController.java
new file mode 100644
index 00000000000..09d62f012ac
--- /dev/null
+++ b/src/com/android/settings/network/WidevineProvisioningPrefController.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.ext.settings.WidevineProvisioningSettings;
+
+import com.android.settings.R;
+import androidx.preference.PreferenceScreen;
+import com.android.settings.ext.IntSettingPrefController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+public class WidevineProvisioningPrefController extends IntSettingPrefController {
+
+    public WidevineProvisioningPrefController(Context ctx, String key) {
+        super(ctx, key, WidevineProvisioningSettings.SERVER_SETTING);
+    }
+
+    @Override
+    public void addPrefsAfterList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+        addFooterPreference(screen, R.string.widevine_provisioning_footer);
+    }
+
+    @Override
+    protected void getEntries(Entries entries) {
+        entries.add(R.string.widevine_provisioning_enabled_grapheneos_proxy, WidevineProvisioningSettings.WV_GRAPHENEOS_PROXY);
+        entries.add(R.string.widevine_provisioning_enabled_google_server, WidevineProvisioningSettings.WV_STANDARD_SERVER);
+    }
+}
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
index 7d5230db2b6..a0b88295f4a 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@@ -93,7 +93,7 @@ public EnabledNetworkModePreferenceController(Context context, String key) {
     @Override
     public int getAvailabilityStatus() {
         return getNetworkModePreferenceType(mContext, mSubId)
-                == NetworkModePreferenceType.EnabledNetworkMode
+                != NetworkModePreferenceType.PreferredNetworkMode
                 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
     }
 
@@ -289,6 +289,7 @@ public void updateConfig() {
         }
 
         void setPreferenceEntries() {
+            boolean lteOnlyUnsupported = false;
             mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
 
             clearAllEntries();
@@ -304,6 +305,7 @@ void setPreferenceEntries() {
                             .addFormat(UiOptions.PresentFormat.addGlobalEntry);
                     break;
                 case ENABLED_NETWORKS_CDMA_NO_LTE_CHOICES:
+                    lteOnlyUnsupported = true;
                     uiOptions = uiOptions
                             .setChoices(R.array.enabled_networks_cdma_no_lte_values)
                             .addFormat(UiOptions.PresentFormat.add3gEntry)
@@ -323,6 +325,7 @@ void setPreferenceEntries() {
                             .addFormat(UiOptions.PresentFormat.add2gEntry);
                     break;
                 case ENABLED_NETWORKS_EXCEPT_GSM_LTE_CHOICES:
+                    lteOnlyUnsupported = true;
                     uiOptions = uiOptions
                             .setChoices(R.array.enabled_networks_except_gsm_lte_values)
                             .addFormat(UiOptions.PresentFormat.add3gEntry);
@@ -340,6 +343,7 @@ void setPreferenceEntries() {
                             .addFormat(UiOptions.PresentFormat.add3gEntry);
                     break;
                 case ENABLED_NETWORKS_EXCEPT_LTE_CHOICES:
+                    lteOnlyUnsupported = true;
                     uiOptions = uiOptions
                             .setChoices(R.array.enabled_networks_except_lte_values)
                             .addFormat(UiOptions.PresentFormat.add3gEntry)
@@ -388,6 +392,11 @@ void setPreferenceEntries() {
                 throw new IllegalArgumentException(
                         uiOptions.getType().name() + " index error.");
             }
+
+            if (!lteOnlyUnsupported){
+                addLteOnlyEntry();
+            }
+
             // Compose options based on given values and formats.
             IntStream.range(0, formatList.size()).forEach(entryIndex -> {
                 switch (formatList.get(entryIndex)) {
@@ -574,6 +583,9 @@ void setPreferenceValueAndSummary(int networkMode) {
                         break;
                     }
                 case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY:
+                    setSummary(mShow4gForLTE
+                            ? R.string.network_4G_only : R.string.network_lte_only);
+                    break;
                 case TelephonyManagerConstants.NETWORK_MODE_LTE_WCDMA:
                     if (!mIsGlobalCdma) {
                         setSelectedEntry(
@@ -839,6 +851,16 @@ private void add1xEntry(int value) {
             mEntriesValue.add(value);
         }
 
+        private void addLteOnlyEntry() {
+            if (mShow4gForLTE) {
+                mEntries.add(mContext.getString(R.string.network_4G_only));
+                mEntriesValue.add(TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY);
+            } else {
+                mEntries.add(mContext.getString(R.string.network_lte_only));
+                mEntriesValue.add(TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY);
+            }
+        }
+
         private void addCustomEntry(String name, int value) {
             mEntries.add(name);
             mEntriesValue.add(value);
diff --git a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
index 210cd879966..f5c0514525b 100644
--- a/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/PreferredNetworkModePreferenceController.java
@@ -126,7 +126,7 @@ private int getPreferredNetworkModeSummaryResId(int NetworkMode) {
             case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA:
                 return R.string.preferred_network_mode_lte_tdscdma_summary;
             case TelephonyManagerConstants.NETWORK_MODE_LTE_ONLY:
-                return R.string.preferred_network_mode_lte_summary;
+                return R.string.preferred_network_mode_lte_only_summary;
             case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM:
                 return R.string.preferred_network_mode_lte_tdscdma_gsm_summary;
             case TelephonyManagerConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
diff --git a/src/com/android/settings/network/tether/TetherSettings.java b/src/com/android/settings/network/tether/TetherSettings.java
index 77ef4b6ef12..f7838c98ce0 100644
--- a/src/com/android/settings/network/tether/TetherSettings.java
+++ b/src/com/android/settings/network/tether/TetherSettings.java
@@ -87,6 +87,7 @@ public class TetherSettings extends RestrictedSettingsFragment
     @VisibleForTesting
     static final String KEY_ENABLE_BLUETOOTH_TETHERING = "enable_bluetooth_tethering";
     private static final String KEY_ENABLE_ETHERNET_TETHERING = "enable_ethernet_tethering";
+    private static final String KEY_ENABLE_DATA_SAVER_TETHERING = "enable_data_saver_tethering";
     private static final String KEY_DATA_SAVER_FOOTER = "disabled_on_data_saver";
     @VisibleForTesting
     static final String KEY_TETHER_PREFS_TOP_INTRO = "tether_prefs_top_intro";
@@ -100,6 +101,8 @@ public class TetherSettings extends RestrictedSettingsFragment
     TwoStatePreference mBluetoothTether;
     @VisibleForTesting
     TwoStatePreference mEthernetTether;
+    @VisibleForTesting
+    TwoStatePreference mDataSaverTether;
 
     private BroadcastReceiver mTetherChangeReceiver;
     private BroadcastReceiver mBluetoothStateReceiver;
@@ -209,6 +212,7 @@ public void onCreate(Bundle icicle) {
         if (!ethernetAvailable) getPreferenceScreen().removePreference(mEthernetTether);
         // Set initial state based on Data Saver mode.
         onDataSaverChanged(mDataSaverBackend.isDataSaverEnabled());
+        mDataSaverTether.setChecked(false);
     }
 
     @VisibleForTesting
@@ -247,15 +251,16 @@ void setupTetherPreference() {
         mUsbTether = (RestrictedSwitchPreference) findPreference(KEY_USB_TETHER_SETTINGS);
         mBluetoothTether = (TwoStatePreference) findPreference(KEY_ENABLE_BLUETOOTH_TETHERING);
         mEthernetTether = (TwoStatePreference) findPreference(KEY_ENABLE_ETHERNET_TETHERING);
+        mDataSaverTether = (TwoStatePreference) findPreference(KEY_ENABLE_DATA_SAVER_TETHERING);
     }
 
     @Override
     public void onDataSaverChanged(boolean isDataSaving) {
         mDataSaverEnabled = isDataSaving;
-        mWifiTetherPreferenceController.setDataSaverEnabled(mDataSaverEnabled);
-        mUsbTether.setEnabled(!mDataSaverEnabled);
-        mBluetoothTether.setEnabled(!mDataSaverEnabled);
-        mEthernetTether.setEnabled(!mDataSaverEnabled);
+        mWifiTetherPreferenceController.setDataSaverEnabled(mDataSaverEnabled && !mDataSaverTether.isChecked());
+        mUsbTether.setEnabled(!mDataSaverEnabled || mDataSaverTether.isChecked());
+        mBluetoothTether.setEnabled(!mDataSaverEnabled || mDataSaverTether.isChecked());
+        mEthernetTether.setEnabled(!mDataSaverEnabled || mDataSaverTether.isChecked());
         mDataSaverFooter.setVisible(mDataSaverEnabled);
     }
 
@@ -461,7 +466,7 @@ void updateUsbState(String[] tethered) {
                     + ", usbTethered : " + usbTethered);
         }
         if (usbTethered) {
-            mUsbTether.setEnabled(!mDataSaverEnabled);
+            mUsbTether.setEnabled(!mDataSaverEnabled || mDataSaverTether.isChecked());
             mUsbTether.setChecked(true);
             final RestrictedLockUtils.EnforcedAdmin enforcedAdmin =
                     checkIfUsbDataSignalingIsDisabled(mContext, UserHandle.myUserId());
@@ -482,7 +487,7 @@ private void updateUsbPreference() {
         if (enforcedAdmin != null) {
             mUsbTether.setDisabledByAdmin(enforcedAdmin);
         } else if (usbAvailable) {
-            mUsbTether.setEnabled(!mDataSaverEnabled);
+            mUsbTether.setEnabled(!mDataSaverEnabled || mDataSaverTether.isChecked());
         } else {
             mUsbTether.setEnabled(false);
         }
@@ -520,9 +525,9 @@ private void updateBluetoothState() {
         } else {
             if (btState == BluetoothAdapter.STATE_ON && isBluetoothTetheringOn()) {
                 mBluetoothTether.setChecked(true);
-                mBluetoothTether.setEnabled(!mDataSaverEnabled);
+                mBluetoothTether.setEnabled(!mDataSaverEnabled || mDataSaverTether.isChecked());
             } else {
-                mBluetoothTether.setEnabled(!mDataSaverEnabled);
+                mBluetoothTether.setEnabled(!mDataSaverEnabled || mDataSaverTether.isChecked());
                 mBluetoothTether.setChecked(false);
             }
         }
@@ -547,10 +552,10 @@ void updateEthernetState(String[] available, String[] tethered) {
         }
 
         if (isTethered) {
-            mEthernetTether.setEnabled(!mDataSaverEnabled);
+            mEthernetTether.setEnabled(!mDataSaverEnabled || mDataSaverTether.isChecked());
             mEthernetTether.setChecked(true);
         } else if (mAvailableInterfaces.size() > 0) {
-            mEthernetTether.setEnabled(!mDataSaverEnabled);
+            mEthernetTether.setEnabled(!mDataSaverEnabled || mDataSaverTether.isChecked());
             mEthernetTether.setChecked(false);
         } else {
             mEthernetTether.setEnabled(false);
@@ -659,6 +664,11 @@ public List<String> getNonIndexableKeys(Context context) {
                     if (!ethernetAvailable) {
                         keys.add(KEY_ENABLE_ETHERNET_TETHERING);
                     }
+
+                    if (!TetherUtil.isTetherAvailable(context)) {
+                        keys.add(KEY_ENABLE_DATA_SAVER_TETHERING);
+                    }
+
                     return keys;
                 }
     };
diff --git a/src/com/android/settings/password/ChooseLockGenericController.java b/src/com/android/settings/password/ChooseLockGenericController.java
index cd9eb2fd44d..48dc2094d50 100644
--- a/src/com/android/settings/password/ChooseLockGenericController.java
+++ b/src/com/android/settings/password/ChooseLockGenericController.java
@@ -175,8 +175,9 @@ public boolean isScreenLockVisible(ScreenLockType type) {
                     && !managedProfile; // Swipe doesn't make sense for profiles.
             case MANAGED:
                 return mManagedPasswordProvider.isManagedPasswordChoosable();
-            case PIN:
             case PATTERN:
+                return false;
+            case PIN:
             case PASSWORD:
                 // Hide the secure lock screen options if the device doesn't support the secure lock
                 // screen feature.
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index aba9eddce21..cd23dad959f 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -856,11 +856,39 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
             return false;
         }
 
+    String[] convertErrorCodeToMessages() {
+        var pvec = new PasswordValidationErrorConverter(getContext(), mIsAlphaMode, mValidationErrors);
+        String[] res = pvec.convertErrorCodeToMessages();
+        mIsErrorTooShort = pvec.mIsErrorTooShort;
+        return res;
+    }
+
+    public static class PasswordValidationErrorConverter {
+        private final Context mContext;
+        private final boolean mIsAlphaMode;
+        private final List<PasswordValidationError> mValidationErrors;
+        public boolean mIsErrorTooShort = true;
+
+        public PasswordValidationErrorConverter(Context context, boolean isAlphaMode,
+                              List<PasswordValidationError> validationErrors) {
+            mContext = context;
+            mIsAlphaMode = isAlphaMode;
+            mValidationErrors = validationErrors;
+        }
+
+        private Context getContext() {
+            return mContext;
+        }
+
+        private String getString(int id) {
+            return mContext.getString(id);
+        }
+
         /**
          * @param errorCode error code returned from password validation.
          * @return an array of messages describing the error, important messages come first.
          */
-        String[] convertErrorCodeToMessages() {
+        public String[] convertErrorCodeToMessages() {
             List<String> messages = new ArrayList<>();
             mIsErrorTooShort = false;
             for (PasswordValidationError error : mValidationErrors) {
@@ -951,6 +979,7 @@ String[] convertErrorCodeToMessages() {
 
             return messages.toArray(new String[0]);
         }
+    }
 
         /**
          * Update the hint based on current Stage and length of password entry
@@ -1015,9 +1044,6 @@ private void setAutoPinConfirmOption(boolean enabled, int length) {
             if (enabled && !mIsAlphaMode && isAutoPinConfirmPossible(length)) {
                 mAutoPinConfirmOption.setVisibility(View.VISIBLE);
                 mAutoConfirmSecurityMessage.setVisibility(View.VISIBLE);
-                if (!mIsAutoPinConfirmOptionSetManually) {
-                    mAutoPinConfirmOption.setChecked(length == MIN_AUTO_PIN_REQUIREMENT_LENGTH);
-                }
             } else {
                 mAutoPinConfirmOption.setVisibility(View.GONE);
                 mAutoConfirmSecurityMessage.setVisibility(View.GONE);
diff --git a/src/com/android/settings/privacy/CameraExtensionsFallbackPreferenceController.java b/src/com/android/settings/privacy/CameraExtensionsFallbackPreferenceController.java
index 1d9c3543b9d..aa4d83ccb74 100644
--- a/src/com/android/settings/privacy/CameraExtensionsFallbackPreferenceController.java
+++ b/src/com/android/settings/privacy/CameraExtensionsFallbackPreferenceController.java
@@ -48,6 +48,14 @@ public boolean setChecked(boolean isChecked) {
 
     @Override
     public int getAvailabilityStatus() {
+        if (!com.android.internal.camera.flags.Flags.concertMode()) {
+            // this toggle is a no-op when concert_mode flag is off
+            return CONDITIONALLY_UNAVAILABLE;
+        }
+        if (mContext.getString(com.android.internal.R.string.config_extensionFallbackPackageName).isEmpty()) {
+            // this toggle is a no-op when there's no fallback camera extension package
+            return CONDITIONALLY_UNAVAILABLE;
+        }
         return AVAILABLE;
     }
 
diff --git a/src/com/android/settings/privatespace/HidePrivateSpaceController.java b/src/com/android/settings/privatespace/HidePrivateSpaceController.java
index 81814adc9db..f0c9e044031 100644
--- a/src/com/android/settings/privatespace/HidePrivateSpaceController.java
+++ b/src/com/android/settings/privatespace/HidePrivateSpaceController.java
@@ -63,9 +63,6 @@ public boolean setChecked(boolean isChecked) {
         mPrivateSpaceMaintainer.setHidePrivateSpaceEntryPointSetting(
                 isChecked ? HIDE_PRIVATE_SPACE_ENTRY_POINT_ENABLED_VAL
                         : HIDE_PRIVATE_SPACE_ENTRY_POINT_DISABLED_VAL);
-        if (isChecked) {
-            showAlertDialog();
-        }
         return true;
     }
 
@@ -73,16 +70,4 @@ public boolean setChecked(boolean isChecked) {
     public int getSliceHighlightMenuRes() {
         return 0;
     }
-
-    private void showAlertDialog() {
-        new AlertDialog.Builder(mContext)
-                .setTitle(R.string.private_space_hide_dialog_title)
-                .setMessage(R.string.private_space_hide_dialog_message)
-                .setPositiveButton(
-                        R.string.private_space_hide_dialog_button,
-                        (DialogInterface dialog, int which) -> {
-                            dialog.dismiss();
-                        })
-                .show();
-    }
 }
diff --git a/src/com/android/settings/privatespace/HidePrivateSpaceSettings.java b/src/com/android/settings/privatespace/HidePrivateSpaceSettings.java
index 0c24db5e6ed..c6abf822575 100644
--- a/src/com/android/settings/privatespace/HidePrivateSpaceSettings.java
+++ b/src/com/android/settings/privatespace/HidePrivateSpaceSettings.java
@@ -35,8 +35,6 @@
 public class HidePrivateSpaceSettings extends DashboardFragment {
     private static final String TAG = "HidePrivateSpaceSettings";
     private static final int IMPORTANT_FOR_ACCESSIBILITY_ITEM_COUNT = 5;
-    private static final String PRIVATE_SPACE_HIDE_ILLUSTRATION_KEY =
-            "private_space_hide_illustration";
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -85,9 +83,6 @@ public void onStart() {
     @Override
     public void onResume() {
         super.onResume();
-        final IllustrationPreference illustrationPreference =
-                getPreferenceScreen().findPreference(PRIVATE_SPACE_HIDE_ILLUSTRATION_KEY);
-        illustrationPreference.applyDynamicColor();
     }
 
     @Override
diff --git a/src/com/android/settings/safetycenter/ExploitProtectionFragment.java b/src/com/android/settings/safetycenter/ExploitProtectionFragment.java
new file mode 100644
index 00000000000..2542012590b
--- /dev/null
+++ b/src/com/android/settings/safetycenter/ExploitProtectionFragment.java
@@ -0,0 +1,29 @@
+package com.android.settings.safetycenter;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+@SearchIndexable
+public class ExploitProtectionFragment extends DashboardFragment {
+    private static final String TAG = "ExploitProtFragment";
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.exploit_protection_settings;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return METRICS_CATEGORY_UNKNOWN;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider(R.xml.exploit_protection_settings);
+}
diff --git a/src/com/android/settings/security/AutoRebootPrefController.java b/src/com/android/settings/security/AutoRebootPrefController.java
new file mode 100644
index 00000000000..9c00e954e96
--- /dev/null
+++ b/src/com/android/settings/security/AutoRebootPrefController.java
@@ -0,0 +1,49 @@
+package com.android.settings.security;
+
+import android.content.Context;
+import android.ext.settings.ExtSettings;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.ext.IntSettingPrefController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+import static java.util.concurrent.TimeUnit.DAYS;
+import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.MINUTES;
+
+public class AutoRebootPrefController extends IntSettingPrefController {
+
+    public AutoRebootPrefController(Context ctx, String key) {
+        super(ctx, key, ExtSettings.AUTO_REBOOT_TIMEOUT);
+    }
+
+    @Override
+    public void addPrefsBeforeList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+        addFooterPreference(screen, R.string.auto_reboot_footer,
+                "https://grapheneos.org/features#auto-reboot");
+    }
+
+    @Override
+    protected void getEntries(Entries entries) {
+        entries.add(R.string.switch_off_text, 0);
+        entries.add(3, DAYS);
+        entries.add(2, DAYS);
+        entries.add(36, HOURS);
+        entries.add(1, DAYS);
+        entries.add(18, HOURS);
+        entries.add(12, HOURS);
+        entries.add(8, HOURS);
+        entries.add(4, HOURS);
+        entries.add(2, HOURS);
+        entries.add(1, HOURS);
+        entries.add(30, MINUTES);
+        entries.add(10, MINUTES);
+    }
+
+    @Override
+    protected boolean isCredentialConfirmationRequired() {
+        return true;
+    }
+}
diff --git a/src/com/android/settings/security/DenyNewUsbPrefController.java b/src/com/android/settings/security/DenyNewUsbPrefController.java
new file mode 100644
index 00000000000..26d9ea0788a
--- /dev/null
+++ b/src/com/android/settings/security/DenyNewUsbPrefController.java
@@ -0,0 +1,88 @@
+package com.android.settings.security;
+
+import android.content.Context;
+import android.ext.settings.DenyNewUsbSetting;
+import android.os.SystemProperties;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.ext.AbstractListPreferenceController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static com.android.settings.ext.ExtSettingControllerHelper.getGlobalSettingAvailability;
+
+public class DenyNewUsbPrefController extends AbstractListPreferenceController {
+
+    private final List<String> list = Arrays.asList(
+            DenyNewUsbSetting.DISABLED,
+            DenyNewUsbSetting.DYNAMIC,
+            DenyNewUsbSetting.ENABLED
+    );
+
+    private final boolean isUsbPortSecuritySupported;
+
+    public DenyNewUsbPrefController(Context ctx, String key) {
+        super(ctx, key);
+
+        isUsbPortSecuritySupported = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_usbPortSecuritySupported);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (isUsbPortSecuritySupported) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
+
+        return getGlobalSettingAvailability(mContext);
+    }
+
+    @Override
+    protected void getEntries(Entries entries) {
+        entries.add(R.string.deny_new_usb_val_enabled, list.indexOf(DenyNewUsbSetting.ENABLED));
+        entries.add(R.string.deny_new_usb_val_dynamic, list.indexOf(DenyNewUsbSetting.DYNAMIC));
+        entries.add(R.string.deny_new_usb_val_disabled, list.indexOf(DenyNewUsbSetting.DISABLED));
+    }
+
+    @Override
+    public void addPrefsAfterList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+        addFooterPreference(screen, R.string.deny_new_usb_footer,
+                "https://grapheneos.org/usage#usb-peripherals");
+    }
+
+    @Override
+    protected int getCurrentValue() {
+        return list.indexOf(DenyNewUsbSetting.SYS_PROP.get());
+    }
+
+    @Override
+    protected boolean setValue(int val) {
+        String strVal = list.get(val);
+        boolean res = DenyNewUsbSetting.SYS_PROP.put(strVal);
+        if (!res) {
+            return false;
+        }
+        if (DenyNewUsbSetting.DYNAMIC.equals(strVal)) {
+            // when "dynamic" is written to the sysprop, the following hook is triggered in
+            // system/core/rootdir/init.rc :
+
+            // on property:persist.security.deny_new_usb=dynamic
+            // -    write /proc/sys/kernel/deny_new_usb 1
+
+            // But the fact that the setting was set by the user implies that the device is unlocked,
+            // and deny_new_usb should be disabled until the device gets locked
+            SystemProperties.set(DenyNewUsbSetting.TRANSIENT_PROP,
+                    DenyNewUsbSetting.TRANSIENT_DISABLE);
+        }
+        return true;
+    }
+
+    @Override
+    protected boolean isCredentialConfirmationRequired() {
+        return true;
+    }
+}
diff --git a/src/com/android/settings/security/DuressPasswordActivity.java b/src/com/android/settings/security/DuressPasswordActivity.java
new file mode 100644
index 00000000000..54a6cb89feb
--- /dev/null
+++ b/src/com/android/settings/security/DuressPasswordActivity.java
@@ -0,0 +1,71 @@
+package com.android.settings.security;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.SetupWizardUtils;
+import com.android.settings.overlay.FeatureFactory;
+import com.google.android.setupdesign.GlifLayout;
+import com.google.android.setupdesign.template.DescriptionMixin;
+import com.google.android.setupdesign.util.ThemeHelper;
+
+public class DuressPasswordActivity extends Activity {
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
+
+        setTheme(SetupWizardUtils.getTheme(this, getIntent()));
+        ThemeHelper.trySetDynamicColor(this);
+
+        setResult(RESULT_OK);
+    }
+
+    protected boolean allowNextOnStop;
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        if (!isChangingConfigurations() && hasUserCredential()) {
+            if (allowNextOnStop) {
+                allowNextOnStop = false;
+            } else {
+                // require user credential to be re-entered after activity is backgrounded
+                setResult(RESULT_CANCELED);
+                finish();
+            }
+        }
+    }
+
+    protected boolean hasUserCredential() {
+        return true;
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (!isChangingConfigurations()) {
+            /** @see com.android.settings.password.ConfirmDeviceCredentialBaseActivity#onDestroy */
+            getMainThreadHandler().postDelayed(() -> {
+                System.gc();
+                System.runFinalization();
+                System.gc();
+            }, 5000);
+        }
+    }
+
+    static void adjustDescriptionStyle(GlifLayout l) {
+        l.getMixin(DescriptionMixin.class).getTextView().setTextSize(16f);
+    }
+
+    LockPatternUtils getLockPatternUtils() {
+        return FeatureFactory.getFeatureFactory()
+                .getSecurityFeatureProvider()
+                .getLockPatternUtils(this);
+    }
+}
diff --git a/src/com/android/settings/security/DuressPasswordMainActivity.java b/src/com/android/settings/security/DuressPasswordMainActivity.java
new file mode 100644
index 00000000000..e99f38e43a7
--- /dev/null
+++ b/src/com/android/settings/security/DuressPasswordMainActivity.java
@@ -0,0 +1,182 @@
+package com.android.settings.security;
+
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
+import com.android.settings.R;
+import com.android.settings.password.ChooseLockSettingsHelper;
+import com.google.android.setupdesign.GlifRecyclerLayout;
+import com.google.android.setupdesign.items.IItem;
+import com.google.android.setupdesign.items.Item;
+import com.google.android.setupdesign.items.ItemGroup;
+import com.google.android.setupdesign.items.RecyclerItemAdapter;
+
+import java.util.Objects;
+
+import static java.util.Objects.requireNonNull;
+
+public class DuressPasswordMainActivity extends DuressPasswordActivity implements RecyclerItemAdapter.OnItemSelectedListener {
+    private static final String TAG = DuressPasswordMainActivity.class.getSimpleName();
+    private static final String KEY_USER_CREDENTIAL = "user_credential";
+    private static final String KEY_HAS_ASKED_FOR_USER_CREDENTIALS = "asked_for_user_credentials";
+
+    private GlifRecyclerLayout layout;
+    private LockscreenCredential userCredential;
+    private boolean askedForUserCredentials;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        var layout = new GlifRecyclerLayout(this);
+        this.layout = layout;
+        layout.setIcon(getDrawable(R.drawable.ic_lock));
+        layout.setHeaderText(R.string.duress_pwd_pref_title);
+        adjustDescriptionStyle(layout);
+        layout.setDescriptionText(R.string.duress_pwd_description);
+
+        setContentView(layout);
+
+        if (savedInstanceState != null) {
+            userCredential = savedInstanceState.getParcelable(KEY_USER_CREDENTIAL, LockscreenCredential.class);
+            askedForUserCredentials = requireNonNull(savedInstanceState.getBoolean2(KEY_HAS_ASKED_FOR_USER_CREDENTIALS));
+        }
+    }
+
+    @Override
+    protected boolean hasUserCredential() {
+        return userCredential != null && !userCredential.isNone();
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putParcelable(KEY_USER_CREDENTIAL, userCredential);
+        outState.putBoolean(KEY_HAS_ASKED_FOR_USER_CREDENTIALS, askedForUserCredentials);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        if (userCredential == null) {
+            if (!getLockPatternUtils().isSecure(getUserId())) {
+                userCredential = LockscreenCredential.createNone();
+            } else if (!askedForUserCredentials) {
+                var b = new ChooseLockSettingsHelper.Builder(this);
+                b.setRequestCode(REQ_CODE_OBTAIN_USER_CREDENTIALS);
+                b.setReturnCredentials(true);
+                b.setForegroundOnly(true);
+                b.show();
+                askedForUserCredentials = true;
+            }
+        }
+
+        updateActionList();
+    }
+
+    private void updateActionList() {
+        if (userCredential == null) {
+            Log.d(TAG, "no userCredential, skipping updateActionList");
+            return;
+        }
+
+        var g = new ItemGroup();
+
+        if (getLockPatternUtils().hasDuressCredentials(userCredential)) {
+            g.addChild(createItem(R.string.duress_pwd_action_update, R.drawable.ic_edit));
+            g.addChild(createItem(R.string.duress_pwd_action_delete, R.drawable.ic_delete));
+        } else {
+            g.addChild(createItem(R.string.duress_pwd_action_add, R.drawable.ic_add_24dp));
+        }
+
+        var adapter = new RecyclerItemAdapter(g);
+        adapter.setOnItemSelectedListener(this);
+        layout.setAdapter(adapter);
+    }
+
+    private Item createItem(@StringRes int title, @DrawableRes int icon) {
+        var i = new Item();
+        i.setId(title);
+        i.setTitle(getText(title));
+        i.setIcon(getDrawable(icon));
+        return i;
+    }
+
+    // RecyclerItemAdapter.OnItemSelectedListener
+    @Override
+    public void onItemSelected(IItem iitem) {
+        Item item = (Item) iitem;
+        int id = item.getId();
+
+        if (id == R.string.duress_pwd_action_add || id == R.string.duress_pwd_action_update) {
+            var i = new Intent(this, DuressPasswordSetupActivity.class);
+            i.putExtra(DuressPasswordSetupActivity.EXTRA_TITLE_TEXT, id);
+            i.putExtra(DuressPasswordSetupActivity.EXTRA_USER_CREDENTIAL, userCredential);
+            allowNextOnStop = true;
+            startActivityForResult(i, REQ_CODE_SETUP);
+        } else if (id == R.string.duress_pwd_action_delete) {
+            var b = new AlertDialog.Builder(this);
+            b.setMessage(R.string.duress_pwd_action_delete_confirmation);
+            b.setPositiveButton(R.string.duress_pwd_delete_button, (dialog, which) -> {
+                LockPatternUtils lpu = getLockPatternUtils();
+                try {
+                    lpu.deleteDuressCredentials(userCredential);
+                } catch (Exception e) {
+                    Log.e(TAG, "deleteDuressCredentials failed", e);
+
+                    var d = new AlertDialog.Builder(this);
+                    d.setMessage(getString(R.string.duress_pwd_delete_error, e.toString()));
+                    d.setNeutralButton(R.string.duress_pwd_error_dialog_dismiss, null);
+                    d.show();
+                    return;
+                }
+                updateActionList();
+            });
+            b.setNegativeButton(R.string.duress_pwd_cancel_button, null);
+            b.show();
+        }
+    }
+
+    static final int REQ_CODE_OBTAIN_USER_CREDENTIALS = 1;
+    static final int REQ_CODE_SETUP = 2;
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == REQ_CODE_SETUP) {
+            if (resultCode == RESULT_CANCELED) {
+                finish();
+            }
+            return;
+        }
+
+        if (requestCode != REQ_CODE_OBTAIN_USER_CREDENTIALS) {
+            throw new IllegalStateException(Integer.toString(resultCode));
+        }
+
+        Log.d(TAG, "onActivityResult, requestCode: " + requestCode + ", resultCode: " + resultCode);
+
+        if (resultCode != RESULT_OK) {
+            finish();
+            return;
+        }
+
+        if (data == null) {
+            throw new IllegalStateException("data == null");
+        }
+
+        var credential = data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, LockscreenCredential.class);
+        if (credential == null) {
+            throw new IllegalStateException("no returned credential");
+        }
+        userCredential = credential;
+    }
+}
diff --git a/src/com/android/settings/security/DuressPasswordSetupActivity.java b/src/com/android/settings/security/DuressPasswordSetupActivity.java
new file mode 100644
index 00000000000..9cedb11f872
--- /dev/null
+++ b/src/com/android/settings/security/DuressPasswordSetupActivity.java
@@ -0,0 +1,196 @@
+package com.android.settings.security;
+
+import android.app.AlertDialog;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.inputmethod.EditorInfo;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.annotation.IdRes;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
+import com.android.internal.widget.PasswordValidationError;
+import com.android.settings.R;
+import com.android.settings.password.ChooseLockPassword.ChooseLockPasswordFragment.PasswordValidationErrorConverter;
+import com.google.android.setupcompat.template.FooterBarMixin;
+import com.google.android.setupcompat.template.FooterButton;
+import com.google.android.setupdesign.GlifLayout;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
+
+public class DuressPasswordSetupActivity extends DuressPasswordActivity
+        implements TextView.OnEditorActionListener {
+    static final String TAG = DuressPasswordSetupActivity.class.getSimpleName();
+    static final String EXTRA_USER_CREDENTIAL = "user_credential";
+    static final String EXTRA_TITLE_TEXT = "title";
+    private boolean isUpdate;
+
+    enum DuressCredentialType {
+        PIN(LockscreenCredential::createPin,
+                R.id.pin_input, R.id.pin_input_confirmation,
+                R.string.lockpassword_confirm_pins_dont_match),
+        PASSWORD(LockscreenCredential::createPassword,
+                R.id.password_input, R.id.password_input_confirmation,
+                R.string.lockpassword_confirm_passwords_dont_match),
+        ;
+
+        final Function<String, LockscreenCredential> credenialCreator;
+        final @IdRes int mainInputId;
+        final @IdRes int confirmationInputId;
+        final @StringRes int confirmationMismatchText;
+
+        DuressCredentialType(Function<String, LockscreenCredential> credenialCreator,
+                             int mainInputId, int confirmationInputId,
+                             int confirmationMismatchText) {
+            this.credenialCreator = credenialCreator;
+            this.mainInputId = mainInputId;
+            this.confirmationInputId = confirmationInputId;
+            this.confirmationMismatchText = confirmationMismatchText;
+        }
+
+        LockscreenCredential createCredential(DuressPasswordSetupActivity activity) {
+            EditText ed = activity.requireViewById(mainInputId);
+            return credenialCreator.apply(ed.getText().toString());
+        }
+    }
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.duress_password_setup);
+
+        GlifLayout layout = requireViewById(R.id.glif_layout);
+        int headerText = getIntent().getExtras().getNumber(EXTRA_TITLE_TEXT);
+        isUpdate = headerText == R.string.duress_pwd_action_update;
+        layout.setHeaderText(headerText);
+        adjustDescriptionStyle(layout);
+
+        FooterBarMixin footerBar = layout.getMixin(FooterBarMixin.class);
+        {
+            var b = new FooterButton.Builder(this);
+            b.setText(isUpdate ? R.string.duress_pwd_update_button : R.string.duress_pwd_add_button);
+            b.setButtonType(FooterButton.ButtonType.DONE);
+            b.setListener(v -> save());
+            b.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary);
+            footerBar.setPrimaryButton(b.build());
+        }
+        {
+            var b = new FooterButton.Builder(this);
+            b.setText(R.string.duress_pwd_cancel_button);
+            b.setButtonType(FooterButton.ButtonType.CANCEL);
+            b.setListener(v -> finish());
+            b.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary);
+            footerBar.setSecondaryButton(b.build());
+        }
+        for (var ct : DuressCredentialType.values()) {
+            for (int id : new int[] { ct.mainInputId, ct.confirmationInputId }) {
+                EditText ed = requireViewById(id);
+                ed.setTag(ct);
+                ed.setOnEditorActionListener(this);
+            }
+        }
+    }
+
+    // TextView.OnEditorActionListener
+    @Override
+    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+        if ((actionId != EditorInfo.IME_ACTION_NEXT && actionId != EditorInfo.IME_ACTION_DONE)) {
+            return false;
+        }
+
+        EditText ed = (EditText) v;
+        DuressCredentialType ct = (DuressCredentialType) ed.getTag();
+        int id = v.getId();
+
+        if (id == ct.mainInputId) {
+            return !checkCredentialInputErrors(ct);
+        }
+        if (id == ct.confirmationInputId) {
+            return !checkCredentialConfirmationError(ct);
+        }
+        return false;
+    }
+
+    private void save() {
+        boolean credentialCheckRes = true;
+        for (DuressCredentialType ct : DuressCredentialType.values()) {
+            credentialCheckRes &= checkCredentialInputErrors(ct);
+            credentialCheckRes &= checkCredentialConfirmationError(ct);
+        }
+        if (!credentialCheckRes) {
+            return;
+        }
+
+        var userCredential = getIntent().getParcelableExtra(EXTRA_USER_CREDENTIAL, LockscreenCredential.class);
+        Objects.requireNonNull(userCredential, EXTRA_USER_CREDENTIAL);
+        LockscreenCredential pin = DuressCredentialType.PIN.createCredential(this);
+        LockscreenCredential password = DuressCredentialType.PASSWORD.createCredential(this);
+        LockPatternUtils lockPatternUtils = getLockPatternUtils();
+
+        Runnable save = () -> {
+            try {
+                lockPatternUtils.setDuressCredentials(userCredential, pin, password);
+            } catch (Exception e) {
+                Log.e(TAG, "setDuressCredentials failed", e);
+
+                var d = new AlertDialog.Builder(this);
+                d.setMessage(getString(R.string.duress_pwd_save_error, e.toString()));
+                d.setNeutralButton(R.string.duress_pwd_error_dialog_dismiss, null);
+                d.show();
+                return;
+            }
+            Toast.makeText(this,
+                    isUpdate ? R.string.duress_pwd_toast_updated : R.string.duress_pwd_toast_added,
+                    Toast.LENGTH_LONG).show();
+            finish();
+        };
+
+        if (isUpdate) {
+            save.run();
+        } else {
+            var warning = new AlertDialog.Builder(this);
+            warning.setTitle(R.string.duress_pwd_save_warning_title);
+            warning.setMessage(R.string.duress_pwd_save_warning_text);
+            warning.setNegativeButton(R.string.duress_pwd_cancel_button, null);
+            warning.setPositiveButton(R.string.duress_pwd_proceed_button, (d, w) -> {
+                save.run();
+            });
+            warning.show();
+        }
+    }
+
+    private boolean checkCredentialInputErrors(DuressCredentialType ct) {
+        EditText ed = requireViewById(ct.mainInputId);
+        String text = ed.getText().toString();
+        LockscreenCredential c = ct.credenialCreator.apply(text);
+
+        List<PasswordValidationError> errors = LockPatternUtils.validateDuressCredential(c);
+        String error = null;
+        boolean res = true;
+        if (!errors.isEmpty()) {
+            res = false;
+            var pvec = new PasswordValidationErrorConverter(this, c.isPassword(), errors);
+            error = String.join("\n", pvec.convertErrorCodeToMessages());
+        }
+        ed.setError(error);
+        return res;
+    }
+
+    private boolean checkCredentialConfirmationError(DuressCredentialType ct) {
+        EditText main = requireViewById(ct.mainInputId);
+        EditText confirmation = requireViewById(ct.confirmationInputId);
+
+        boolean res = main.getText().toString().equals(confirmation.getText().toString());
+        confirmation.setError(res ? null : getText(ct.confirmationMismatchText));
+        return res;
+    }
+}
diff --git a/src/com/android/settings/security/ExecSpawningFragment.java b/src/com/android/settings/security/ExecSpawningFragment.java
new file mode 100644
index 00000000000..1ab1f744617
--- /dev/null
+++ b/src/com/android/settings/security/ExecSpawningFragment.java
@@ -0,0 +1,34 @@
+package com.android.settings.security;
+
+import android.ext.settings.BoolSetting;
+import android.ext.settings.ExtSettings;
+import android.net.Uri;
+
+import com.android.settings.R;
+import com.android.settings.ext.BoolSettingFragment;
+import com.android.settingslib.widget.FooterPreference;
+
+public class ExecSpawningFragment extends BoolSettingFragment {
+
+    @Override
+    protected BoolSetting getSetting() {
+        return ExtSettings.EXEC_SPAWNING;
+    }
+
+    @Override
+    protected CharSequence getTitle() {
+        return getText(R.string.exec_spawning_title);
+    }
+
+    @Override
+    protected CharSequence getMainSwitchTitle() {
+        return getText(R.string.exec_spawning_title_inner);
+    }
+
+    @Override
+    protected FooterPreference makeFooterPref(FooterPreference.Builder builder) {
+        FooterPreference p = builder.setTitle(R.string.exec_spawning_footer).build();
+        setFooterPrefLearnMoreUri(p, Uri.parse("https://grapheneos.org/usage#exec-spawning"));
+        return p;
+    }
+}
diff --git a/src/com/android/settings/security/ExecSpawningPrefController.java b/src/com/android/settings/security/ExecSpawningPrefController.java
new file mode 100644
index 00000000000..cd2be5cfc71
--- /dev/null
+++ b/src/com/android/settings/security/ExecSpawningPrefController.java
@@ -0,0 +1,13 @@
+package com.android.settings.security;
+
+import android.content.Context;
+import android.ext.settings.ExtSettings;
+
+import com.android.settings.ext.BoolSettingFragmentPrefController;
+
+public class ExecSpawningPrefController extends BoolSettingFragmentPrefController {
+
+    public ExecSpawningPrefController(Context ctx, String key) {
+        super(ctx, key, ExtSettings.EXEC_SPAWNING);
+    }
+}
diff --git a/src/com/android/settings/security/UsbPortSecurityPrefController.java b/src/com/android/settings/security/UsbPortSecurityPrefController.java
new file mode 100644
index 00000000000..ddea6316299
--- /dev/null
+++ b/src/com/android/settings/security/UsbPortSecurityPrefController.java
@@ -0,0 +1,141 @@
+package com.android.settings.security;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.ext.settings.UsbPortSecurity;
+import android.hardware.usb.UsbManager;
+import android.hardware.usb.ext.PortSecurityState;
+import android.os.Bundle;
+import android.os.ResultReceiver;
+
+import androidx.preference.Preference;
+
+import com.android.internal.infra.AndroidFuture;
+import com.android.settings.R;
+import com.android.settings.ext.IntSettingPrefController;
+
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+import static java.util.Objects.requireNonNull;
+
+public class UsbPortSecurityPrefController extends IntSettingPrefController {
+    private final boolean appliesToPogoPins;
+
+    public UsbPortSecurityPrefController(Context ctx, String key) {
+        super(ctx, key, UsbPortSecurity.MODE_SETTING);
+
+        appliesToPogoPins = ctx.getResources().getBoolean(
+                com.android.internal.R.bool.config_usb_port_security_applies_to_pogo_pins);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        String prefKey = getPreferenceKey();
+        if (appliesToPogoPins) {
+            if ("usbc_port".equals(prefKey)) {
+                return UNSUPPORTED_ON_DEVICE;
+            }
+        } else {
+            if ("usbc_port_and_pogo_pins".equals(prefKey)) {
+                return UNSUPPORTED_ON_DEVICE;
+            }
+        }
+
+        int res = super.getAvailabilityStatus();
+        if (res == AVAILABLE) {
+            int config = com.android.internal.R.bool.config_usbPortSecuritySupported;
+            if (!mContext.getResources().getBoolean(config)) {
+                res = UNSUPPORTED_ON_DEVICE;
+            }
+        }
+        return res;
+    }
+
+    @Override
+    protected void getEntries(Entries entries) {
+        boolean pogo = appliesToPogoPins;
+
+        Resources res = mContext.getResources();
+        entries.add(pogo ? R.string.usbc_port_and_pogo_pins_off_title : R.string.usbc_port_off_title,
+                pogo ? R.string.usbc_port_and_pogo_pins_off_summary : R.string.usbc_port_off_summary,
+                UsbPortSecurity.MODE_DISABLED);
+        entries.add(R.string.usbc_port_charging_only_title,
+                pogo ? R.string.usbc_port_and_pogo_pins_charging_only_summary : R.string.usbc_port_charging_only_summary,
+                UsbPortSecurity.MODE_CHARGING_ONLY);
+
+        String title = res.getString(R.string.usbc_port_charging_only_when_locked_title);
+        CharSequence summary = res.getText(pogo ?
+                R.string.usbc_port_and_pogo_pins_charging_only_when_locked_summary :
+                R.string.usbc_port_charging_only_when_locked_summary);
+        entries.add(title, summary,
+                UsbPortSecurity.MODE_CHARGING_ONLY_WHEN_LOCKED);
+
+        CharSequence titleAfu = res.getText(R.string.usbc_port_charging_only_when_locked_afu_title);
+        String summaryAfu = res.getString(R.string.usbc_port_charging_only_when_locked_afu_summary, title);
+        entries.add(titleAfu, summaryAfu,
+                UsbPortSecurity.MODE_CHARGING_ONLY_WHEN_LOCKED_AFU);
+
+        entries.add(R.string.usbc_port_on_title, R.string.usbc_port_on_summary,
+                UsbPortSecurity.MODE_ENABLED);
+    }
+
+    private static void setSecurityStateForAllPortsSync(UsbManager usbManager, int state) {
+        var future = new AndroidFuture<>();
+        usbManager.setSecurityStateForAllPorts(state, new ResultReceiver(null) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                if (resultCode != android.hardware.usb.ext.IUsbExt.NO_ERROR) {
+                    String msg = "setPortSecurityState failed, " +
+                            "resultCode: " + resultCode;
+                    if (resultData != null) {
+                        msg += ", resultData: " + resultData.toStringDeep();
+                    }
+                    throw new RuntimeException(msg);
+                }
+                future.complete(null);
+            }
+        });
+        try {
+            future.get(3, TimeUnit.SECONDS);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void setState(int prevSetting, @android.hardware.usb.ext.PortSecurityState int state) {
+        var usbManager = requireNonNull(mContext.getSystemService(UsbManager.class));
+        if (prevSetting == UsbPortSecurity.MODE_CHARGING_ONLY && state >= UsbPortSecurity.MODE_CHARGING_ONLY_WHEN_LOCKED) {
+            // Turn USB ports off first to trigger reconnection of devices that were connected
+            // in charging-only state. Simply enabling the data path is not enough in some
+            // advanced scenarios, e.g. when port alt mode or port role switching are used.
+            setSecurityStateForAllPortsSync(usbManager, PortSecurityState.DISABLED);
+        }
+        setSecurityStateForAllPortsSync(usbManager, state);
+    }
+
+    @Override
+    protected boolean setValue(int val) {
+        int prevSetting = getCurrentValue();
+        boolean res = super.setValue(val);
+        if (!res) {
+            return false;
+        }
+
+        int pss = switch (val) {
+            case UsbPortSecurity.MODE_DISABLED -> PortSecurityState.DISABLED;
+            case UsbPortSecurity.MODE_CHARGING_ONLY -> PortSecurityState.CHARGING_ONLY_IMMEDIATE;
+            case UsbPortSecurity.MODE_CHARGING_ONLY_WHEN_LOCKED -> PortSecurityState.ENABLED;
+            case UsbPortSecurity.MODE_CHARGING_ONLY_WHEN_LOCKED_AFU -> PortSecurityState.ENABLED;
+            case UsbPortSecurity.MODE_ENABLED -> PortSecurityState.ENABLED;
+            default -> throw new IllegalArgumentException(Integer.toString(val));
+        };
+        setState(prevSetting, pss);
+        return true;
+    }
+
+    @Override
+    protected boolean isCredentialConfirmationRequired() {
+        return true;
+    }
+}
diff --git a/src/com/android/settings/security/screenlock/PinScramblingPrefController.java b/src/com/android/settings/security/screenlock/PinScramblingPrefController.java
new file mode 100644
index 00000000000..855366be5ea
--- /dev/null
+++ b/src/com/android/settings/security/screenlock/PinScramblingPrefController.java
@@ -0,0 +1,33 @@
+package com.android.settings.security.screenlock;
+
+import android.content.Context;
+import android.ext.settings.ExtSettings;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.ext.BoolSettingPrefController;
+import com.android.settings.overlay.FeatureFactory;
+
+public class PinScramblingPrefController extends BoolSettingPrefController {
+
+    private final LockPatternUtils lockPatternUtils;
+
+    public PinScramblingPrefController(Context ctx, String key) {
+        super(ctx, key, ExtSettings.SCRAMBLE_LOCKSCREEN_PIN_LAYOUT);
+
+        lockPatternUtils = FeatureFactory.getFeatureFactory()
+                .getSecurityFeatureProvider()
+                .getLockPatternUtils(ctx);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        int res = super.getAvailabilityStatus();
+        if (res == AVAILABLE) {
+            if (lockPatternUtils.getCredentialTypeForUser(mContext.getUserId())
+                    != LockPatternUtils.CREDENTIAL_TYPE_PIN) {
+                return CONDITIONALLY_UNAVAILABLE;
+            }
+        }
+        return res;
+    }
+}
diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
index 8b481797907..e7362ebdfcb 100644
--- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt
+++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
@@ -100,6 +100,13 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) {
     open fun settingsPageProviders() = listOf(
         HomePageProvider,
         AppsMainPageProvider,
+        com.android.settings.applications.AswAdapterUseHardenedMalloc.makeAppListPageProvider(),
+        com.android.settings.applications.AswAdapterUseMemoryTagging.makeAppListPageProvider(),
+        com.android.settings.applications.AswAdapterUseExtendedVaSpace.makeAppListPageProvider(),
+        com.android.settings.applications.AswAdapterNativeDebugging.makeAppListPageProvider(),
+        com.android.settings.applications.AswAdapterWebViewDynCodeLoading.makeAppListPageProvider(),
+        com.android.settings.applications.AswAdapterMemoryDynCodeLoading.makeAppListPageProvider(),
+        com.android.settings.applications.AswAdapterStorageDynCodeLoading.makeAppListPageProvider(),
         AllAppListPageProvider,
         AppInfoSettingsProvider,
         SpecialAppAccessPageProvider,
diff --git a/src/com/android/settings/spa/app/AppUtil.kt b/src/com/android/settings/spa/app/AppUtil.kt
index 64da61380f5..7b319aeddeb 100644
--- a/src/com/android/settings/spa/app/AppUtil.kt
+++ b/src/com/android/settings/spa/app/AppUtil.kt
@@ -37,6 +37,7 @@ fun Context.startUninstallActivity(
 
     val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri).apply {
         putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, forAllUsers)
+        putExtra(Intent.EXTRA_UNINSTALL_SHOW_MORE_OPTIONS_BUTTON, false)
     }
     startActivityAsUser(intent, userHandle)
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/spa/app/appinfo/AppContactScopesPreference.kt b/src/com/android/settings/spa/app/appinfo/AppContactScopesPreference.kt
new file mode 100644
index 00000000000..e898f4e9086
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AppContactScopesPreference.kt
@@ -0,0 +1,31 @@
+package com.android.settings.spa.app.appinfo
+
+import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import android.ext.cscopes.ContactScopesApi
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spaprivileged.model.app.userHandle
+import com.android.settingslib.spaprivileged.model.app.userId
+
+@Composable
+fun AppContactScopesPreference(app: ApplicationInfo) {
+    val pkgName = app.packageName
+    if (GosPackageState.get(pkgName, app.userId)?.hasFlags(GosPackageState.FLAG_CONTACT_SCOPES_ENABLED) != true) {
+        return
+    }
+
+    val context = LocalContext.current
+
+    Preference(object : PreferenceModel {
+        override val title = stringResource(R.string.contact_scopes)
+        override val onClick = {
+            val intent = ContactScopesApi.createConfigActivityIntent(pkgName)
+            context.startActivityAsUser(intent, app.userHandle)
+        }
+    })
+}
diff --git a/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt b/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt
index 555e9f14c61..07d583cde30 100644
--- a/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppDisableButton.kt
@@ -31,6 +31,7 @@ import com.android.settingslib.spa.widget.dialog.AlertDialogButton
 import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
 import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
 import com.android.settingslib.spaprivileged.framework.common.userManager
+import com.android.settingslib.spaprivileged.model.app.installed
 import com.android.settingslib.spaprivileged.model.app.isDisabledUntilUsed
 import com.android.settingslib.Utils as SettingsLibUtils
 
@@ -47,7 +48,7 @@ class AppDisableButton(
 
     @Composable
     fun getActionButton(app: ApplicationInfo): ActionButton? {
-        if (!app.isSystemApp) return null
+        if (!app.installed) return null
 
         return when {
             app.enabled && !app.isDisabledUntilUsed -> {
@@ -62,6 +63,8 @@ class AppDisableButton(
      * Gets whether a package can be disabled.
      */
     private fun ApplicationInfo.canBeDisabled(): Boolean = when {
+        !isSystemApp -> appButtonRepository.isAllowUninstallOrArchive(context, this)
+
         // Try to prevent the user from bricking their phone by not allowing disabling of apps
         // signed with the system certificate.
         isSignedWithPlatformKey -> false
@@ -98,7 +101,12 @@ class AppDisableButton(
             // Currently we apply the same device policy for both the uninstallation and disable
             // button.
             if (!appButtonRepository.isUninstallBlockedByAdmin(app)) {
-                dialogPresenter.open()
+                if (app.isSystemApp) {
+                    dialogPresenter.open()
+                } else {
+                    packageInfoPresenter.disable()
+                }
+
             }
         }
     }
diff --git a/src/com/android/settings/spa/app/appinfo/AppExploitProtectionCompatModeSwitchPreference.kt b/src/com/android/settings/spa/app/appinfo/AppExploitProtectionCompatModeSwitchPreference.kt
new file mode 100644
index 00000000000..d7a8b482f3f
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AppExploitProtectionCompatModeSwitchPreference.kt
@@ -0,0 +1,58 @@
+package com.android.settings.spa.app.appinfo
+
+import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settings.applications.AswExploitProtectionFragment
+import com.android.settingslib.spa.widget.preference.SwitchPreference
+import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
+import com.android.settingslib.spaprivileged.model.app.installed
+import com.android.settingslib.spaprivileged.model.app.userId
+
+@Composable
+fun AppExploitProtectionCompatModeSwitchPreference(app: ApplicationInfo,
+                                                   packageInfoPresenter: PackageInfoPresenter) {
+    if (app.isSystemApp || !app.installed) {
+        return
+    }
+
+    val context = LocalContext.current
+    val pkgName = app.packageName
+    val userId = app.userId
+    val psFlag = GosPackageState.FLAG_ENABLE_EXPLOIT_PROTECTION_COMPAT_MODE
+
+    SwitchPreference(object : SwitchPreferenceModel {
+        override val title = stringResource(R.string.aep_compat_mode_title)
+        override val summary = {
+            context.getString(R.string.aep_compat_mode_summary)
+        }
+
+        override val checked = {
+            GosPackageState.get(pkgName, userId)?.hasFlag(psFlag) == true
+        }
+
+        override val onCheckedChange = { newChecked: Boolean ->
+            val action = Runnable {
+                GosPackageState.edit(pkgName, userId).run {
+                    setFlagsState(psFlag, newChecked)
+                    killUidAfterApply()
+                    if (apply()) {
+                        // needed to recompose other exploit protection settings
+                        check(packageInfoPresenter.manualRefreshFlow.tryEmit(Any()))
+                    }
+                }
+            }
+
+            if (newChecked) {
+                val d = AswExploitProtectionFragment.getExploitProtectionWarningOnDisable(context, action)
+                d.show()
+            } else {
+                action.run()
+            }
+            Unit
+        }
+    })
+}
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index fa9cee2c899..cae60026a5b 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -43,6 +43,7 @@ import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider
 import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListProvider
 import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.LifecycleEffect
 import com.android.settingslib.spa.framework.compose.navigator
 import com.android.settingslib.spa.widget.scaffold.RegularScaffold
 import com.android.settingslib.spa.widget.ui.Category
@@ -120,6 +121,8 @@ object AppInfoSettingsProvider : SettingsPageProvider {
 
 @Composable
 private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
+    // needed to refresh AppSwitch items after returning from their fragments
+    LifecycleEffect(onStart = { check(packageInfoPresenter.manualRefreshFlow.tryEmit(Any())) })
     val packageInfoState = packageInfoPresenter.flow.collectAsStateWithLifecycle()
     val featureFlags: PmFeatureFlags = PmFeatureFlagsImpl()
     RegularScaffold(
@@ -144,6 +147,8 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
         AppAllServicesPreference(app)
         AppNotificationPreference(app)
         AppPermissionPreference(app)
+        AppStorageScopesPreference(app)
+        AppContactScopesPreference(app)
         AppStoragePreference(app)
         InstantAppDomainsPreference(app)
         AppDataUsagePreference(app)
@@ -152,6 +157,7 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
         AppLocalePreference(app)
         AppOpenByDefaultPreference(app)
         DefaultAppShortcuts(app)
+        AppLogcatPreference(app)
 
         Category(title = stringResource(R.string.unused_apps_category)) {
             HibernationSwitchPreference(app, isHibernationSwitchEnabledStateFlow)
@@ -167,6 +173,17 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
             AlarmsAndRemindersAppListProvider.InfoPageEntryItem(app)
         }
 
+        Category(title = stringResource(R.string.exploit_protection_category_title)) {
+            AppExploitProtectionCompatModeSwitchPreference(app, packageInfoPresenter)
+            com.android.settings.applications.AppHardenedMallocPreference(app)
+            com.android.settings.applications.AppMemtagPreference(app)
+            com.android.settings.applications.AppExtendedVaSpacePreference(app)
+            com.android.settings.applications.AppNativeDebuggingPreference(app)
+            com.android.settings.applications.AppWebViewDynCodeLoadingPreference(app)
+            com.android.settings.applications.AppMemoryDynCodeLoadingPreference(app)
+            com.android.settings.applications.AppStorageDynCodeLoadingPreference(app)
+        }
+
         Category(title = stringResource(R.string.app_install_details_group_title)) {
             AppInstallerInfoPreference(app)
         }
@@ -175,4 +192,4 @@ private fun AppInfoSettings(packageInfoPresenter: PackageInfoPresenter) {
 }
 
 fun isArchivingEnabled(featureFlags: PmFeatureFlags) =
-        featureFlags.archiving() || Flags.appArchiving()
\ No newline at end of file
+        featureFlags.archiving() || Flags.appArchiving()
diff --git a/src/com/android/settings/spa/app/appinfo/AppLogcatPreference.kt b/src/com/android/settings/spa/app/appinfo/AppLogcatPreference.kt
new file mode 100644
index 00000000000..14e3c60b5e1
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AppLogcatPreference.kt
@@ -0,0 +1,29 @@
+package com.android.settings.spa.app.appinfo
+
+import android.content.pm.ApplicationInfo
+import android.ext.LogViewerApp
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spaprivileged.model.app.installed
+import com.android.settingslib.spaprivileged.model.app.userHandle
+
+@Composable
+fun AppLogcatPreference(app: ApplicationInfo) {
+    if (!app.installed) {
+        return
+    }
+
+    val context = LocalContext.current
+
+    Preference(object : PreferenceModel {
+        override val title = stringResource(R.string.view_logs)
+        override val onClick = {
+            val intent = LogViewerApp.getPackageLogcatIntent(app.packageName)
+            context.startActivityAsUser(intent, app.userHandle)
+        }
+    })
+}
diff --git a/src/com/android/settings/spa/app/appinfo/AppStorageScopesPreference.kt b/src/com/android/settings/spa/app/appinfo/AppStorageScopesPreference.kt
new file mode 100644
index 00000000000..5f759248a89
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AppStorageScopesPreference.kt
@@ -0,0 +1,31 @@
+package com.android.settings.spa.app.appinfo
+
+import android.app.StorageScope
+import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spaprivileged.model.app.userHandle
+import com.android.settingslib.spaprivileged.model.app.userId
+
+@Composable
+fun AppStorageScopesPreference(app: ApplicationInfo) {
+    val pkgName = app.packageName
+    if (GosPackageState.get(pkgName, app.userId)?.hasFlags(GosPackageState.FLAG_STORAGE_SCOPES_ENABLED) != true) {
+        return
+    }
+
+    val context = LocalContext.current
+
+    Preference(object : PreferenceModel {
+        override val title = stringResource(R.string.storage_scopes)
+        override val onClick = {
+            val intent = StorageScope.createConfigActivityIntent(pkgName)
+            context.startActivityAsUser(intent, app.userHandle)
+        }
+    })
+}
diff --git a/src/com/android/settings/spa/app/appinfo/AswAppList.kt b/src/com/android/settings/spa/app/appinfo/AswAppList.kt
new file mode 100644
index 00000000000..e69f7f36803
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AswAppList.kt
@@ -0,0 +1,96 @@
+package com.android.settings.spa.app.appinfo
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import android.os.Bundle
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import com.android.settings.applications.AswAdapter
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.rememberContext
+import com.android.settingslib.spa.framework.util.asyncFilter
+import com.android.settingslib.spa.framework.util.asyncMap
+import com.android.settingslib.spa.widget.ui.SpinnerOption
+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 com.android.settingslib.spaprivileged.template.app.AppListPage
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+
+open class AswAppListPageProvider(val adapter: AswAdapter<*>) : SettingsPageProvider {
+    override val name = adapter.getAppListPageProviderName()
+
+    @Composable
+    override fun Page(arguments: Bundle?) {
+        AswAppListPage(adapter)
+    }
+}
+
+@Composable
+fun AswAppListPage(adapter: AswAdapter<*>) {
+    AppListPage(
+        title = rememberContext { ctx ->
+            adapter.getShortAswTitle(ctx).toString()
+        },
+        listModel = rememberContext { ctx ->
+            AswAppListModel(ctx, adapter)
+        },
+    )
+}
+
+class AppRecordImpl(override val app: ApplicationInfo, val gosPackageState: GosPackageState?) : AppRecord
+
+class AswAppListModel(val ctx: Context, val adapter: AswAdapter<*>) : AppListModel<AppRecordImpl> {
+    companion object {
+        const val SPINNER_OPTION_OFF = 0
+        const val SPINNER_OPTION_ON = 1
+    }
+
+    override fun getSpinnerOptions(recordList: List<AppRecordImpl>): List<SpinnerOption> {
+        val options = ArrayList<SpinnerOption>(2)
+        options.add(SpinnerOption(SPINNER_OPTION_OFF, adapter.getOffTitle(ctx).toString()))
+        options.add(SpinnerOption(SPINNER_OPTION_ON, adapter.getOnTitle(ctx).toString()))
+        return options
+    }
+
+    override fun transform(
+        userIdFlow: Flow<Int>,
+        appListFlow: Flow<List<ApplicationInfo>>
+    ): Flow<List<AppRecordImpl>> {
+        return userIdFlow.combine(appListFlow) { userId, appList ->
+            appList.asyncMap { app ->
+                AppRecordImpl(app, GosPackageState.get(app.packageName, userId))
+            }
+        }
+    }
+
+    override fun filter(
+        userIdFlow: Flow<Int>,
+        option: Int,
+        recordListFlow: Flow<List<AppRecordImpl>>
+    ): Flow<List<AppRecordImpl>> {
+        val appSwitch = adapter.getAppSwitch()
+        return userIdFlow.combine(recordListFlow) { userId, recordList ->
+            recordList.asyncFilter {
+                val value = appSwitch.get(ctx, userId, it.app, it.gosPackageState)
+                when (option) {
+                    SPINNER_OPTION_OFF -> !value
+                    SPINNER_OPTION_ON -> value
+                    else -> throw IllegalArgumentException(option.toString())
+                }
+            }
+        }
+    }
+
+    @Composable
+    override fun AppListItemModel<AppRecordImpl>.AppItem() {
+        val context = LocalContext.current
+        AppListItem(onClick = {
+            adapter.openAppPage(context, record.app)
+        })
+    }
+}
+
diff --git a/src/com/android/settings/spa/app/appinfo/AswPreference.kt b/src/com/android/settings/spa/app/appinfo/AswPreference.kt
new file mode 100644
index 00000000000..116fa047025
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AswPreference.kt
@@ -0,0 +1,27 @@
+package com.android.settings.spa.app.appinfo
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.ext.settings.app.AppSwitch
+import androidx.compose.runtime.Composable
+import com.android.settings.applications.AswAdapter
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spaprivileged.model.app.installed
+
+@Composable
+fun AswPreference(context: Context, app: ApplicationInfo, adapter: AswAdapter<out AppSwitch>) {
+    if (!app.installed) {
+        return
+    }
+
+    Preference(object : PreferenceModel {
+        override val title = adapter.getAswTitle(context).toString()
+        override val summary = {
+            adapter.getPreferenceSummary(context, app).toString()
+        }
+        override val onClick = {
+            adapter.openAppPage(context, app)
+        }
+    })
+}
diff --git a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt
index 8dbcb14e83b..02a0ffde6ad 100644
--- a/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt
+++ b/src/com/android/settings/spa/app/appinfo/PackageInfoPresenter.kt
@@ -42,6 +42,7 @@ import com.android.settingslib.spaprivileged.model.app.IPackageManagers
 import com.android.settingslib.spaprivileged.model.app.PackageManagers
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.filter
@@ -94,7 +95,9 @@ class PackageInfoPresenter(
         intent.action != Intent.ACTION_PACKAGE_REMOVED ||
             intent.getBooleanExtra(Intent.EXTRA_ARCHIVAL, false)
 
-    val flow: StateFlow<PackageInfo?> = merge(flowOf(null), appChangeFlow)
+    val manualRefreshFlow = MutableStateFlow<Any?>(null)
+
+    val flow: StateFlow<PackageInfo?> = merge(flowOf(null), appChangeFlow, manualRefreshFlow)
         .map { getPackageInfo() }
         .stateIn(coroutineScope + Dispatchers.Default, SharingStarted.Eagerly, null)
 
diff --git a/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt b/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt
index f6c08c0ca7c..6dba4817a2a 100644
--- a/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt
+++ b/src/com/android/settings/spa/app/specialaccess/AllFilesAccess.kt
@@ -18,11 +18,19 @@ package com.android.settings.spa.app.specialaccess
 
 import android.Manifest
 import android.app.AppOpsManager
+import android.app.StorageScope
 import android.app.settings.SettingsEnums
 import android.content.Context
+import android.content.pm.PackageInfo
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
 import com.android.settings.R
 import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
 import com.android.settingslib.spaprivileged.model.app.AppOps
+import com.android.settingslib.spaprivileged.model.app.userHandle
 import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel
 import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord
 import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
@@ -54,4 +62,18 @@ class AllFilesAccessListModel(context: Context) : AppOpPermissionListModel(conte
         }
         featureFactory.metricsFeatureProvider.action(context, category, "")
     }
+
+    @Composable
+    override fun extContent(record: AppOpPermissionRecord, pkgInfo: PackageInfo) {
+        val context = LocalContext.current
+
+        Preference(object : PreferenceModel {
+            override val title = stringResource(R.string.storage_scopes)
+            override val onClick = {
+                val app = record.app
+                val i = StorageScope.createConfigActivityIntent(app.packageName)
+                context.startActivityAsUser(i, app.userHandle)
+            }
+        })
+    }
 }
diff --git a/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt b/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt
index 06d5b488e73..af109d0313e 100644
--- a/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt
+++ b/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt
@@ -22,10 +22,17 @@ import android.app.AppOpsManager
 import android.app.AppOpsManager.MODE_DEFAULT
 import android.content.Context
 import android.content.pm.ApplicationInfo
+import android.content.pm.GosPackageState
+import android.content.pm.PackageInfo
 import android.os.UserManager
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
 import com.android.settings.R
 import com.android.settingslib.spa.lifecycle.collectAsCallbackWithLifecycle
+import com.android.settingslib.spa.widget.preference.SwitchPreference
+import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import com.android.settingslib.spaprivileged.model.app.AppOps
 import com.android.settingslib.spaprivileged.model.app.AppOpsController
 import com.android.settingslib.spaprivileged.model.app.AppRecord
@@ -44,7 +51,26 @@ object InstallUnknownAppsListProvider : TogglePermissionAppListProvider {
 data class InstallUnknownAppsRecord(
     override val app: ApplicationInfo,
     val appOpsController: AppOpsController,
-) : AppRecord
+) : AppRecord {
+    val isObbFlagSet = mutableStateOf(isObbFlagSet())
+
+    fun isObbFlagSet(): Boolean {
+        return GosPackageState.get(app.packageName, app.userId)?.hasFlag(GosPackageState.FLAG_ALLOW_ACCESS_TO_OBB_DIRECTORY) == true
+    }
+
+    fun setObbFlagState(state: Boolean): Boolean {
+        GosPackageState.edit(app.packageName, app.userId).run {
+            setFlagsState(GosPackageState.FLAG_ALLOW_ACCESS_TO_OBB_DIRECTORY, state)
+            killUidAfterApply()
+            if (apply()) {
+                isObbFlagSet.value = state
+                return true
+            } else {
+                return false
+            }
+        }
+    }
+}
 
 class InstallUnknownAppsListModel(private val context: Context) :
     TogglePermissionAppListModel<InstallUnknownAppsRecord> {
@@ -83,6 +109,29 @@ class InstallUnknownAppsListModel(private val context: Context) :
 
     override fun setAllowed(record: InstallUnknownAppsRecord, newAllowed: Boolean) {
         record.appOpsController.setAllowed(newAllowed)
+        if (!newAllowed) {
+            record.setObbFlagState(false)
+        }
+    }
+
+    @Composable
+    override fun extContent(record: InstallUnknownAppsRecord, pkgInfo: PackageInfo) {
+        val context = LocalContext.current
+
+        SwitchPreference(object : SwitchPreferenceModel {
+            override val title = stringResource(R.string.allow_access_to_obb_directory_title)
+            override val summary = {
+                context.getString(R.string.allow_access_to_obb_directory_summary)
+            }
+
+            override val checked = {
+                record.isObbFlagSet.value
+            }
+            override val onCheckedChange = { newChecked: Boolean ->
+                record.setObbFlagState(newChecked)
+                Unit
+            }
+        })
     }
 
     companion object {
diff --git a/src/com/android/settings/sudconfig/NonRelationalProvider.kt b/src/com/android/settings/sudconfig/NonRelationalProvider.kt
new file mode 100644
index 00000000000..5a77d8b1b3d
--- /dev/null
+++ b/src/com/android/settings/sudconfig/NonRelationalProvider.kt
@@ -0,0 +1,51 @@
+package com.android.settings.sudconfig
+
+import android.content.ContentProvider
+import android.content.ContentValues
+import android.database.Cursor
+import android.net.Uri
+
+/**
+ * Useful for implementing content provider interfaces that are exclusively for non-relational
+ * (non-tabular) models. This reduces the boilerplate code by providing empty implementations for
+ * methods which are unneeded in non-relational models.
+ *
+ * @see [ContentProvider.call]
+ */
+abstract class NonRelationalProvider : ContentProvider() {
+
+    final override fun query(
+        uri: Uri,
+        projection: Array<out String>?,
+        selection: String?,
+        selectionArgs: Array<out String>?,
+        sortOrder: String?
+    ): Cursor? {
+        throw UnsupportedOperationException()
+    }
+
+    final override fun getType(uri: Uri): String? {
+        throw UnsupportedOperationException()
+    }
+
+    final override fun insert(uri: Uri, values: ContentValues?): Uri? {
+        throw UnsupportedOperationException()
+    }
+
+    final override fun delete(
+        uri: Uri,
+        selection: String?,
+        selectionArgs: Array<out String>?
+    ): Int {
+        throw UnsupportedOperationException()
+    }
+
+    final override fun update(
+        uri: Uri,
+        values: ContentValues?,
+        selection: String?,
+        selectionArgs: Array<out String>?
+    ): Int {
+        throw UnsupportedOperationException()
+    }
+}
diff --git a/src/com/android/settings/sudconfig/SudConfigProvider.kt b/src/com/android/settings/sudconfig/SudConfigProvider.kt
new file mode 100644
index 00000000000..ae2b4926f1f
--- /dev/null
+++ b/src/com/android/settings/sudconfig/SudConfigProvider.kt
@@ -0,0 +1,84 @@
+package com.android.settings.sudconfig
+
+import android.os.Build
+import android.os.Bundle
+import android.provider.Settings
+import android.text.TextUtils
+import android.util.Log
+import com.android.settings.R;
+import java.util.Optional
+
+/**
+ * Provides system-wide config for setup wizard screens.
+ */
+class SudConfigProvider : NonRelationalProvider() {
+    companion object {
+        private const val TAG = "SudConfigProvider"
+
+        // resources to be forwarded via overlay config
+        private val overlayConfigResources = arrayOf(
+            R.dimen.setup_design_card_view_intrinsic_height,
+            R.dimen.setup_design_card_view_intrinsic_width,
+            R.bool.setup_compat_light_navigation_bar,
+            R.bool.setup_compat_light_status_bar,
+            R.color.setup_compat_footer_primary_button_bg_color,
+            R.dimen.setup_compat_footer_button_radius,
+            R.fraction.setup_compat_footer_button_ripple_alpha
+        )
+    }
+
+    private lateinit var defaultThemeString: String
+
+    override fun onCreate(): Boolean {
+        // returns value of setupwizard.theme sysprop
+        val theme: Optional<String> = android.sysprop.SetupWizardProperties.theme()
+        // setupwizard.theme should always be set to prevent inconsistencies in setupdesign UIs
+        check(theme.isPresent) { "missing setupwizard.theme sysprop" }
+        defaultThemeString = theme.get()
+        return true
+    }
+
+    override fun call(method: String, arg: String?, extras: Bundle?): Bundle {
+        Log.d(TAG, "method: $method, caller: $callingPackage")
+        val bundle = Bundle()
+        when (method) {
+            "suwDefaultThemeString" -> bundle.putString(method, defaultThemeString)
+
+            "applyGlifThemeControlledTransition",
+            "isDynamicColorEnabled",
+            "isEmbeddedActivityOnePaneEnabled",
+            "isFullDynamicColorEnabled",
+            "IsMaterialYouStyleEnabled",
+            "isNeutralButtonStyleEnabled",
+            "isSuwDayNightEnabled" -> bundle.putBoolean(method, true)
+
+            "getDeviceName" -> bundle.putCharSequence(method, getDeviceName())
+
+            "getOverlayConfig" -> fillOverlayConfig(bundle)
+        }
+        return bundle
+    }
+
+    private fun getDeviceName(): String {
+        var name = Settings.Global.getString(
+            requireContext().contentResolver,
+            Settings.Global.DEVICE_NAME
+        )
+        if (TextUtils.isEmpty(name)) {
+            name = Build.MODEL
+        }
+        return name
+    }
+
+    private fun fillOverlayConfig(bundle: Bundle) {
+        overlayConfigResources.forEach { resId ->
+            val context = requireContext()
+            val resName = context.resources.getResourceEntryName(resId)
+            val config = Bundle()
+            config.putString("packageName", context.packageName)
+            config.putString("resourceName", resName)
+            config.putInt("resourceId", resId)
+            bundle.putBundle(resName, config)
+        }
+    }
+}
diff --git a/src/com/android/settings/system/LogcatLinkPrefController.java b/src/com/android/settings/system/LogcatLinkPrefController.java
new file mode 100644
index 00000000000..e56f57dcd85
--- /dev/null
+++ b/src/com/android/settings/system/LogcatLinkPrefController.java
@@ -0,0 +1,34 @@
+package com.android.settings.system;
+
+import android.content.Context;
+import android.content.Intent;
+import android.ext.LogViewerApp;
+import android.text.TextUtils;
+
+import androidx.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.ext.ExtSettingControllerHelper;
+
+public class LogcatLinkPrefController extends BasePreferenceController {
+
+    public LogcatLinkPrefController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return ExtSettingControllerHelper.getGlobalSettingAvailability(mContext);
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+            return false;
+        }
+
+        Intent i = LogViewerApp.getLogcatIntent();
+        mContext.startActivity(i);
+        return true;
+    }
+}
diff --git a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
index fe90a2a25b8..ef54f0b2755 100644
--- a/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
+++ b/src/com/android/settings/users/AddUserWhenLockedPreferenceController.java
@@ -59,15 +59,7 @@ public void updateState(Preference preference) {
 
     @Override
     public int getAvailabilityStatus() {
-        if (!mUserCaps.isAdmin()) {
-            return DISABLED_FOR_USER;
-        } else if (android.multiuser.Flags.newMultiuserSettingsUx()) {
-            return AVAILABLE;
-        } else if (mUserCaps.disallowAddUser() || mUserCaps.disallowAddUserSetByAdmin()) {
-            return DISABLED_FOR_USER;
-        } else {
-            return mUserCaps.mUserSwitcherEnabled ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
-        }
+        return UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
diff --git a/src/com/android/settings/users/SendCensoredNotificationsToCurrentUserPreferenceController.java b/src/com/android/settings/users/SendCensoredNotificationsToCurrentUserPreferenceController.java
new file mode 100644
index 00000000000..637d7bbb782
--- /dev/null
+++ b/src/com/android/settings/users/SendCensoredNotificationsToCurrentUserPreferenceController.java
@@ -0,0 +1,60 @@
+package com.android.settings.users;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.widget.Toast;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+
+public class SendCensoredNotificationsToCurrentUserPreferenceController
+        extends TogglePreferenceController {
+    private final UserCapabilities mUserCaps;
+
+    public SendCensoredNotificationsToCurrentUserPreferenceController(Context context, String key) {
+        super(context, key);
+        mUserCaps = UserCapabilities.create(context);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        mUserCaps.updateAddUserCapabilities(mContext);
+        if (!isAvailable()) {
+            preference.setVisible(false);
+        } else {
+            preference.setVisible(mUserCaps.mUserSwitcherEnabled);
+        }
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mUserCaps.mUserSwitcherEnabled ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.SEND_CENSORED_NOTIFICATIONS_TO_CURRENT_USER, 0) != 0;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        return Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.SEND_CENSORED_NOTIFICATIONS_TO_CURRENT_USER, isChecked ? 1 : 0);
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        return mContext.getString(
+                R.string.user_settings_send_censored_notifications_to_current_summary);
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        return R.string.menu_key_system;
+    }
+}
diff --git a/src/com/android/settings/users/UserAppsInstallSettings.java b/src/com/android/settings/users/UserAppsInstallSettings.java
new file mode 100644
index 00000000000..52312d90f5c
--- /dev/null
+++ b/src/com/android/settings/users/UserAppsInstallSettings.java
@@ -0,0 +1,173 @@
+package com.android.settings.users;
+
+import static com.android.settings.users.UserDetailsSettings.EXTRA_USER_ID;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.utils.CandidateInfoExtra;
+import com.android.settings.widget.RadioButtonPickerFragment;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settingslib.widget.CandidateInfo;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class UserAppsInstallSettings extends RadioButtonPickerFragment {
+
+    private static final String INSTALL_ENABLED = "install_apps_enabled";
+    private static final String INSTALL_FIRST_PARTY_ENABLED = "install_apps_first_party_enabled";
+    private static final String INSTALL_DISABLED = "install_apps_disabled";
+    private UserRestrictions userRestrictions;
+
+    static void launch(Preference preference, int userId) {
+
+        Bundle extras = preference.getExtras();
+        extras.putInt(EXTRA_USER_ID, userId);
+
+        new SubSettingLauncher(preference.getContext())
+                .setDestination(UserAppsInstallSettings.class.getName())
+                .setSourceMetricsCategory(extras.getInt(DashboardFragment.CATEGORY,
+                        SettingsEnums.PAGE_UNKNOWN))
+                .setTitleText(preference.getTitle())
+                .setArguments(extras)
+                .launch();
+    }
+
+    private static String getCurrentInstallRestriction(UserRestrictions userRestrictions) {
+        if (userRestrictions.isSet(UserManager.DISALLOW_INSTALL_APPS)) {
+            return INSTALL_DISABLED;
+        }
+
+        if (userRestrictions.isSet(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) {
+            return INSTALL_FIRST_PARTY_ENABLED;
+        }
+
+        return INSTALL_ENABLED;
+    }
+
+    static String getDescription(Context context, UserRestrictions userRestrictions) {
+        switch (getCurrentInstallRestriction(userRestrictions)) {
+            case INSTALL_ENABLED:
+                return context.getString(R.string.user_app_install_enabled);
+            case INSTALL_FIRST_PARTY_ENABLED:
+                return context.getString(R.string.user_app_install_enabled_first_party_sources);
+            case INSTALL_DISABLED:
+                return context.getString(R.string.user_app_install_disabled);
+            default:
+                throw new IllegalStateException();
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        Bundle args = requireArguments();
+        int userId = args.getInt(EXTRA_USER_ID, UserHandle.USER_NULL);
+
+        Context ctx = requireContext();
+        UserManager userManager = ctx.getSystemService(UserManager.class);
+        UserInfo userInfo = userManager.getUserInfo(userId);
+        userRestrictions = new UserRestrictions(userManager, userInfo);
+
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        PreferenceScreen ps = getPreferenceManager().createPreferenceScreen(requireContext());
+        setPreferenceScreen(ps);
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return -1;
+    }
+
+    @Override
+    protected List<? extends CandidateInfo> getCandidates() {
+        Context ctx = requireContext();
+        ArrayList<CandidateInfoExtra> candidates = new ArrayList<>(3);
+        if (!userRestrictions.userInfo.isGuest()) {
+            candidates.add(new CandidateInfoExtra(ctx.getString(R.string.user_app_install_enabled),
+                    ctx.getString(R.string.user_app_install_enabled_desc),
+                    INSTALL_ENABLED, true));
+        }
+        candidates.add(new CandidateInfoExtra(ctx.getString(R.string.user_app_install_enabled_first_party_sources),
+                        ctx.getString(R.string.user_app_install_enabled_first_party_sources_desc),
+                INSTALL_FIRST_PARTY_ENABLED, true));
+        candidates.add(new CandidateInfoExtra(ctx.getString(R.string.user_app_install_disabled),
+                        ctx.getString(R.string.user_app_install_disabled_desc),
+                INSTALL_DISABLED, true));
+        return candidates;
+    }
+
+    @Override
+    public void bindPreferenceExtra(SelectorWithWidgetPreference pref, String key, CandidateInfo info,
+                                    String defaultKey, String systemDefaultKey) {
+        pref.setSingleLineTitle(false);
+
+        if (info instanceof CandidateInfoExtra) {
+            var cie = (CandidateInfoExtra) info;
+            pref.setSummary(cie.loadSummary());
+        }
+    }
+
+    @Override
+    protected String getDefaultKey() {
+        return getCurrentInstallRestriction(userRestrictions);
+    }
+
+    @Override
+    protected boolean setDefaultKey(String key) {
+        if (key == null) {
+            return false;
+        }
+
+        switch (key) {
+            case INSTALL_ENABLED:
+                if (userRestrictions.userInfo.isGuest()) {
+                    return false;
+                }
+                userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, false);
+                userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, false);
+                return true;
+            case INSTALL_FIRST_PARTY_ENABLED:
+                userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, false);
+                if (!userRestrictions.userInfo.isGuest()) {
+                    userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
+                }
+                return true;
+            case INSTALL_DISABLED:
+                userRestrictions.set(UserManager.DISALLOW_INSTALL_APPS, true);
+                if (!userRestrictions.userInfo.isGuest()) {
+                    userRestrictions.set(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
+                }
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return METRICS_CATEGORY_UNKNOWN;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        updateCandidates();
+    }
+}
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index 8afab9678f4..8368e0448d4 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -32,6 +32,7 @@
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
+import androidx.preference.SwitchPreferenceCompat;
 import androidx.preference.TwoStatePreference;
 
 import com.android.settings.R;
@@ -66,6 +67,9 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
     private static final String KEY_APP_AND_CONTENT_ACCESS = "app_and_content_access";
     private static final String KEY_APP_COPYING = "app_copying";
 
+    private static final String KEY_APP_INSTALLS = "app_installs";
+    private static final String KEY_RUN_IN_BACKGROUND = "allow_run_in_background";
+
     /** Integer extra containing the userId to manage */
     static final String EXTRA_USER_ID = "user_id";
 
@@ -78,7 +82,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
     private static final int DIALOG_CONFIRM_GRANT_ADMIN = 7;
 
     /** Whether to enable the app_copying fragment. */
-    private static final boolean SHOW_APP_COPYING_PREF = false;
+    private static final boolean SHOW_APP_COPYING_PREF = true;
     private static final int MESSAGE_PADDING = 20;
 
     private UserManager mUserManager;
@@ -98,10 +102,13 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
     Preference mRemoveUserPref;
     @VisibleForTesting
     TwoStatePreference mGrantAdminPref;
+    Preference mAppsInstallsPref;
+    private SwitchPreferenceCompat mRunInBackgroundPref;
 
     @VisibleForTesting
     /** The user being studied (not the user doing the studying). */
     UserInfo mUserInfo;
+    private UserRestrictions userRestrictions;
 
     @Override
     public int getMetricsCategory() {
@@ -134,6 +141,9 @@ public void onResume() {
         if (mUserInfo.isGuest() && mGuestUserAutoCreated) {
             mRemoveUserPref.setEnabled((mUserInfo.flags & UserInfo.FLAG_INITIALIZED) != 0);
         }
+        mAppsInstallsPref.setSummary(UserAppsInstallSettings.getDescription(
+                requireContext(), userRestrictions));
+        mAppCopyingPref.setEnabled(!userRestrictions.isSet(UserManager.DISALLOW_INSTALL_APPS));
     }
 
     @Override
@@ -174,6 +184,9 @@ public boolean onPreferenceClick(Preference preference) {
         } else if (preference == mAppCopyingPref) {
             openAppCopyingScreen();
             return true;
+        } else if (preference == mAppsInstallsPref) {
+            UserAppsInstallSettings.launch(preference, mUserInfo.id);
+            return true;
         }
         return false;
     }
@@ -201,7 +214,11 @@ public boolean onPreferenceChange(Preference preference, Object newValue) {
                 showDialog(DIALOG_CONFIRM_GRANT_ADMIN);
             }
             return false;
+        } else if (preference == mRunInBackgroundPref) {
+            userRestrictions.set(UserManager.DISALLOW_RUN_IN_BACKGROUND, !((boolean) newValue));
+            return true;
         }
+
         return true;
     }
 
@@ -344,6 +361,7 @@ void initialize(Context context, Bundle arguments) {
         boolean isNewUser =
                 arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false);
         mUserInfo = mUserManager.getUserInfo(userId);
+        userRestrictions = new UserRestrictions(mUserManager, mUserInfo);
 
         mSwitchUserPref = findPreference(KEY_SWITCH_USER);
         mPhonePref = findPreference(KEY_ENABLE_TELEPHONY);
@@ -353,6 +371,8 @@ void initialize(Context context, Bundle arguments) {
         mGrantAdminPref = findPreference(KEY_GRANT_ADMIN);
 
         mGrantAdminPref.setChecked(mUserInfo.isAdmin());
+        mAppsInstallsPref = findPreference(KEY_APP_INSTALLS);
+        mRunInBackgroundPref = findPreference(KEY_RUN_IN_BACKGROUND);
 
         mSwitchUserPref.setTitle(
                 context.getString(com.android.settingslib.R.string.user_switch_to_user,
@@ -387,6 +407,8 @@ void initialize(Context context, Bundle arguments) {
             removePreference(KEY_REMOVE_USER);
             removePreference(KEY_APP_AND_CONTENT_ACCESS);
             removePreference(KEY_APP_COPYING);
+            removePreference(KEY_APP_INSTALLS);
+            removePreference(KEY_RUN_IN_BACKGROUND);
         } else {
             if (!Utils.isVoiceCapable(context)) { // no telephony
                 removePreference(KEY_ENABLE_TELEPHONY);
@@ -416,11 +438,13 @@ void initialize(Context context, Bundle arguments) {
                 if (!SHOW_APP_COPYING_PREF) {
                     removePreference(KEY_APP_COPYING);
                 }
+                removePreference(KEY_RUN_IN_BACKGROUND);
             } else {
                 mPhonePref.setChecked(!mUserManager.hasUserRestriction(
                         UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
                 mRemoveUserPref.setTitle(R.string.user_remove_user);
-                removePreference(KEY_APP_COPYING);
+                mRunInBackgroundPref.setChecked(!userRestrictions.isSet(
+                        UserManager.DISALLOW_RUN_IN_BACKGROUND));
             }
 
             // Remove preference KEY_REMOVE_USER if DISALLOW_REMOVE_USER restriction is set
@@ -432,10 +456,12 @@ void initialize(Context context, Bundle arguments) {
             }
 
             mRemoveUserPref.setOnPreferenceClickListener(this);
+            mAppsInstallsPref.setOnPreferenceClickListener(this);
             mPhonePref.setOnPreferenceChangeListener(this);
             mGrantAdminPref.setOnPreferenceChangeListener(this);
             mAppAndContentAccessPref.setOnPreferenceClickListener(this);
             mAppCopyingPref.setOnPreferenceClickListener(this);
+            mRunInBackgroundPref.setOnPreferenceChangeListener(this);
         }
     }
 
diff --git a/src/com/android/settings/users/UserRestrictions.java b/src/com/android/settings/users/UserRestrictions.java
new file mode 100644
index 00000000000..7db3161c201
--- /dev/null
+++ b/src/com/android/settings/users/UserRestrictions.java
@@ -0,0 +1,38 @@
+package com.android.settings.users;
+
+import android.content.pm.UserInfo;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import java.util.List;
+
+final class UserRestrictions {
+
+    final UserManager userManager;
+    final UserInfo userInfo;
+
+    UserRestrictions(UserManager userManager, UserInfo userInfo) {
+        this.userManager = userManager;
+        this.userInfo = userInfo;
+    }
+
+    boolean isSet(String restrictionKey) {
+        final boolean isSetFromUser = userManager.hasUserRestriction(restrictionKey, userInfo.getUserHandle());
+        if (userInfo.isGuest()) {
+            return isSetFromUser || userManager.getDefaultGuestRestrictions().getBoolean(restrictionKey);
+        }
+
+        return isSetFromUser;
+    }
+
+    void set(String restrictionKey, boolean enableRestriction) {
+        if (userInfo.isGuest()) {
+            Bundle defaultGuestRestrictions = userManager.getDefaultGuestRestrictions();
+            defaultGuestRestrictions.putBoolean(restrictionKey, enableRestriction);
+            userManager.setDefaultGuestRestrictions(defaultGuestRestrictions);
+        } else {
+            userManager.setUserRestriction(restrictionKey, enableRestriction, userInfo.getUserHandle());
+        }
+    }
+}
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index a0137df728f..fe09642b58a 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -139,6 +139,8 @@ public class UserSettings extends SettingsPreferenceFragment
     private static final String KEY_GUEST_USER_CATEGORY = "guest_user_category";
     private static final String KEY_ALLOW_MULTIPLE_USERS = "allow_multiple_users";
     private static final String KEY_USER_SETTINGS_SCREEN = "user_settings_screen";
+    private static final String KEY_SEND_CENSORED_NOTIFICATIONS =
+            "user_settings_send_censored_notifications_to_current";
 
     private static final String SETTING_GUEST_HAS_LOGGED_IN = "systemui.guest_has_logged_in";
 
@@ -227,6 +229,7 @@ public class UserSettings extends SettingsPreferenceFragment
     private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController;
     private GuestTelephonyPreferenceController mGuestTelephonyPreferenceController;
     private RemoveGuestOnExitPreferenceController mRemoveGuestOnExitPreferenceController;
+    private SendCensoredNotificationsToCurrentUserPreferenceController mSendCensoredNotificationsToCurrentUserPreferenceController;
     private MultiUserTopIntroPreferenceController mMultiUserTopIntroPreferenceController;
     private TimeoutToDockUserPreferenceController mTimeoutToDockUserPreferenceController;
     private UserCreatingDialog mUserCreatingDialog;
@@ -324,6 +327,10 @@ public void onCreate(Bundle icicle) {
         mRemoveGuestOnExitPreferenceController = new RemoveGuestOnExitPreferenceController(
                 activity, KEY_REMOVE_GUEST_ON_EXIT, this, mHandler);
 
+        mSendCensoredNotificationsToCurrentUserPreferenceController =
+                new SendCensoredNotificationsToCurrentUserPreferenceController(activity,
+                        KEY_SEND_CENSORED_NOTIFICATIONS);
+
         mMultiUserTopIntroPreferenceController = new MultiUserTopIntroPreferenceController(activity,
                 KEY_MULTIUSER_TOP_INTRO);
 
@@ -334,11 +341,14 @@ public void onCreate(Bundle icicle) {
         mAddUserWhenLockedPreferenceController.displayPreference(screen);
         mGuestTelephonyPreferenceController.displayPreference(screen);
         mRemoveGuestOnExitPreferenceController.displayPreference(screen);
+        mSendCensoredNotificationsToCurrentUserPreferenceController.displayPreference(screen);
         mMultiUserTopIntroPreferenceController.displayPreference(screen);
         mTimeoutToDockUserPreferenceController.displayPreference(screen);
 
         screen.findPreference(mAddUserWhenLockedPreferenceController.getPreferenceKey())
                 .setOnPreferenceChangeListener(mAddUserWhenLockedPreferenceController);
+        screen.findPreference(mSendCensoredNotificationsToCurrentUserPreferenceController.getPreferenceKey())
+                .setOnPreferenceChangeListener(mSendCensoredNotificationsToCurrentUserPreferenceController);
 
         screen.findPreference(mGuestTelephonyPreferenceController.getPreferenceKey())
                 .setOnPreferenceChangeListener(mGuestTelephonyPreferenceController);
@@ -420,6 +430,9 @@ public void onResume() {
         mRemoveGuestOnExitPreferenceController.updateState(screen.findPreference(
                 mRemoveGuestOnExitPreferenceController.getPreferenceKey()));
         mSwitchBarController.updateState();
+        mSendCensoredNotificationsToCurrentUserPreferenceController.updateState(screen.findPreference(
+                mSendCensoredNotificationsToCurrentUserPreferenceController.getPreferenceKey()));
+
         if (mShouldUpdateUserList) {
             updateUI();
         }
@@ -1342,6 +1355,10 @@ void updateUserList() {
                 mGuestTelephonyPreferenceController.getPreferenceKey());
         mGuestTelephonyPreferenceController.updateState(guestCallPreference);
 
+        final Preference sendCensoredNotifs = getPreferenceScreen().findPreference(
+                mSendCensoredNotificationsToCurrentUserPreferenceController.getPreferenceKey());
+        mSendCensoredNotificationsToCurrentUserPreferenceController.updateState(sendCensoredNotifs);
+
         final Preference multiUserTopIntroPreference = getPreferenceScreen().findPreference(
                 mMultiUserTopIntroPreferenceController.getPreferenceKey());
         mMultiUserTopIntroPreferenceController.updateState(multiUserTopIntroPreference);
@@ -1846,6 +1863,8 @@ public List<String> getNonIndexableKeysFromXml(Context context, int xmlResId,
                             new AddUserWhenLockedPreferenceController(
                                     context, KEY_ADD_USER_WHEN_LOCKED);
                     controller.updateNonIndexableKeys(niks);
+                    new SendCensoredNotificationsToCurrentUserPreferenceController(context,
+                            KEY_SEND_CENSORED_NOTIFICATIONS).updateNonIndexableKeys(niks);
                     new AutoSyncDataPreferenceController(context, null /* parent */)
                             .updateNonIndexableKeys(niks);
                     new AutoSyncPersonalDataPreferenceController(context, null /* parent */)
diff --git a/src/com/android/settings/widget/RadioButtonPickerFragment.java b/src/com/android/settings/widget/RadioButtonPickerFragment.java
index d68a91afca8..547f2779ebc 100644
--- a/src/com/android/settings/widget/RadioButtonPickerFragment.java
+++ b/src/com/android/settings/widget/RadioButtonPickerFragment.java
@@ -55,7 +55,7 @@ public abstract class RadioButtonPickerFragment extends SettingsPreferenceFragme
         SelectorWithWidgetPreference.OnClickListener {
 
     @VisibleForTesting
-    static final String EXTRA_FOR_WORK = "for_work";
+    protected static final String EXTRA_FOR_WORK = "for_work";
     private static final String TAG = "RadioButtonPckrFrgmt";
     @VisibleForTesting
     boolean mAppendStaticPreferences = false;
@@ -166,6 +166,12 @@ protected SelectorWithWidgetPreference createPreference() {
         return new SelectorWithWidgetPreference(getPrefContext());
     }
 
+    protected void addPrefsBeforeList(PreferenceScreen screen) {
+        if (!mAppendStaticPreferences) {
+            addStaticPreferences(screen);
+        }
+    }
+
     public void updateCandidates() {
         mCandidates.clear();
         final List<? extends CandidateInfo> candidateList = getCandidates();
@@ -181,9 +187,7 @@ public void updateCandidates() {
         if (mIllustrationId != 0) {
             addIllustration(screen);
         }
-        if (!mAppendStaticPreferences) {
-            addStaticPreferences(screen);
-        }
+        addPrefsBeforeList(screen);
 
         final int customLayoutResId = getRadioButtonPreferenceCustomLayoutResId();
         if (shouldShowItemNone()) {
@@ -210,6 +214,10 @@ public void updateCandidates() {
             }
         }
         mayCheckOnlyRadioButton();
+        addPrefsAfterList(screen);
+    }
+
+    protected void addPrefsAfterList(PreferenceScreen screen) {
         if (mAppendStaticPreferences) {
             addStaticPreferences(screen);
         }
diff --git a/src/com/android/settings/wifi/WifiAutoOffPrefController.java b/src/com/android/settings/wifi/WifiAutoOffPrefController.java
new file mode 100644
index 00000000000..b8ec16bd69a
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiAutoOffPrefController.java
@@ -0,0 +1,39 @@
+package com.android.settings.wifi;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.ext.settings.ExtSettings;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.ext.AutoOffSetting;
+import com.android.settings.ext.IntSettingPrefController;
+import com.android.settings.ext.RadioButtonPickerFragment2;
+
+public class WifiAutoOffPrefController extends IntSettingPrefController {
+
+    public WifiAutoOffPrefController(Context ctx, String key) {
+        super(ctx, key, ExtSettings.WIFI_AUTO_OFF);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        int r = super.getAvailabilityStatus();
+        if (r == AVAILABLE) {
+            return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI) ?
+                    AVAILABLE : UNSUPPORTED_ON_DEVICE;
+        }
+        return r;
+    }
+
+    @Override
+    public void addPrefsBeforeList(RadioButtonPickerFragment2 fragment, PreferenceScreen screen) {
+        addFooterPreference(screen, R.string.wifi_auto_off_footer);
+    }
+
+    @Override
+    protected void getEntries(Entries entries) {
+        AutoOffSetting.getEntries(entries);
+    }
+}
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 39c77a17924..e1c430f3185 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -73,6 +73,7 @@
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settings.utils.AndroidKeystoreAliasLoader;
 import com.android.settings.wifi.details2.WifiPrivacyPreferenceController;
+import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2;
 import com.android.settings.wifi.dpp.WifiDppUtils;
 import com.android.settingslib.Utils;
 import com.android.settingslib.utils.ThreadUtils;
@@ -152,8 +153,9 @@ public class WifiConfigController implements TextWatcher,
     };
 
     // Should be the same index value as wifi_privacy_entries in arrays.xml
-    @VisibleForTesting static final int PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC = 0;
-    @VisibleForTesting static final int PRIVACY_SPINNER_INDEX_DEVICE_MAC = 1;
+    public static final int PRIVACY_PREF_INDEX_PER_CONNECTION_RANDOMIZED_MAC = 0;
+    public static final int PRIVACY_PREF_INDEX_PER_NETWORK_RANDOMIZED_MAC = 1;
+    public static final int PRIVACY_PREF_INDEX_DEVICE_MAC = 2;
 
     // Should be the same index value as wifi_dhcp_entries in arrays.xml
     @VisibleForTesting static final int DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_ENABLE = 0;
@@ -326,9 +328,9 @@ private void initWifiConfigController(AccessPoint accessPoint, int mode) {
                         ? HIDDEN_NETWORK
                         : NOT_HIDDEN_NETWORK);
 
-                mPrivacySettingsSpinner.setSelection(
-                        config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT
-                        ? PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC : PRIVACY_SPINNER_INDEX_DEVICE_MAC);
+                int selection = WifiPrivacyPreferenceController2
+                        .translateWifiEntryPrivacyToPrefValue(config.macRandomizationSetting);
+                mPrivacySettingsSpinner.setSelection(selection);
 
                 mDhcpSettingsSpinner.setSelection(
                         config.isSendDhcpHostnameEnabled()
@@ -848,10 +850,8 @@ public WifiConfiguration getConfig() {
         }
 
         if (mPrivacySettingsSpinner != null) {
-            config.macRandomizationSetting = mPrivacySettingsSpinner.getSelectedItemPosition()
-                    == PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC
-                    ? WifiConfiguration.RANDOMIZATION_PERSISTENT
-                    : WifiConfiguration.RANDOMIZATION_NONE;
+            config.macRandomizationSetting = WifiPrivacyPreferenceController2
+                    .translatePrefValueToWifiConfigSetting(mPrivacySettingsSpinner.getSelectedItemPosition());
         }
 
         if (mDhcpSettingsSpinner != null) {
diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java
index 1ea0103c28e..ed1d56d3ec6 100644
--- a/src/com/android/settings/wifi/WifiConfigController2.java
+++ b/src/com/android/settings/wifi/WifiConfigController2.java
@@ -313,6 +313,13 @@ private void initWifiConfigController2(WifiEntry wifiEntry) {
             mPrivacySettingsSpinner = mView.findViewById(R.id.privacy_settings);
             if (Flags.androidVWifiApi()) {
                 mDhcpSettingsSpinner = mView.findViewById(R.id.dhcp_settings);
+                if (mDhcpSettingsSpinner != null) {
+                    int selection = 1;
+                    if (WifiPrivacyPreferenceController.Companion.translatePrefValueToSendDhcpHostnameEnabled(selection)) {
+                        throw new IllegalStateException("unexpected order of DHCP hostname setting entries");
+                    }
+                    mDhcpSettingsSpinner.setSelection(selection);
+                }
             }
             mView.findViewById(R.id.privacy_settings_fields).setVisibility(View.VISIBLE);
         }
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index a8d7f417a4a..29f45af1cd5 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -758,7 +758,7 @@ private void refreshWifiType() {
     }
 
     private int getMacAddressTitle() {
-        if (mWifiEntry.getPrivacy() == WifiEntry.PRIVACY_RANDOMIZED_MAC) {
+        if (mWifiEntry.getPrivacy() != WifiEntry.PRIVACY_DEVICE_MAC) {
             return mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED
                     ? R.string.wifi_advanced_randomized_mac_address_title
                     : R.string.wifi_advanced_randomized_mac_address_disconnected_title;
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt b/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt
index 8888f0dacf5..cb859abdec6 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt
@@ -94,8 +94,8 @@ fun WifiPrivacyPage(wifiEntry: WifiEntry) {
     ) {
         Column {
             val title = stringResource(id = R.string.wifi_privacy_mac_settings)
-            val wifiPrivacyEntries = stringArrayResource(R.array.wifi_privacy_entries)
-            val wifiPrivacyValues = stringArrayResource(R.array.wifi_privacy_values)
+            val wifiPrivacyEntries = stringArrayResource(R.array.wifi_privacy_entries_ext)
+            val wifiPrivacyValues = stringArrayResource(R.array.wifi_privacy_values_ext)
             val textsSelectedId = rememberSaveable { mutableIntStateOf(wifiEntry.privacy) }
             val dataList = remember {
                 wifiPrivacyEntries.mapIndexed { index, text ->
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
index 0c67c04622e..cb20ea9c77c 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
@@ -30,6 +31,10 @@
 import com.android.wifi.flags.Flags;
 import com.android.wifitrackerlib.WifiEntry;
 
+import static com.android.settings.wifi.WifiConfigController.PRIVACY_PREF_INDEX_DEVICE_MAC;
+import static com.android.settings.wifi.WifiConfigController.PRIVACY_PREF_INDEX_PER_CONNECTION_RANDOMIZED_MAC;
+import static com.android.settings.wifi.WifiConfigController.PRIVACY_PREF_INDEX_PER_NETWORK_RANDOMIZED_MAC;
+
 /**
  * A controller that controls whether the Wi-Fi network is mac randomized or not.
  */
@@ -95,9 +100,6 @@ int getRandomizationValue() {
         return mWifiEntry.getPrivacy();
     }
 
-    private static final int PREF_RANDOMIZATION_PERSISTENT = 0;
-    private static final int PREF_RANDOMIZATION_NONE = 1;
-
     /**
      * Translates a WifiEntry.Privacy value to the matching preference index value.
      *
@@ -105,8 +107,13 @@ int getRandomizationValue() {
      * @return index value of preference
      */
     public static int translateWifiEntryPrivacyToPrefValue(@WifiEntry.Privacy int privacy) {
-        return (privacy == WifiEntry.PRIVACY_RANDOMIZED_MAC)
-            ? PREF_RANDOMIZATION_PERSISTENT : PREF_RANDOMIZATION_NONE;
+        Log.d("WifiMacRnd", "translateMacRandomizedValueToPrefValue called from", new Throwable());
+        return switch (privacy) {
+            case WifiEntry.PRIVACY_RANDOMIZATION_ALWAYS -> PRIVACY_PREF_INDEX_PER_CONNECTION_RANDOMIZED_MAC;
+            case WifiEntry.PRIVACY_RANDOMIZED_MAC -> PRIVACY_PREF_INDEX_PER_NETWORK_RANDOMIZED_MAC;
+            case WifiEntry.PRIVACY_DEVICE_MAC -> PRIVACY_PREF_INDEX_DEVICE_MAC;
+            default -> PRIVACY_PREF_INDEX_DEVICE_MAC;
+        };
     }
 
     /**
@@ -116,8 +123,13 @@ public static int translateWifiEntryPrivacyToPrefValue(@WifiEntry.Privacy int pr
      * @return WifiConfiguration.MacRandomizationSetting value
      */
     public static int translatePrefValueToWifiConfigSetting(int prefMacRandomized) {
-        return (prefMacRandomized == PREF_RANDOMIZATION_PERSISTENT)
-            ? WifiConfiguration.RANDOMIZATION_AUTO : WifiConfiguration.RANDOMIZATION_NONE;
+        Log.d("WifiMacRnd", "translatePrefValueToWifiConfigSetting called from", new Throwable());
+        return switch (prefMacRandomized) {
+            case PRIVACY_PREF_INDEX_DEVICE_MAC -> WifiConfiguration.RANDOMIZATION_NONE;
+            case PRIVACY_PREF_INDEX_PER_NETWORK_RANDOMIZED_MAC -> WifiConfiguration.RANDOMIZATION_PERSISTENT;
+            case PRIVACY_PREF_INDEX_PER_CONNECTION_RANDOMIZED_MAC -> WifiConfiguration.RANDOMIZATION_ALWAYS;
+            default -> WifiConfiguration.RANDOMIZATION_ALWAYS;
+        };
     }
 
     private void updateSummary(ListPreference preference, int macRandomized) {
diff --git a/src/com/google/hardware/biometrics/sidefps/IFingerprintExt.aidl b/src/com/google/hardware/biometrics/sidefps/IFingerprintExt.aidl
new file mode 100644
index 00000000000..9fa1fd500e5
--- /dev/null
+++ b/src/com/google/hardware/biometrics/sidefps/IFingerprintExt.aidl
@@ -0,0 +1,5 @@
+package com.google.hardware.biometrics.sidefps;
+
+interface IFingerprintExt {
+    void resumeEnroll() = 1;
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java
index 6ae670dc120..2af9242dab8 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java
@@ -99,31 +99,6 @@ public void isDrivingModeAvailable_returnFalse() {
             AdvancedConnectedDeviceController.isDrivingModeAvailable(mContext)).isFalse();
     }
 
-    @Test
-    public void isAndroidAutoSettingAvailable_returnTrue() {
-        final ApplicationInfo appInfo =
-                ApplicationInfoBuilder.newBuilder().setPackageName(ANDROID_AUTO_PACKAGE).build();
-        final ActivityInfo activityInfo = new ActivityInfo();
-        activityInfo.packageName = ANDROID_AUTO_PACKAGE;
-        activityInfo.name = ANDROID_AUTO_PACKAGE;
-        activityInfo.applicationInfo = appInfo;
-        final ResolveInfo resolveInfo = new ResolveInfo();
-        resolveInfo.activityInfo = activityInfo;
-        mShadowPackageManager.addResolveInfoForIntent(
-                buildAndroidAutoSettingsIntent(),
-                resolveInfo);
-
-        assertThat(
-            AdvancedConnectedDeviceController.isAndroidAutoSettingAvailable(mContext)).isTrue();
-    }
-
-    @Test
-    public void isAndroidAutoSettingAvailable_returnFalse() {
-        // No ResolveInfo for Android Auto, expect false.
-        assertThat(
-            AdvancedConnectedDeviceController.isAndroidAutoSettingAvailable(mContext)).isFalse();
-    }
-
     @Test
     public void getConnectedDevicesSummaryResourceId_NFCAndDrivingModeAvailable() {
         // NFC available, driving mode available
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
index d80464d5467..4053468af24 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java
@@ -16,11 +16,12 @@
 
 package com.android.settings.wifi;
 
-import static com.android.settings.wifi.WifiConfigController.PRIVACY_SPINNER_INDEX_DEVICE_MAC;
-import static com.android.settings.wifi.WifiConfigController.PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC;
+import static com.android.settings.wifi.WifiConfigController.PRIVACY_PREF_INDEX_DEVICE_MAC;
+import static com.android.settings.wifi.WifiConfigController.PRIVACY_PREF_INDEX_PER_CONNECTION_RANDOMIZED_MAC;
 import static com.android.settings.wifi.WifiConfigController.DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_ENABLE;
 import static com.android.settings.wifi.WifiConfigController.DHCP_SPINNER_INDEX_SEND_DHCP_HOST_NAME_DISABLE;
 
+import static com.android.settings.wifi.details2.WifiPrivacyPreferenceController2.translateWifiEntryPrivacyToPrefValue;
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.mock;
@@ -407,7 +408,7 @@ public void loadMacRandomizedValue_shouldMandomizedMacAsDefault() {
 
         assertThat(privacySetting.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(privacySetting.getSelectedItemPosition()).isEqualTo(
-                PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC);
+                PRIVACY_PREF_INDEX_PER_CONNECTION_RANDOMIZED_MAC);
     }
 
     @Test
@@ -432,8 +433,7 @@ private void checkSavedMacRandomizedValue(int macRandomizedValue) {
 
         assertThat(privacySetting.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(privacySetting.getSelectedItemPosition()).isEqualTo(
-                macRandomizedValue == WifiConfiguration.RANDOMIZATION_PERSISTENT
-                ? PRIVACY_SPINNER_INDEX_RANDOMIZED_MAC : PRIVACY_SPINNER_INDEX_DEVICE_MAC);
+                translateWifiEntryPrivacyToPrefValue(macRandomizedValue));
     }
 
     @Test
@@ -446,7 +446,7 @@ public void saveMacRandomizedValue_noChanged_shouldPersistentAsDefault() {
     @Test
     public void saveMacRandomizedValue_ChangedToDeviceMac_shouldGetNone() {
         final Spinner privacySetting = mView.findViewById(R.id.privacy_settings);
-        privacySetting.setSelection(PRIVACY_SPINNER_INDEX_DEVICE_MAC);
+        privacySetting.setSelection(PRIVACY_PREF_INDEX_DEVICE_MAC);
 
         WifiConfiguration config = mController.getConfig();
         assertThat(config.macRandomizationSetting).isEqualTo(WifiConfiguration.RANDOMIZATION_NONE);
diff --git a/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPageProviderTest.kt b/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPageProviderTest.kt
index 5c9a1a4a932..a3893a85c13 100644
--- a/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPageProviderTest.kt
+++ b/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPageProviderTest.kt
@@ -85,7 +85,7 @@ class WifiPrivacyPageProviderTest {
         composeTestRule.setContent {
             WifiPrivacyPage(mockWifiEntry)
         }
-        val wifiPrivacyEntries = context.resources.getStringArray(R.array.wifi_privacy_entries)
+        val wifiPrivacyEntries = context.resources.getStringArray(R.array.wifi_privacy_entries_ext)
         for (entry in wifiPrivacyEntries) {
             composeTestRule.onNodeWithText(
                 entry
@@ -98,7 +98,7 @@ class WifiPrivacyPageProviderTest {
         composeTestRule.setContent {
             WifiPrivacyPage(mockWifiEntry)
         }
-        val wifiPrivacyEntries = context.resources.getStringArray(R.array.wifi_privacy_entries)
+        val wifiPrivacyEntries = context.resources.getStringArray(R.array.wifi_privacy_entries_ext)
         for (entry in wifiPrivacyEntries) {
             composeTestRule.onNodeWithText(
                 entry
@@ -111,8 +111,8 @@ class WifiPrivacyPageProviderTest {
         composeTestRule.setContent {
             WifiPrivacyPage(mockWifiEntry)
         }
-        val wifiPrivacyEntries = context.resources.getStringArray(R.array.wifi_privacy_entries)
-        val wifiPrivacyValues = context.resources.getStringArray(R.array.wifi_privacy_values)
+        val wifiPrivacyEntries = context.resources.getStringArray(R.array.wifi_privacy_entries_ext)
+        val wifiPrivacyValues = context.resources.getStringArray(R.array.wifi_privacy_values_ext)
         composeTestRule.onNodeWithText(
             wifiPrivacyEntries[wifiPrivacyValues.indexOf("0")]
         ).assertIsSelected()
@@ -126,7 +126,7 @@ class WifiPrivacyPageProviderTest {
         composeTestRule.setContent {
             WifiPrivacyPage(mockWifiEntry)
         }
-        val wifiPrivacyEntries = context.resources.getStringArray(R.array.wifi_privacy_entries)
+        val wifiPrivacyEntries = context.resources.getStringArray(R.array.wifi_privacy_entries_ext)
         for (entry in wifiPrivacyEntries) {
             composeTestRule.onNodeWithText(entry).assertIsNotEnabled()
         }
@@ -176,4 +176,4 @@ class WifiPrivacyPageProviderTest {
             context.getString(R.string.wifi_privacy_send_device_name_toggle_title)
         ).assertIsOff()
     }
-}
\ No newline at end of file
+}
diff --git a/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.kt b/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.kt
index 9260409af37..983d5fe1414 100644
--- a/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.kt
+++ b/tests/spa_unit/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.kt
@@ -45,11 +45,11 @@ class WifiPrivacyPreferenceController2Test {
     })
 
     private var preference = ListPreference(context).apply {
-        setEntries(R.array.wifi_privacy_entries)
-        setEntryValues(R.array.wifi_privacy_values)
+        setEntries(R.array.wifi_privacy_entries_ext)
+        setEntryValues(R.array.wifi_privacy_values_ext)
     }
 
-    private var preferenceStrings = context.resources.getStringArray(R.array.wifi_privacy_entries)
+    private var preferenceStrings = context.resources.getStringArray(R.array.wifi_privacy_entries_ext)
 
     @Test
     fun updateState_wifiPrivacy_setCorrectValue() {