Merge "[Shadow] Fix failed test case for battery defender" into main
diff --git a/Android.bp b/Android.bp
index c9a409c..a9c3ea0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -46,7 +46,6 @@
 
 android_library {
     name: "Settings-core",
-    platform_apis: true,
     defaults: [
         "SettingsLib-search-defaults",
         "SettingsLintDefaults",
diff --git a/res/layout/search_bar_two_pane_version.xml b/res/layout/search_bar_two_pane_version.xml
index f98985c..337294e 100644
--- a/res/layout/search_bar_two_pane_version.xml
+++ b/res/layout/search_bar_two_pane_version.xml
@@ -29,6 +29,9 @@
         android:paddingStart="@dimen/search_bar_padding_start_two_pane"
         android:paddingEnd="@dimen/search_bar_padding_end_two_pane"
         android:background="@drawable/search_bar_selected_background"
+        android:focusable="true"
+        android:focusableInTouchMode="true"
+        android:nextFocusForward="@+id/homepage_container"
         android:contentInsetStartWithNavigation="@dimen/search_bar_content_inset"
         android:navigationIcon="@drawable/ic_homepage_search">
         <TextView
@@ -40,4 +43,4 @@
             android:layout_gravity="start"
             android:text="@string/search_settings"/>
     </Toolbar>
-</com.google.android.material.card.MaterialCardView>
\ No newline at end of file
+</com.google.android.material.card.MaterialCardView>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 746dbf5..12a4c72 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -132,6 +132,8 @@
     <string name="bluetooth_pairing_pref_title">Pair new device</string>
     <!-- Keywords for bluetooth pairing item [CHAR LIMIT=30] -->
     <string name="keywords_add_bt_device">bluetooth</string>
+    <!-- Title for bluetooth auto on toggle [CHAR LIMIT=60] -->
+    <string name="bluetooth_screen_auto_on_title">Automatically turn on again tomorrow</string>
 
 
     <!-- Button to help user to pair right ear of the hearing aid device. It will show when only one of the hearing aid device set is connected. [CHAR LIMIT=20] -->
@@ -1800,8 +1802,12 @@
     <string name="bluetooth_device_context_pair_connect">Pair &amp; connect</string>
     <!-- Bluetooth settings. Text displayed when Bluetooth is off and device list is empty [CHAR LIMIT=NONE]-->
     <string name="bluetooth_empty_list_bluetooth_off">When Bluetooth is turned on, your device can communicate with other nearby Bluetooth devices</string>
+    <!-- Bluetooth settings. Text displayed when Bluetooth is off and device list is empty when auto-on feature is enabled [CHAR LIMIT=NONE]-->
+    <string name="bluetooth_empty_list_bluetooth_off_auto_on_available">When Bluetooth is on, your device can communicate with other nearby Bluetooth devices. Features like Quick Share, Find My Device, and device location use Bluetooth.</string>
     <!-- Bluetooth settings. Text displayed when Bluetooth is off and bluetooth scanning is turned on [CHAR LIMIT=NONE] -->
     <string name="bluetooth_scanning_on_info_message">When Bluetooth is turned on, your device can communicate with other nearby Bluetooth devices.\n\nTo improve device experience, apps and services can still scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services. You can change this in Bluetooth scanning settings.</string>
+    <!-- Bluetooth settings. Text displayed when Bluetooth is off and bluetooth scanning is turned on [CHAR LIMIT=NONE] -->
+    <string name="bluetooth_scanning_on_info_message_auto_on_available">When Bluetooth is on, your device can communicate with other nearby Bluetooth devices. Features like Quick Share, Find My Device, and device location use Bluetooth.\n\nApps and services can still scan for nearby devices at any time, even when Bluetooth is off. This can be used, for example, to improve location-based features and services. You can change this in Bluetooth scanning settings.</string>
     <!-- Bluetooth settings. Link text to bring the user to "scanning settings" screen. [CHAR LIMIT=NONE]-->
     <string name="bluetooth_scan_change">Change</string>
 
@@ -4362,6 +4368,10 @@
     <string name="trackpad_pointer_speed">Pointer speed</string>
     <!-- Title for the button to trigger the 'touch gesture' education. [CHAR LIMIT=35] -->
     <string name="trackpad_touch_gesture">Learn touchpad gestures</string>
+    <!-- Search keywords for "touchpad" -->
+    <string name="keywords_touchpad">trackpad, track pad, mouse, cursor, scroll, swipe, right click, click, pointer</string>
+    <!-- Search keywords for 'Bottom-right tap', the name of the touchpad setting that allows the user to click the bottom right corner of the touchpad for more options. -->
+    <string name="keywords_trackpad_bottom_right_tap">right click, tap</string>
 
     <!-- Title text for 'Go home' gesture education [CHAR LIMIT=35] -->
     <string name="gesture_title_go_home">Go home</string>
@@ -5140,7 +5150,7 @@
     <!-- Title for accessibility hearing device page footer. [CHAR LIMIT=40] -->
     <string name="accessibility_hearing_device_about_title">About hearing devices</string>
     <!-- Description for text in accessibility hearing aids footer. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_hearing_device_footer_summary">Make sure your hearing device is turned on and ready to pair</string>
+    <string name="accessibility_hearing_device_footer_summary">Make sure your hearing device is turned on and ready to pair. Only ASHA and LE Audio hearing devices show on this page.</string>
     <!-- Title for the pair hearing device page. [CHAR LIMIT=25] -->
     <string name="accessibility_hearing_device_pairing_page_title">Pair hearing device</string>
     <!-- Title for the preference category containing the list of the available hearing during and after bluetooth scanning devices. [CHAR LIMIT=30] -->
diff --git a/res/xml/bluetooth_screen.xml b/res/xml/bluetooth_screen.xml
index 86dc8a1..51507fb 100644
--- a/res/xml/bluetooth_screen.xml
+++ b/res/xml/bluetooth_screen.xml
@@ -18,6 +18,11 @@
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/bluetooth_settings_title">
 
+    <SwitchPreferenceCompat
+        android:key="bluetooth_auto_on_settings_toggle"
+        android:title="@string/bluetooth_screen_auto_on_title"
+        settings:controller="com.android.settings.bluetooth.BluetoothAutoOnPreferenceController"/>
+
     <Preference
         android:key="bluetooth_screen_bt_pair_rename_devices"
         android:title="@string/bluetooth_device_name"
diff --git a/res/xml/trackpad_settings.xml b/res/xml/trackpad_settings.xml
index 84ea528..cca92a3 100644
--- a/res/xml/trackpad_settings.xml
+++ b/res/xml/trackpad_settings.xml
@@ -49,7 +49,8 @@
         android:summary="@string/trackpad_bottom_right_tap_summary"
         android:icon="@drawable/ic_trackpad_bottom_right_click"
         settings:controller="com.android.settings.inputmethod.TrackpadBottomPreferenceController"
-        android:order="30"/>
+        android:order="30"
+        settings:keywords="@string/keywords_trackpad_bottom_right_tap"/>
 
     <com.android.settings.widget.SeekBarPreference
         android:key="trackpad_pointer_speed"
@@ -64,4 +65,4 @@
         android:title="@string/trackpad_touch_gesture"
         android:icon="@drawable/ic_trackpad_touch_gestures_inverse"
         settings:controller="com.android.settings.inputmethod.TouchGesturesButtonPreferenceController"/>
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
diff --git a/src/com/android/settings/ActionDisabledByAppOpsDialog.java b/src/com/android/settings/ActionDisabledByAppOpsDialog.java
index 15b8503..be3558e 100644
--- a/src/com/android/settings/ActionDisabledByAppOpsDialog.java
+++ b/src/com/android/settings/ActionDisabledByAppOpsDialog.java
@@ -21,7 +21,6 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
-import android.util.Log;
 
 public class ActionDisabledByAppOpsDialog extends Activity
         implements DialogInterface.OnDismissListener {
diff --git a/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java b/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java
index 0dbf05e..4e9cd92 100644
--- a/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragment.java
@@ -43,6 +43,7 @@
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.settingslib.accessibility.AccessibilityUtils;
 
 import java.util.List;
@@ -164,16 +165,9 @@
         if (permittedServices != null && !permittedServices.contains(packageName)) {
             return false;
         }
-        try {
-            final int mode = mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
-                    uid, packageName);
-            final boolean ecmEnabled = getContext().getResources().getBoolean(
-                    com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
-            return !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
-        } catch (Exception e) {
-            // Fallback in case if app ops is not available in testing.
-            return true;
-        }
+
+        return !RestrictedLockUtilsInternal.isEnhancedConfirmationRestricted(getContext(),
+                packageName, AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE);
     }
 
     private AccessibilityServiceInfo getAccessibilityServiceInfo(ComponentName componentName) {
diff --git a/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java b/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java
index 6f21fb8..03bf142 100644
--- a/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java
+++ b/src/com/android/settings/accessibility/RestrictedPreferenceHelper.java
@@ -235,10 +235,11 @@
         boolean serviceAllowed = permittedServices == null || permittedServices.contains(
                 preference.getPackageName());
 
-        if (android.security.Flags.extendEcmToAllSettings()) {
+        if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
+                && android.security.Flags.extendEcmToAllSettings()) {
             preference.checkEcmRestrictionAndSetDisabled(
                     AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE,
-                    preference.getPackageName(), preference.getUid());
+                    preference.getPackageName());
             if (preference.isDisabledByEcm()) {
                 serviceAllowed = false;
             }
@@ -257,40 +258,39 @@
                     preference.setEnabled(false);
                 }
             }
-            return;
-        }
-
-        boolean appOpsAllowed;
-        if (serviceAllowed) {
-            try {
-                final int mode = mAppOps.noteOpNoThrow(
-                        AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
-                        preference.getUid(), preference.getPackageName());
-                final boolean ecmEnabled = mContext.getResources().getBoolean(
-                        com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
-                appOpsAllowed = !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
-                serviceAllowed = appOpsAllowed;
-            } catch (Exception e) {
-                // Allow service in case if app ops is not available in testing.
-                appOpsAllowed = true;
-            }
         } else {
-            appOpsAllowed = false;
-        }
-        if (serviceAllowed || serviceEnabled) {
-            preference.setEnabled(true);
-        } else {
-            // Disable accessibility service that are not permitted.
-            final RestrictedLockUtils.EnforcedAdmin admin =
-                    RestrictedLockUtilsInternal.checkIfAccessibilityServiceDisallowed(
-                            mContext, preference.getPackageName(), UserHandle.myUserId());
-
-            if (admin != null) {
-                preference.setDisabledByAdmin(admin);
-            } else if (!appOpsAllowed) {
-                preference.setDisabledByAppOps(true);
+            boolean appOpsAllowed;
+            if (serviceAllowed) {
+                try {
+                    final int mode = mAppOps.noteOpNoThrow(
+                            AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
+                            preference.getUid(), preference.getPackageName());
+                    final boolean ecmEnabled = mContext.getResources().getBoolean(
+                            com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
+                    appOpsAllowed = !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
+                    serviceAllowed = appOpsAllowed;
+                } catch (Exception e) {
+                    // Allow service in case if app ops is not available in testing.
+                    appOpsAllowed = true;
+                }
             } else {
-                preference.setEnabled(false);
+                appOpsAllowed = false;
+            }
+            if (serviceAllowed || serviceEnabled) {
+                preference.setEnabled(true);
+            } else {
+                // Disable accessibility service that are not permitted.
+                final RestrictedLockUtils.EnforcedAdmin admin =
+                        RestrictedLockUtilsInternal.checkIfAccessibilityServiceDisallowed(
+                                mContext, preference.getPackageName(), UserHandle.myUserId());
+
+                if (admin != null) {
+                    preference.setDisabledByAdmin(admin);
+                } else if (!appOpsAllowed) {
+                    preference.setDisabledByAppOps(true);
+                } else {
+                    preference.setEnabled(false);
+                }
             }
         }
     }
diff --git a/src/com/android/settings/applications/UsageAccessDetails.java b/src/com/android/settings/applications/UsageAccessDetails.java
index 6976149..e111942 100644
--- a/src/com/android/settings/applications/UsageAccessDetails.java
+++ b/src/com/android/settings/applications/UsageAccessDetails.java
@@ -174,7 +174,7 @@
 
         if (shouldEnable && !hasAccess) {
             mSwitchPref.checkEcmRestrictionAndSetDisabled(AppOpsManager.OPSTR_GET_USAGE_STATS,
-                    mPackageName, mPackageInfo.applicationInfo.uid);
+                    mPackageName);
             shouldEnable = !mSwitchPref.isDisabledByEcm();
         }
 
diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
index 82d55f3..90d733e 100644
--- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
+++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
@@ -24,6 +24,7 @@
 import android.app.AppOpsManager;
 import android.app.KeyguardManager;
 import android.app.admin.DevicePolicyManager;
+import android.app.ecm.EnhancedConfirmationManager;
 import android.app.settings.SettingsEnums;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -490,12 +491,23 @@
                 return true;
             case ACCESS_RESTRICTED_SETTINGS:
                 showLockScreen(getContext(), () -> {
-                    final AppOpsManager appOpsManager = getContext().getSystemService(
-                            AppOpsManager.class);
-                    appOpsManager.setMode(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
-                            getUid(),
-                            getPackageName(),
-                            AppOpsManager.MODE_ALLOWED);
+                    if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
+                            && android.security.Flags.extendEcmToAllSettings()) {
+                        EnhancedConfirmationManager manager = getContext().getSystemService(
+                                EnhancedConfirmationManager.class);
+                        try {
+                            manager.clearRestriction(getPackageName());
+                        } catch (NameNotFoundException e) {
+                            Log.e(TAG, "Exception when retrieving package:" + getPackageName(), e);
+                        }
+                    } else {
+                        final AppOpsManager appOpsManager = getContext().getSystemService(
+                                AppOpsManager.class);
+                        appOpsManager.setMode(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
+                                getUid(),
+                                getPackageName(),
+                                AppOpsManager.MODE_ALLOWED);
+                    }
                     getActivity().invalidateOptionsMenu();
                     final String toastString = getContext().getString(
                             R.string.toast_allows_restricted_settings_successfully,
@@ -527,14 +539,25 @@
     }
 
     private boolean shouldShowAccessRestrictedSettings() {
-        try {
-            final int mode = getSystemService(AppOpsManager.class).noteOpNoThrow(
-                    AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, getUid(),
-                    getPackageName());
-            return mode == AppOpsManager.MODE_IGNORED;
-        } catch (Exception e) {
-            // Fallback in case if app ops is not available in testing.
-            return false;
+        if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
+                && android.security.Flags.extendEcmToAllSettings()) {
+            try {
+                return getSystemService(EnhancedConfirmationManager.class)
+                        .isClearRestrictionAllowed(getPackageName());
+            } catch (NameNotFoundException e) {
+                Log.e(TAG, "Exception when retrieving package:" + getPackageName(), e);
+                return false;
+            }
+        } else {
+            try {
+                final int mode = getSystemService(AppOpsManager.class).noteOpNoThrow(
+                        AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, getUid(),
+                        getPackageName());
+                return mode == AppOpsManager.MODE_IGNORED;
+            } catch (Exception e) {
+                // Fallback in case if app ops is not available in testing.
+                return false;
+            }
         }
     }
 
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java
index 55ba8ac..640f21d 100644
--- a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java
+++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java
@@ -32,6 +32,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.UserProperties;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -156,12 +157,23 @@
         mAdmins.clear();
         final List<UserHandle> profiles = mUm.getUserProfiles();
         for (UserHandle profile : profiles) {
+            if (shouldSkipProfile(profile)) {
+                continue;
+            }
             final int profileId = profile.getIdentifier();
             updateAvailableAdminsForProfile(profileId);
         }
         Collections.sort(mAdmins);
     }
 
+    private boolean shouldSkipProfile(UserHandle profile) {
+        return  android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace()
+                && mUm.isQuietModeEnabled(profile)
+                && mUm.getUserProperties(profile).getShowInQuietMode()
+                        == UserProperties.SHOW_IN_QUIET_MODE_HIDDEN;
+    }
+
     private void refreshUI() {
         if (mPreferenceGroup == null) {
             return;
@@ -210,7 +222,7 @@
         pref.setOnPreferenceChangeListener((preference, newValue) -> false);
         pref.setSingleLineTitle(true);
         pref.checkEcmRestrictionAndSetDisabled(Manifest.permission.BIND_DEVICE_ADMIN,
-                item.getPackageName(), item.getUid());
+                item.getPackageName());
     }
 
     /**
diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
index 00f0625..70a31b8 100644
--- a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
+++ b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageManager;
 import android.os.AsyncTask;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceFragmentCompat;
@@ -42,7 +43,7 @@
     private NotificationManager mNm;
     private PackageManager mPm;
     // The appOp representing this preference
-    private String mAppOpStr;
+    private String mSettingIdentifier;
 
     public ApprovalPreferenceController(Context context, String key) {
         super(context, key);
@@ -76,8 +77,9 @@
     /**
      * Set the associated appOp for the Setting
      */
-    public ApprovalPreferenceController setAppOpStr(String appOpStr) {
-        mAppOpStr = appOpStr;
+    @NonNull
+    public ApprovalPreferenceController setSettingIdentifier(@NonNull String settingIdentifier) {
+        mSettingIdentifier = settingIdentifier;
         return this;
     }
 
@@ -118,14 +120,15 @@
             }
         });
 
-        if (android.security.Flags.extendEcmToAllSettings()) {
+        if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
+                && android.security.Flags.extendEcmToAllSettings()) {
             if (!isAllowedCn && !isEnabled) {
                 preference.setEnabled(false);
             } else if (isEnabled) {
                 preference.setEnabled(true);
             } else {
-                preference.checkEcmRestrictionAndSetDisabled(mAppOpStr,
-                        mCn.getPackageName(), mPkgInfo.applicationInfo.uid);
+                preference.checkEcmRestrictionAndSetDisabled(mSettingIdentifier,
+                        mCn.getPackageName());
             }
         } else {
             preference.updateState(
diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java b/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java
index 89767dd..e885d5c 100644
--- a/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java
+++ b/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java
@@ -103,7 +103,7 @@
                 .setCn(mComponentName)
                 .setNm(context.getSystemService(NotificationManager.class))
                 .setPm(mPm)
-                .setAppOpStr(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS)
+                .setSettingIdentifier(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS)
                 .setParent(this);
         use(HeaderPreferenceController.class)
                 .setFragment(this)
diff --git a/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccess.java b/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccess.java
index 4c9f813..2a5f1db 100644
--- a/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccess.java
+++ b/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccess.java
@@ -25,7 +25,6 @@
 
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
-import androidx.preference.DropDownPreference;
 import androidx.preference.Preference;
 import androidx.preference.Preference.OnPreferenceChangeListener;
 import androidx.preference.PreferenceScreen;
@@ -38,6 +37,7 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.EmptyTextSettings;
+import com.android.settingslib.RestrictedDropDownPreference;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
 import com.android.settingslib.applications.ApplicationsState.Callbacks;
@@ -52,6 +52,8 @@
 public class PremiumSmsAccess extends EmptyTextSettings
         implements Callback, Callbacks, OnPreferenceChangeListener {
 
+    private static final String ECM_RESTRICTION_KEY = "android:premium_sms_access";
+
     private ApplicationsState mApplicationsState;
     private AppStateSmsPremBridge mSmsBackend;
     private Session mSession;
@@ -205,7 +207,7 @@
 
     }
 
-    private class PremiumSmsPreference extends DropDownPreference {
+    private class PremiumSmsPreference extends RestrictedDropDownPreference {
         private final AppEntry mAppEntry;
 
         public PremiumSmsPreference(AppEntry appEntry, Context context) {
@@ -224,6 +226,7 @@
             });
             setValue(String.valueOf(getCurrentValue()));
             setSummary("%s");
+            this.checkEcmRestrictionAndSetDisabled(ECM_RESTRICTION_KEY, appEntry.info.packageName);
         }
 
         private int getCurrentValue() {
diff --git a/src/com/android/settings/biometrics/BiometricUtils.java b/src/com/android/settings/biometrics/BiometricUtils.java
index 53892bd..3376d86 100644
--- a/src/com/android/settings/biometrics/BiometricUtils.java
+++ b/src/com/android/settings/biometrics/BiometricUtils.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.SensorProperties;
 import android.hardware.face.FaceManager;
 import android.hardware.face.FaceSensorPropertiesInternal;
@@ -65,6 +66,7 @@
  */
 public class BiometricUtils {
     private static final String TAG = "BiometricUtils";
+    public static final String EXTRA_ENROLL_REASON = BiometricManager.EXTRA_ENROLL_REASON;
 
     /** The character ' • ' to separate the setup choose options */
     public static final String SEPARATOR = " \u2022 ";
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
index 62e9757..6862bc9 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
@@ -265,6 +265,8 @@
         }
 
         intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
+        intent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
+                getIntent().getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1));
 
         if (!mSwitchDiversity.isChecked() && mAccessibilityEnabled) {
             FaceEnrollAccessibilityDialog dialog = FaceEnrollAccessibilityDialog.newInstance();
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
index e8bd0ef..da3689a 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
@@ -165,7 +165,7 @@
             disabledFeatures[i] = mDisabledFeatures.get(i);
         }
 
-        return new FaceEnrollSidecar(disabledFeatures);
+        return new FaceEnrollSidecar(disabledFeatures, getIntent());
     }
 
     @Override
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index eb50e08..b0996a4 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -484,6 +484,9 @@
     protected Intent getEnrollingIntent() {
         Intent intent = new Intent(this, FaceEnrollEducation.class);
         WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
+        intent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
+                getIntent().getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1));
+
         return intent;
     }
 
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
index de713dd..b7ba1b5 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.app.settings.SettingsEnums;
+import android.content.Intent;
 import android.hardware.face.FaceManager;
 
 import com.android.settings.biometrics.BiometricEnrollSidecar;
@@ -33,8 +34,11 @@
 
     private FaceUpdater mFaceUpdater;
 
-    public FaceEnrollSidecar(int[] disabledFeatures) {
+    private Intent mIntent;
+
+    public FaceEnrollSidecar(int[] disabledFeatures, Intent intent) {
         mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
+        mIntent = intent;
     }
 
     @Override
@@ -47,7 +51,7 @@
     public void startEnrollment() {
         super.startEnrollment();
         mFaceUpdater.enroll(mUserId, mToken, mEnrollmentCancel,
-                mEnrollmentCallback, mDisabledFeatures);
+                mEnrollmentCallback, mDisabledFeatures, mIntent);
     }
 
     private FaceManager.EnrollmentCallback mEnrollmentCallback
diff --git a/src/com/android/settings/biometrics/face/FaceUpdater.java b/src/com/android/settings/biometrics/face/FaceUpdater.java
index 57c1195..ddb6812 100644
--- a/src/com/android/settings/biometrics/face/FaceUpdater.java
+++ b/src/com/android/settings/biometrics/face/FaceUpdater.java
@@ -17,8 +17,10 @@
 package com.android.settings.biometrics.face;
 
 import android.content.Context;
+import android.content.Intent;
 import android.hardware.face.Face;
 import android.hardware.face.FaceEnrollCell;
+import android.hardware.face.FaceEnrollOptions;
 import android.hardware.face.FaceManager;
 import android.os.CancellationSignal;
 import android.view.Surface;
@@ -26,6 +28,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.settings.Utils;
+import com.android.settings.biometrics.BiometricUtils;
 import com.android.settings.safetycenter.BiometricsSafetySource;
 
 /**
@@ -49,19 +52,19 @@
 
     /** Wrapper around the {@link FaceManager#enroll} method. */
     public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
-            FaceManager.EnrollmentCallback callback, int[] disabledFeatures) {
+            FaceManager.EnrollmentCallback callback, int[] disabledFeatures, Intent intent) {
         this.enroll(userId, hardwareAuthToken, cancel,
                 new NotifyingEnrollmentCallback(mContext, callback), disabledFeatures,
-                null, false);
+                null, false, intent);
     }
 
     /** Wrapper around the {@link FaceManager#enroll} method. */
     public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
             FaceManager.EnrollmentCallback callback, int[] disabledFeatures,
-            @Nullable Surface previewSurface, boolean debugConsent) {
+            @Nullable Surface previewSurface, boolean debugConsent, Intent intent) {
         mFaceManager.enroll(userId, hardwareAuthToken, cancel,
                 new NotifyingEnrollmentCallback(mContext, callback), disabledFeatures,
-                previewSurface, debugConsent);
+                previewSurface, debugConsent, toFaceEnrollOptions(intent));
     }
 
     /** Wrapper around the {@link FaceManager#remove} method. */
@@ -135,4 +138,14 @@
             BiometricsSafetySource.onBiometricsChanged(mContext); // biometrics data changed
         }
     }
+
+    private FaceEnrollOptions toFaceEnrollOptions(Intent intent) {
+        final int reason = intent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1);
+        final FaceEnrollOptions.Builder builder = new FaceEnrollOptions.Builder();
+        builder.setEnrollReason(FaceEnrollOptions.ENROLL_REASON_UNKNOWN);
+        if (reason != -1) {
+            builder.setEnrollReason(reason);
+        }
+        return builder.build();
+    }
 }
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index 175e8f9..90b9346 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -352,7 +352,7 @@
     @Override
     protected BiometricEnrollSidecar getSidecar() {
         final FingerprintEnrollSidecar sidecar = new FingerprintEnrollSidecar(this,
-                FingerprintManager.ENROLL_ENROLL);
+                FingerprintManager.ENROLL_ENROLL, getIntent());
         return sidecar;
     }
 
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
index be3a769..6b7538a 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
@@ -292,6 +292,8 @@
     @Override
     protected Intent getFingerprintEnrollingIntent() {
         final Intent ret = super.getFingerprintEnrollingIntent();
+        ret.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
+                getIntent().getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1));
         if (Flags.udfpsEnrollCalibration()) {
             if (mCalibrator != null) {
                 ret.putExtras(mCalibrator.getExtrasForNextIntent(true));
@@ -349,7 +351,7 @@
                 FingerprintEnrollEnrolling.TAG_SIDECAR);
         if (mSidecar == null) {
             mSidecar = new FingerprintEnrollSidecar(this,
-                    FingerprintManager.ENROLL_FIND_SENSOR);
+                    FingerprintManager.ENROLL_FIND_SENSOR, getIntent());
             getSupportFragmentManager().beginTransaction()
                     .add(mSidecar, FingerprintEnrollEnrolling.TAG_SIDECAR)
                     .commitAllowingStateLoss();
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index 242b745..f92cfbf 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -59,7 +59,6 @@
 import java.util.List;
 
 public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
-
     private static final String TAG = "FingerprintIntro";
 
     @VisibleForTesting
@@ -388,6 +387,8 @@
                 intent.putExtras(mCalibrator.getExtrasForNextIntent(false));
             }
         }
+        intent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
+                getIntent().getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1));
         return intent;
     }
 
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
index 493302b..52d7d2b 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
@@ -21,6 +21,8 @@
 import android.app.Activity;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.content.Intent;
+import android.hardware.fingerprint.FingerprintEnrollOptions;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.SystemClock;
 import android.util.Log;
@@ -28,6 +30,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.biometrics.BiometricEnrollSidecar;
+import com.android.settings.biometrics.BiometricUtils;
+
+import com.google.android.setupcompat.util.WizardManagerHelper;
 
 /**
  * Sidecar fragment to handle the state around fingerprint enrollment.
@@ -39,15 +44,18 @@
     private @FingerprintManager.EnrollReason int mEnrollReason;
     private final MessageDisplayController mMessageDisplayController;
     private final boolean mMessageDisplayControllerFlag;
+    private final Intent mIntent;
 
     /**
      * Create a new FingerprintEnrollSidecar object.
-     * @param context associated context
+     *
+     * @param context      associated context
      * @param enrollReason reason for enrollment
      */
     public FingerprintEnrollSidecar(Context context,
-            @FingerprintManager.EnrollReason int enrollReason) {
+            @FingerprintManager.EnrollReason int enrollReason, Intent intent) {
         mEnrollReason = enrollReason;
+        mIntent = intent;
 
         int helpMinimumDisplayTime = context.getResources().getInteger(
                 R.integer.enrollment_help_minimum_time_display);
@@ -85,14 +93,21 @@
             return;
         }
 
+        if (mIntent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1) == -1) {
+            final boolean isSuw = WizardManagerHelper.isAnySetupWizard(mIntent);
+            mIntent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
+                    isSuw ? FingerprintEnrollOptions.ENROLL_REASON_SUW :
+                            FingerprintEnrollOptions.ENROLL_REASON_SETTINGS);
+        }
+
         if (mEnrollReason == ENROLL_ENROLL && mMessageDisplayControllerFlag) {
             //API calls need to be processed for {@link FingerprintEnrollEnrolling}
             mFingerprintUpdater.enroll(mToken, mEnrollmentCancel, mUserId,
-                    mMessageDisplayController, mEnrollReason);
+                    mMessageDisplayController, mEnrollReason, mIntent);
         } else {
             //No processing required for {@link FingerprintEnrollFindSensor}
             mFingerprintUpdater.enroll(mToken, mEnrollmentCancel, mUserId, mEnrollmentCallback,
-                    mEnrollReason);
+                    mEnrollReason, mIntent);
         }
     }
 
@@ -100,7 +115,8 @@
         mEnrollReason = enrollReason;
     }
 
-    @VisibleForTesting FingerprintManager.EnrollmentCallback mEnrollmentCallback
+    @VisibleForTesting
+    FingerprintManager.EnrollmentCallback mEnrollmentCallback
             = new FingerprintManager.EnrollmentCallback() {
 
         @Override
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java b/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java
index 306b1a3..ea9abf1 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java
@@ -17,13 +17,16 @@
 package com.android.settings.biometrics.fingerprint;
 
 import android.content.Context;
+import android.content.Intent;
 import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintEnrollOptions;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.CancellationSignal;
 
 import androidx.annotation.Nullable;
 
 import com.android.settings.Utils;
+import com.android.settings.biometrics.BiometricUtils;
 import com.android.settings.safetycenter.BiometricsSafetySource;
 
 /**
@@ -48,9 +51,10 @@
     /** Wrapper around the {@link FingerprintManager#enroll} method. */
     public void enroll(byte [] hardwareAuthToken, CancellationSignal cancel, int userId,
             FingerprintManager.EnrollmentCallback callback,
-            @FingerprintManager.EnrollReason int enrollReason) {
+            @FingerprintManager.EnrollReason int enrollReason, Intent intent) {
         mFingerprintManager.enroll(hardwareAuthToken, cancel, userId,
-                new NotifyingEnrollmentCallback(mContext, callback), enrollReason);
+                new NotifyingEnrollmentCallback(mContext, callback), enrollReason,
+                toFingerprintEnrollOptions(intent));
     }
 
     /** Wrapper around the {@link FingerprintManager#remove} method. */
@@ -138,4 +142,14 @@
             BiometricsSafetySource.onBiometricsChanged(mContext); // biometrics data changed
         }
     }
+
+    private FingerprintEnrollOptions toFingerprintEnrollOptions(Intent intent) {
+        final int reason = intent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1);
+        final FingerprintEnrollOptions.Builder builder = new FingerprintEnrollOptions.Builder();
+        builder.setEnrollReason(FingerprintEnrollOptions.ENROLL_REASON_UNKNOWN);
+        if (reason != -1) {
+            builder.setEnrollReason(reason);
+        }
+        return builder.build();
+    }
 }
diff --git a/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java b/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java
index abc31c9..60ced6e 100644
--- a/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java
+++ b/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImpl.java
@@ -33,11 +33,14 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 
 import java.util.function.Function;
 
 public class SfpsEnrollmentFeatureImpl implements SfpsEnrollmentFeature {
+    @VisibleForTesting
+    public static final int HELP_ANIMATOR_DURATION = 550;
 
     @Nullable
     private FingerprintManager mFingerprintManager = null;
@@ -96,12 +99,11 @@
     @Override
     public Animator getHelpAnimator(@NonNull View target) {
         final float translationX = 40;
-        final int duration = 550;
         final ObjectAnimator help = ObjectAnimator.ofFloat(target,
                 "translationX" /* propertyName */,
                 0, translationX, -1 * translationX, translationX, 0f);
         help.setInterpolator(new AccelerateInterpolator());
-        help.setDuration(duration);
+        help.setDuration(HELP_ANIMATOR_DURATION);
         help.setAutoCancel(false);
         return help;
     }
diff --git a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractorImpl.kt b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractorImpl.kt
index 135a36c..900f7cf 100644
--- a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractorImpl.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractorImpl.kt
@@ -18,12 +18,16 @@
 
 import android.content.Context
 import android.content.Intent
+import android.hardware.biometrics.BiometricConstants;
+import android.hardware.biometrics.BiometricFingerprintConstants
+import android.hardware.fingerprint.FingerprintEnrollOptions;
 import android.hardware.fingerprint.FingerprintManager
 import android.hardware.fingerprint.FingerprintManager.GenerateChallengeCallback
 import android.hardware.fingerprint.FingerprintManager.RemovalCallback
 import android.os.CancellationSignal
 import android.util.Log
 import com.android.settings.biometrics.GatekeeperPasswordProvider
+import com.android.settings.biometrics.BiometricUtils
 import com.android.settings.biometrics.fingerprint2.conversion.Util.toEnrollError
 import com.android.settings.biometrics.fingerprint2.conversion.Util.toOriginalReason
 import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepository
@@ -35,6 +39,8 @@
 import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
 import com.android.settings.biometrics.fingerprint2.lib.model.SetupWizard
 import com.android.settings.password.ChooseLockSettingsHelper
+import com.android.systemui.biometrics.shared.model.toFingerprintSensor
+import com.google.android.setupcompat.util.WizardManagerHelper
 import kotlin.coroutines.resume
 import kotlin.coroutines.suspendCoroutine
 import kotlinx.coroutines.CancellableContinuation
@@ -60,6 +66,7 @@
   private val gatekeeperPasswordProvider: GatekeeperPasswordProvider,
   private val pressToAuthInteractor: PressToAuthInteractor,
   private val fingerprintFlow: FingerprintFlow,
+  private val intent: Intent,
 ) : FingerprintManagerInteractor {
 
   private val maxFingerprints =
@@ -158,12 +165,21 @@
       }
 
     val cancellationSignal = CancellationSignal()
+
+    if (intent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1) === -1) {
+      val isSuw: Boolean = WizardManagerHelper.isAnySetupWizard(intent)
+      intent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
+      if (isSuw) FingerprintEnrollOptions.ENROLL_REASON_SUW else
+        FingerprintEnrollOptions.ENROLL_REASON_SETTINGS)
+    }
+
     fingerprintManager.enroll(
       hardwareAuthToken,
       cancellationSignal,
       applicationContext.userId,
       enrollmentCallback,
       enrollReason.toOriginalReason(),
+      toFingerprintEnrollOptions(intent)
     )
     awaitClose {
       // If the stream has not been ended, and the user has stopped collecting the flow
@@ -244,4 +260,15 @@
         applicationContext.userId,
       )
     }
+
+  private fun toFingerprintEnrollOptions(intent: Intent): FingerprintEnrollOptions {
+    val reason: Int =
+      intent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1)
+    val builder: FingerprintEnrollOptions.Builder = FingerprintEnrollOptions.Builder()
+    builder.setEnrollReason(FingerprintEnrollOptions.ENROLL_REASON_UNKNOWN)
+    if (reason != -1) {
+      builder.setEnrollReason(reason)
+    }
+    return builder.build()
+  }
 }
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt
index 9f3935b..65030de 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt
@@ -191,6 +191,7 @@
         GatekeeperPasswordProvider(LockPatternUtils(context)),
         pressToAuthInteractor,
         enrollType,
+        getIntent(),
       )
 
     var challenge: Long? = intent.getExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE) as Long?
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/settings/fragment/FingerprintSettingsV2Fragment.kt b/src/com/android/settings/biometrics/fingerprint2/ui/settings/fragment/FingerprintSettingsV2Fragment.kt
index a5f2021..bd90524 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/settings/fragment/FingerprintSettingsV2Fragment.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/settings/fragment/FingerprintSettingsV2Fragment.kt
@@ -232,6 +232,7 @@
         GatekeeperPasswordProvider(LockPatternUtils(context.applicationContext)),
         pressToAuthInteractor,
         Settings,
+        getIntent()
       )
 
     val token = intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN)
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
index 9b25ee8..1cfec52 100644
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
+++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
@@ -23,6 +23,7 @@
 import static com.android.settings.biometrics2.ui.model.EnrollmentProgress.INITIAL_STEPS;
 
 import android.app.Application;
+import android.content.Intent;
 import android.content.res.Resources;
 import android.hardware.fingerprint.FingerprintManager.EnrollReason;
 import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
@@ -212,10 +213,11 @@
                     res.getBoolean(R.bool.enrollment_progress_priority_over_help),
                     res.getBoolean(R.bool.enrollment_prioritize_acquire_messages),
                     res.getInteger(R.integer.enrollment_collect_time));
-            mFingerprintUpdater.enroll(mToken, mCancellationSignal, mUserId, callback, reason);
+            mFingerprintUpdater.enroll(mToken, mCancellationSignal, mUserId, callback, reason,
+                    new Intent());
         } else {
             mFingerprintUpdater.enroll(mToken, mCancellationSignal, mUserId, mEnrollmentCallback,
-                    reason);
+                    reason, new Intent());
         }
         return mCancellationSignal;
     }
diff --git a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
index 23ba4f6..8250f70 100644
--- a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
@@ -23,7 +23,7 @@
 import androidx.preference.Preference;
 
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
-import com.android.settings.connecteddevice.audiosharing.AudioSharingUtils;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 
@@ -72,6 +72,32 @@
         if (isDeviceConnected(cachedDevice) && isDeviceInCachedDevicesList(cachedDevice)) {
             Log.d(TAG, "isFilterMatched() current audio profile : " + currentAudioProfile);
 
+            // If device is LE Audio, it is compatible with HFP and A2DP.
+            // It would show in Available Devices group if the audio sharing flag is disabled or
+            // the device is not in the audio sharing session.
+            if (cachedDevice.isConnectedLeAudioDevice()) {
+                boolean isAudioSharingFilterMatched =
+                        FeatureFactory.getFeatureFactory()
+                                .getAudioSharingFeatureProvider()
+                                .isAudioSharingFilterMatched(cachedDevice, mLocalManager);
+                if (!isAudioSharingFilterMatched) {
+                    Log.d(
+                            TAG,
+                            "isFilterMatched() device : "
+                                    + cachedDevice.getName()
+                                    + ", the LE Audio profile is connected and not in sharing "
+                                    + "if broadcast enabled.");
+                    return true;
+                } else {
+                    Log.d(
+                            TAG,
+                            "Filter out device : "
+                                    + cachedDevice.getName()
+                                    + ", it is in audio sharing.");
+                    return false;
+                }
+            }
+
             // If device is Hearing Aid, it is compatible with HFP and A2DP.
             // It would show in Available Devices group.
             if (cachedDevice.isConnectedAshaHearingAidDevice()) {
@@ -82,20 +108,7 @@
                                 + ", the Hearing Aid profile is connected.");
                 return true;
             }
-            // If device is LE Audio, it is compatible with HFP and A2DP.
-            // It would show in Available Devices group if the audio sharing flag is disabled or
-            // the device is not in the audio sharing session.
-            if (cachedDevice.isConnectedLeAudioDevice()) {
-                if (!AudioSharingUtils.isFeatureEnabled()
-                        || !AudioSharingUtils.hasBroadcastSource(cachedDevice, mLocalManager)) {
-                    Log.d(
-                            TAG,
-                            "isFilterMatched() device : "
-                                    + cachedDevice.getName()
-                                    + ", the LE Audio profile is connected and not in sharing.");
-                    return true;
-                }
-            }
+
             // According to the current audio profile type,
             // this page will show the bluetooth device that have corresponding profile.
             // For example:
@@ -125,13 +138,9 @@
         mMetricsFeatureProvider.logClickedPreference(preference, mMetricsCategory);
         final CachedBluetoothDevice device =
                 ((BluetoothDevicePreference) preference).getBluetoothDevice();
-        if (AudioSharingUtils.isFeatureEnabled()
-                && AudioSharingUtils.isBroadcasting(mLocalBtManager)) {
-            if (DBG) {
-                Log.d(TAG, "onPreferenceClick stop broadcasting.");
-            }
-            AudioSharingUtils.stopBroadcasting(mLocalBtManager);
-        }
+        FeatureFactory.getFeatureFactory()
+                .getAudioSharingFeatureProvider()
+                .handleMediaDeviceOnClick(mLocalManager);
         return device.setActive();
     }
 
diff --git a/src/com/android/settings/bluetooth/BluetoothAutoOnPreferenceController.java b/src/com/android/settings/bluetooth/BluetoothAutoOnPreferenceController.java
new file mode 100644
index 0000000..f6f62e8
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothAutoOnPreferenceController.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2024 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.bluetooth;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.flags.Flags;
+import com.android.settingslib.utils.ThreadUtils;
+
+public class BluetoothAutoOnPreferenceController extends TogglePreferenceController
+        implements LifecycleObserver, OnStart, OnStop {
+    private static final String TAG = "BluetoothAutoOnPreferenceController";
+    @VisibleForTesting static final String PREF_KEY = "bluetooth_auto_on_settings_toggle";
+    static final String SETTING_NAME = "bluetooth_automatic_turn_on";
+    static final int UNSET = -1;
+    @VisibleForTesting static final int ENABLED = 1;
+    @VisibleForTesting static final int DISABLED = 0;
+    private final ContentObserver mContentObserver =
+            new ContentObserver(new Handler(/* async= */ true)) {
+                @Override
+                public void onChange(boolean selfChange) {
+                    var unused =
+                            ThreadUtils.postOnBackgroundThread(
+                                    () -> {
+                                        updateValue();
+                                        mContext.getMainExecutor()
+                                                .execute(
+                                                        () -> {
+                                                            if (mPreference != null) {
+                                                                updateState(mPreference);
+                                                            }
+                                                        });
+                                    });
+                }
+            };
+    private int mAutoOnValue = UNSET;
+    @Nullable private TwoStatePreference mPreference;
+
+    public BluetoothAutoOnPreferenceController(
+            @NonNull Context context, @NonNull String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public void onStart() {
+        mContext.getContentResolver()
+                .registerContentObserver(
+                        Settings.Secure.getUriFor(SETTING_NAME),
+                        /* notifyForDescendants= */ false,
+                        mContentObserver);
+    }
+
+    @Override
+    public void onStop() {
+        mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (!Flags.bluetoothQsTileDialogAutoOnToggle()) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
+        updateValue();
+        return mAutoOnValue != UNSET ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public void displayPreference(@NonNull PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return PREF_KEY;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return mAutoOnValue == ENABLED;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        if (getAvailabilityStatus() != AVAILABLE) {
+            Log.w(TAG, "Trying to set toggle value while feature not available.");
+            return false;
+        }
+        var unused =
+                ThreadUtils.postOnBackgroundThread(
+                        () -> {
+                            boolean updated =
+                                    Settings.Secure.putIntForUser(
+                                            mContext.getContentResolver(),
+                                            SETTING_NAME,
+                                            isChecked ? ENABLED : DISABLED,
+                                            UserHandle.myUserId());
+                            if (updated) {
+                                updateValue();
+                            }
+                        });
+        return true;
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        return 0;
+    }
+
+    private void updateValue() {
+        mAutoOnValue =
+                Settings.Secure.getIntForUser(
+                        mContext.getContentResolver(), SETTING_NAME, UNSET, UserHandle.myUserId());
+    }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java b/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java
index 6fd5070..ac55758 100644
--- a/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java
+++ b/src/com/android/settings/bluetooth/BluetoothSwitchPreferenceController.java
@@ -15,8 +15,13 @@
  */
 package com.android.settings.bluetooth;
 
+import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.SETTING_NAME;
+import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.UNSET;
+
 import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.view.View;
 
 import androidx.annotation.VisibleForTesting;
@@ -29,6 +34,7 @@
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.flags.Flags;
 import com.android.settingslib.widget.FooterPreference;
 
 /**
@@ -36,8 +42,11 @@
  * is delegated to the SwitchWidgetController it uses.
  */
 public class BluetoothSwitchPreferenceController
-        implements LifecycleObserver, OnStart, OnStop,
-        SwitchWidgetController.OnSwitchChangeListener, View.OnClickListener {
+        implements LifecycleObserver,
+                OnStart,
+                OnStop,
+                SwitchWidgetController.OnSwitchChangeListener,
+                View.OnClickListener {
 
     private BluetoothEnabler mBluetoothEnabler;
     private RestrictionUtils mRestrictionUtils;
@@ -46,18 +55,21 @@
     private FooterPreference mFooterPreference;
     private boolean mIsAlwaysDiscoverable;
 
-    @VisibleForTesting
-    AlwaysDiscoverable mAlwaysDiscoverable;
+    @VisibleForTesting AlwaysDiscoverable mAlwaysDiscoverable;
 
-    public BluetoothSwitchPreferenceController(Context context,
+    public BluetoothSwitchPreferenceController(
+            Context context,
             SwitchWidgetController switchController,
             FooterPreference footerPreference) {
         this(context, new RestrictionUtils(), switchController, footerPreference);
     }
 
     @VisibleForTesting
-    public BluetoothSwitchPreferenceController(Context context, RestrictionUtils restrictionUtils,
-            SwitchWidgetController switchController, FooterPreference footerPreference) {
+    public BluetoothSwitchPreferenceController(
+            Context context,
+            RestrictionUtils restrictionUtils,
+            SwitchWidgetController switchController,
+            FooterPreference footerPreference) {
         mRestrictionUtils = restrictionUtils;
         mSwitch = switchController;
         mContext = context;
@@ -66,11 +78,13 @@
         mSwitch.setupView();
         updateText(mSwitch.isChecked());
 
-        mBluetoothEnabler = new BluetoothEnabler(context,
-                switchController,
-                FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(),
-                SettingsEnums.ACTION_SETTINGS_MASTER_SWITCH_BLUETOOTH_TOGGLE,
-                mRestrictionUtils);
+        mBluetoothEnabler =
+                new BluetoothEnabler(
+                        context,
+                        switchController,
+                        FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(),
+                        SettingsEnums.ACTION_SETTINGS_MASTER_SWITCH_BLUETOOTH_TOGGLE,
+                        mRestrictionUtils);
         mBluetoothEnabler.setToggleCallback(this);
         mAlwaysDiscoverable = new AlwaysDiscoverable(context);
     }
@@ -97,8 +111,8 @@
     /**
      * Set whether the device can be discovered. By default the value will be {@code false}.
      *
-     * @param isAlwaysDiscoverable {@code true} if the device can be discovered,
-     *     otherwise {@code false}
+     * @param isAlwaysDiscoverable {@code true} if the device can be discovered, otherwise {@code
+     *     false}
      */
     public void setAlwaysDiscoverable(boolean isAlwaysDiscoverable) {
         mIsAlwaysDiscoverable = isAlwaysDiscoverable;
@@ -119,15 +133,35 @@
                 .launch();
     }
 
-    @VisibleForTesting void updateText(boolean isChecked) {
+    @VisibleForTesting
+    void updateText(boolean isChecked) {
         if (!isChecked && Utils.isBluetoothScanningEnabled(mContext)) {
-            mFooterPreference.setTitle(R.string.bluetooth_scanning_on_info_message);
+            if (isAutoOnFeatureAvailable()) {
+                mFooterPreference.setTitle(
+                        R.string.bluetooth_scanning_on_info_message_auto_on_available);
+            } else {
+                mFooterPreference.setTitle(R.string.bluetooth_scanning_on_info_message);
+            }
             mFooterPreference.setLearnMoreText(mContext.getString(R.string.bluetooth_scan_change));
             mFooterPreference.setLearnMoreAction(v -> onClick(v));
         } else {
-            mFooterPreference.setTitle(R.string.bluetooth_empty_list_bluetooth_off);
+            if (isAutoOnFeatureAvailable()) {
+                mFooterPreference.setTitle(
+                        R.string.bluetooth_empty_list_bluetooth_off_auto_on_available);
+            } else {
+                mFooterPreference.setTitle(R.string.bluetooth_empty_list_bluetooth_off);
+            }
             mFooterPreference.setLearnMoreText("");
             mFooterPreference.setLearnMoreAction(null);
         }
     }
+
+    private boolean isAutoOnFeatureAvailable() {
+        if (!Flags.bluetoothQsTileDialogAutoOnToggle()) {
+            return false;
+        }
+        return Settings.Secure.getIntForUser(
+                        mContext.getContentResolver(), SETTING_NAME, UNSET, UserHandle.myUserId())
+                != UNSET;
+    }
 }
diff --git a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.kt b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.kt
index 77a80b8..3224f94 100644
--- a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.kt
+++ b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.kt
@@ -34,8 +34,10 @@
 import androidx.preference.PreferenceGroup
 import com.android.settings.R
 import com.android.settings.dashboard.RestrictedDashboardFragment
+import com.android.settings.flags.Flags
 import com.android.settingslib.bluetooth.BluetoothCallback
 import com.android.settingslib.bluetooth.BluetoothDeviceFilter
+import com.android.settingslib.bluetooth.BluetoothUtils
 import com.android.settingslib.bluetooth.CachedBluetoothDevice
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager
 import com.android.settingslib.bluetooth.LocalBluetoothManager
@@ -217,6 +219,14 @@
             )
             return
         }
+        if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
+            if (cachedDevice.device.bondState == BluetoothDevice.BOND_BONDED
+                && BluetoothUtils.isExclusivelyManagedBluetoothDevice(
+                    prefContext, cachedDevice.device)) {
+                Log.d(TAG, "Trying to create preference for a exclusively managed device")
+                return
+            }
+        }
         // Only add device preference when it's not found in the map and there's no other state
         // message showing in the list
         val preference = devicePreferenceMap.computeIfAbsent(cachedDevice) {
diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
index 27001d6..2798be4 100644
--- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
@@ -22,12 +22,13 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
 
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
-import com.android.settings.connecteddevice.audiosharing.AudioSharingDevicePreferenceController;
 import com.android.settings.connecteddevice.audiosharing.AudioSharingUtils;
 import com.android.settings.core.SettingsUIDeviceConfig;
 import com.android.settings.dashboard.DashboardFragment;
@@ -36,8 +37,12 @@
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.slices.SlicePreferenceController;
 import com.android.settingslib.bluetooth.HearingAidStatsLogUtils;
+import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.search.SearchIndexable;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
 public class ConnectedDeviceDashboardFragment extends DashboardFragment {
 
@@ -87,9 +92,6 @@
                             + ", action : "
                             + action);
         }
-        if (AudioSharingUtils.isFeatureEnabled()) {
-            use(AudioSharingDevicePreferenceController.class).init(this);
-        }
         use(AvailableMediaDeviceGroupController.class).init(this);
         use(ConnectedDeviceGroupController.class).init(this);
         use(PreviouslyConnectedDevicePreferenceController.class).init(this);
@@ -112,6 +114,29 @@
         }
     }
 
+    @Override
+    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+        return buildPreferenceControllers(context, /* fragment= */ this, getSettingsLifecycle());
+    }
+
+    private static List<AbstractPreferenceController> buildPreferenceControllers(
+            Context context,
+            @Nullable ConnectedDeviceDashboardFragment fragment,
+            @Nullable Lifecycle lifecycle) {
+        final List<AbstractPreferenceController> controllers = new ArrayList<>();
+        if (AudioSharingUtils.isFeatureEnabled()) {
+            AbstractPreferenceController audioSharingController =
+                    FeatureFactory.getFeatureFactory()
+                            .getAudioSharingFeatureProvider()
+                            .createAudioSharingDevicePreferenceController(
+                                    context, fragment, lifecycle);
+            if (audioSharingController != null) {
+                controllers.add(audioSharingController);
+            }
+        }
+        return controllers;
+    }
+
     @VisibleForTesting
     boolean isAlwaysDiscoverable(String callingAppPackageName, String action) {
         return TextUtils.equals(SLICE_ACTION, action)
@@ -122,5 +147,12 @@
 
     /** For Search. */
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-            new BaseSearchIndexProvider(R.xml.connected_devices);
+            new BaseSearchIndexProvider(R.xml.connected_devices) {
+                @Override
+                public List<AbstractPreferenceController> createPreferenceControllers(
+                        Context context) {
+                    return buildPreferenceControllers(
+                            context, /* fragment= */ null, /* lifecycle= */ null);
+                }
+            };
 }
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProvider.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProvider.java
new file mode 100644
index 0000000..c71a368
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProvider.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.connecteddevice.audiosharing;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.Lifecycle;
+
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+/** Feature provider for the audio sharing related features, */
+public interface AudioSharingFeatureProvider {
+
+    /** Create audio sharing device preference controller. */
+    @Nullable
+    AbstractPreferenceController createAudioSharingDevicePreferenceController(
+            @NonNull Context context,
+            @Nullable DashboardFragment fragment,
+            @Nullable Lifecycle lifecycle);
+
+    /**
+     * Check if the device match the audio sharing filter.
+     *
+     * <p>The filter is used to filter device in "Media devices" section.
+     */
+    boolean isAudioSharingFilterMatched(
+            @NonNull CachedBluetoothDevice cachedDevice, LocalBluetoothManager localBtManager);
+
+    /** Handle preference onClick in "Media devices" section. */
+    void handleMediaDeviceOnClick(LocalBluetoothManager localBtManager);
+}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImpl.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImpl.java
new file mode 100644
index 0000000..05a6a63
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.connecteddevice.audiosharing;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.Lifecycle;
+
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+public class AudioSharingFeatureProviderImpl implements AudioSharingFeatureProvider {
+
+    @Nullable
+    @Override
+    public AbstractPreferenceController createAudioSharingDevicePreferenceController(
+            @NonNull Context context,
+            @Nullable DashboardFragment fragment,
+            @Nullable Lifecycle lifecycle) {
+        return null;
+    }
+
+    @Override
+    public boolean isAudioSharingFilterMatched(
+            @NonNull CachedBluetoothDevice cachedDevice, LocalBluetoothManager localBtManager) {
+        return false;
+    }
+
+    @Override
+    public void handleMediaDeviceOnClick(LocalBluetoothManager localBtManager) {}
+}
diff --git a/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java b/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
index 7a7eb8c..b3e66a9 100644
--- a/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
+++ b/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
@@ -20,7 +20,9 @@
 import android.os.UserHandle;
 import android.view.View;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
@@ -36,6 +38,7 @@
 
 public class UnrestrictedDataAccessPreference extends AppSwitchPreference implements
         DataSaverBackend.Listener {
+    private static final String ECM_SETTING_IDENTIFIER = "android:unrestricted_data_access";
 
     private final ApplicationsState mApplicationsState;
     private final AppEntry mEntry;
@@ -58,6 +61,7 @@
         mParentFragment = parentFragment;
         setDisabledByAdmin(checkIfMeteredDataUsageUserControlDisabled(
                 context, entry.info.packageName, UserHandle.getUserId(entry.info.uid)));
+        mHelper.checkEcmRestrictionAndSetDisabled(ECM_SETTING_IDENTIFIER, entry.info.packageName);
         updateState();
         setKey(generateKey(mEntry));
 
@@ -166,10 +170,24 @@
         return mHelper.isDisabledByAdmin();
     }
 
+    @VisibleForTesting
+    boolean isDisabledByEcm() {
+        return mHelper.isDisabledByEcm();
+    }
+
     public void setDisabledByAdmin(EnforcedAdmin admin) {
         mHelper.setDisabledByAdmin(admin);
     }
 
+    /**
+     * Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this
+     * package. Marks the preference as disabled if so.
+     * @param packageName the package to check the restriction for
+     */
+    public void checkEcmRestrictionAndSetDisabled(@NonNull String packageName) {
+        mHelper.checkEcmRestrictionAndSetDisabled(ECM_SETTING_IDENTIFIER, packageName);
+    }
+
     // Sets UI state based on allowlist/denylist status.
     public void updateState() {
         setTitle(mEntry.label);
@@ -179,7 +197,8 @@
                 setSummary(com.android.settingslib.widget.restricted.R.string.disabled_by_admin);
             } else if (mDataUsageState.isDataSaverDenylisted) {
                 setSummary(R.string.restrict_background_blocklisted);
-            } else {
+            // If disabled by ECM, the summary is set directly by the switch.
+            } else if (!isDisabledByEcm()) {
                 setSummary("");
             }
         }
diff --git a/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java b/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java
index fd2fcda..0fb30a8 100644
--- a/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java
+++ b/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java
@@ -151,6 +151,7 @@
             } else {
                 preference.setDisabledByAdmin(checkIfMeteredDataUsageUserControlDisabled(mContext,
                         entry.info.packageName, UserHandle.getUserId(entry.info.uid)));
+                preference.checkEcmRestrictionAndSetDisabled(entry.info.packageName);
                 preference.updateState();
             }
             preference.setOrder(i);
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
index b1ffcf1..887fc32 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
+import android.content.pm.UserProperties;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.VpnManager;
@@ -220,6 +221,9 @@
     public int getNumberOfActiveDeviceAdminsForCurrentUserAndManagedProfile() {
         int activeAdmins = 0;
         for (final UserInfo userInfo : mUm.getProfiles(MY_USER_ID)) {
+            if (shouldSkipProfile(userInfo)) {
+                continue;
+            }
             final List<ComponentName> activeAdminsForUser
                     = mDpm.getActiveAdminsAsUser(userInfo.id);
             if (activeAdminsForUser != null) {
@@ -250,6 +254,14 @@
         return false;
     }
 
+    private boolean shouldSkipProfile(UserInfo userInfo) {
+        return android.os.Flags.allowPrivateProfile()
+                && android.multiuser.Flags.handleInterleavedSettingsForPrivateSpace()
+                && userInfo.isQuietModeEnabled()
+                && mUm.getUserProperties(userInfo.getUserHandle()).getShowInQuietMode()
+                        == UserProperties.SHOW_IN_QUIET_MODE_HIDDEN;
+    }
+
     private Intent getParentalControlsIntent() {
         final ComponentName componentName =
                 mDpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(new UserHandle(MY_USER_ID));
diff --git a/src/com/android/settings/inputmethod/TrackpadTouchGestureSettings.java b/src/com/android/settings/inputmethod/TrackpadTouchGestureSettings.java
index 44d77a3..9a4b90f 100644
--- a/src/com/android/settings/inputmethod/TrackpadTouchGestureSettings.java
+++ b/src/com/android/settings/inputmethod/TrackpadTouchGestureSettings.java
@@ -52,7 +52,7 @@
     }
 
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-            new BaseSearchIndexProvider(R.xml.trackpad_settings) {
+            new BaseSearchIndexProvider(R.xml.trackpad_gesture_settings) {
                 @Override
                 protected boolean isPageSearchEnabled(Context context) {
                     return FeatureFlagUtils
diff --git a/src/com/android/settings/network/SimOnboardingActivity.kt b/src/com/android/settings/network/SimOnboardingActivity.kt
index f5dc886..abeeb6c 100644
--- a/src/com/android/settings/network/SimOnboardingActivity.kt
+++ b/src/com/android/settings/network/SimOnboardingActivity.kt
@@ -22,19 +22,25 @@
 import android.os.Bundle
 import android.telephony.SubscriptionManager
 import android.util.Log
-import android.view.MotionEvent
 import androidx.activity.compose.setContent
 import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.SignalCellularAlt
+import androidx.compose.material3.AlertDialogDefaults
+import androidx.compose.material3.BasicAlertDialog
 import androidx.compose.material3.Button
+import androidx.compose.material3.CircularProgressIndicator
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.Icon
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.ModalBottomSheet
 import androidx.compose.material3.SheetState
+import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
 import androidx.compose.material3.rememberModalBottomSheetState
 import androidx.compose.runtime.Composable
@@ -58,6 +64,7 @@
 import com.android.settingslib.spa.SpaBaseDialogActivity
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
+import com.android.settingslib.spa.widget.dialog.getDialogWidth
 import com.android.settingslib.spa.widget.ui.SettingsTitle
 import com.android.settingslib.spaprivileged.framework.common.userManager
 import kotlinx.coroutines.CoroutineScope
@@ -193,26 +200,43 @@
         }
     }
 
+    @OptIn(ExperimentalMaterial3Api::class)
     @Composable
     fun ProgressDialogImpl() {
-        // TODO: 1. Create the SPA's ProgressDialog and using SPA's widget
-        val dialog: ProgressDialog = object : ProgressDialog(this) {
-            override fun onTouchEvent(event: MotionEvent): Boolean {
-                return true
+        if(showDialog.value) {
+            // TODO: Create the SPA's ProgressDialog and using SPA's widget
+            BasicAlertDialog(
+                onDismissRequest = {},
+                modifier = Modifier.width(
+                    getDialogWidth()
+                ),
+            ) {
+                Surface(
+                    color = AlertDialogDefaults.containerColor,
+                    shape = AlertDialogDefaults.shape
+                ) {
+                    Row(
+                        modifier = Modifier
+                            .fillMaxWidth()
+                            .padding(SettingsDimension.itemPaddingStart),
+                        verticalAlignment = Alignment.CenterVertically
+                    ) {
+                        CircularProgressIndicator()
+                        Column(modifier = Modifier
+                                .padding(start = SettingsDimension.itemPaddingStart)) {
+                            SettingsTitle(
+                                stringResource(
+                                    R.string.sim_onboarding_progressbar_turning_sim_on,
+                                    onboardingService.targetSubInfo?.displayName ?: ""
+                                )
+                            )
+                        }
+                    }
+                }
             }
         }
-        dialog.setMessage(
-            stringResource(
-                R.string.sim_onboarding_progressbar_turning_sim_on,
-                onboardingService.targetSubInfo?.displayName ?: ""
-            )
-        )
-        dialog.setCancelable(false)
-
-        if(showDialog.value) {
-            dialog.show()
-        }
     }
+
     @Composable
     fun registerSidecarReceiverFlow(){
         switchToEuiccSubscriptionSidecar?.sidecarReceiverFlow()
diff --git a/src/com/android/settings/network/SimOnboardingService.kt b/src/com/android/settings/network/SimOnboardingService.kt
index 8679385..f33abf6 100644
--- a/src/com/android/settings/network/SimOnboardingService.kt
+++ b/src/com/android/settings/network/SimOnboardingService.kt
@@ -45,7 +45,6 @@
     var activeSubInfoList: List<SubscriptionInfo> = listOf()
     var slotInfoList: List<UiccSlotInfo> = listOf()
     var uiccCardInfoList: List<UiccCardInfo> = listOf()
-    var selectedSubInfoList: MutableList<SubscriptionInfo> = mutableListOf()
     var targetPrimarySimCalls: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
     var targetPrimarySimTexts: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
     var targetPrimarySimMobileData: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
@@ -56,10 +55,8 @@
                 Log.w(TAG, "No DDS")
                 return SubscriptionManager.INVALID_SUBSCRIPTION_ID
             }
-            return selectedSubInfoList
-                .filter { info ->
-                    (info.simSlotIndex != -1) && (info.subscriptionId != targetPrimarySimMobileData)
-                }
+            return userSelectedSubInfoList
+                .filter { info -> info.subscriptionId != targetPrimarySimMobileData }
                 .map { it.subscriptionId }
                 .firstOrNull() ?: SubscriptionManager.INVALID_SUBSCRIPTION_ID
         }
@@ -118,7 +115,6 @@
             && targetSubInfo != null
             && activeSubInfoList.isNotEmpty()
             && slotInfoList.isNotEmpty()
-            && selectedSubInfoList.isNotEmpty()
     }
 
     fun clear() {
@@ -128,7 +124,6 @@
         activeSubInfoList = listOf()
         slotInfoList = listOf()
         uiccCardInfoList = listOf()
-        selectedSubInfoList = mutableListOf()
         targetPrimarySimCalls = -1
         targetPrimarySimTexts = -1
         targetPrimarySimMobileData = -1
@@ -151,7 +146,8 @@
         ThreadUtils.postOnBackgroundThread {
             activeSubInfoList = SubscriptionUtil.getActiveSubscriptions(subscriptionManager)
             availableSubInfoList = SubscriptionUtil.getAvailableSubscriptions(context)
-            targetSubInfo = availableSubInfoList.find { subInfo -> subInfo.subscriptionId == targetSubId }
+            targetSubInfo =
+                availableSubInfoList.find { subInfo -> subInfo.subscriptionId == targetSubId }
             targetSubInfo?.let { userSelectedSubInfoList.add(it) }
             Log.d(
                 TAG, "targetSubId: $targetSubId" + ", targetSubInfo: $targetSubInfo" +
@@ -186,7 +182,6 @@
             targetSubInfo?.let { list.add(it) }
         }
 
-        Log.d(TAG, "list: $list")
         return list.toList()
     }
 
@@ -206,7 +201,10 @@
             return
         }
         renameMutableMap[subInfo.subscriptionId] = newName
-        Log.d(TAG, "renameMutableMap add ${subInfo.subscriptionId} & $newName into: $renameMutableMap")
+        Log.d(
+            TAG,
+            "renameMutableMap add ${subInfo.subscriptionId} & $newName into: $renameMutableMap"
+        )
     }
 
     fun getSubscriptionInfoDisplayName(subInfo: SubscriptionInfo): String {
@@ -278,11 +276,18 @@
                 targetPrimarySimMobileData
             )
 
-
-            val telephonyManagerForNonDds: TelephonyManager? =
-                context.getSystemService(TelephonyManager::class.java)
-                    ?.createForSubscriptionId(targetNonDds)
-            setAutomaticData(telephonyManagerForNonDds, targetPrimarySimAutoDataSwitch)
+            var nonDds = targetNonDds
+            Log.d(
+                TAG,
+                "setAutomaticData: targetNonDds: $nonDds," +
+                    " targetPrimarySimAutoDataSwitch: $targetPrimarySimAutoDataSwitch"
+            )
+            if (nonDds != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                val telephonyManagerForNonDds: TelephonyManager? =
+                    context.getSystemService(TelephonyManager::class.java)
+                        ?.createForSubscriptionId(nonDds)
+                setAutomaticData(telephonyManagerForNonDds, targetPrimarySimAutoDataSwitch)
+            }
 
             // no next action, send finish
             callback(SimOnboardingActivity.CALLBACK_FINISH)
diff --git a/src/com/android/settings/network/apn/ApnEditPageProvider.kt b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
index cea2b44..eda9d7a 100644
--- a/src/com/android/settings/network/apn/ApnEditPageProvider.kt
+++ b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
@@ -38,17 +38,10 @@
 import androidx.navigation.NavType
 import androidx.navigation.navArgument
 import com.android.settings.R
-import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeDisplayNames
-import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeSelectedOptionsState
-import com.android.settings.network.apn.ApnTypes.APN_TYPES_OPTIONS
-import com.android.settings.network.apn.ApnTypes.APN_TYPE_MMS
-import com.android.settings.network.apn.ApnTypes.getApnTypeSelectedOptionsState
-import com.android.settings.network.apn.ApnTypes.updateApnType
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.compose.LocalNavController
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuBox
-import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuCheckBox
 import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField
 import com.android.settingslib.spa.widget.editor.SettingsTextFieldPassword
 import com.android.settingslib.spa.widget.preference.SwitchPreference
@@ -79,7 +72,7 @@
         val uriString = arguments!!.getString(URI)
         val uriInit = Uri.parse(String(Base64.getDecoder().decode(uriString)))
         val subId = arguments.getInt(SUB_ID)
-        val apnDataInit = getApnDataInit(arguments, LocalContext.current, uriInit, subId)
+        val apnDataInit = getApnDataInit(arguments, LocalContext.current, uriInit, subId) ?: return
         val apnDataCur = remember {
             mutableStateOf(apnDataInit)
         }
@@ -101,12 +94,7 @@
     val context = LocalContext.current
     val authTypeOptions = stringArrayResource(R.array.apn_auth_entries).toList()
     val apnProtocolOptions = stringArrayResource(R.array.apn_protocol_entries).toList()
-    val networkTypeSelectedOptionsState = remember {
-        getNetworkTypeSelectedOptionsState(apnData.networkType)
-    }
-    var apnTypeSelectedOptionsState = remember {
-        getApnTypeSelectedOptionsState(apnData.apnType)
-    }
+    var apnTypeMmsSelected by remember { mutableStateOf(false) }
     val navController = LocalNavController.current
     var valid: String?
     RegularScaffold(
@@ -114,11 +102,6 @@
         actions = {
             if (!apnData.customizedConfig.readOnlyApn) {
                 Button(onClick = {
-                    apnData = apnData.copy(
-                        networkType = ApnNetworkTypes.getNetworkType(
-                            networkTypeSelectedOptionsState
-                        )
-                    )
                     valid = validateAndSaveApnData(
                         apnDataInit,
                         apnData,
@@ -193,27 +176,12 @@
                 label = stringResource(R.string.apn_server),
                 enabled = apnData.serverEnabled
             ) { apnData = apnData.copy(server = it) }
-            SettingsExposedDropdownMenuCheckBox(
-                label = stringResource(R.string.apn_type),
-                options = APN_TYPES_OPTIONS,
-                selectedOptionsState = apnTypeSelectedOptionsState,
-                enabled = apnData.apnTypeEnabled,
-                errorMessage = validateAPNType(
-                    apnData.validEnabled, apnData.apnType,
-                    apnData.customizedConfig.readOnlyApnTypes, context
-                )
-            ) {
-                val apnType = updateApnType(
-                    apnTypeSelectedOptionsState,
-                    apnData.customizedConfig.defaultApnTypes,
-                    apnData.customizedConfig.readOnlyApnTypes
-                )
-                apnTypeSelectedOptionsState = getApnTypeSelectedOptionsState(apnType)
-                apnData = apnData.copy(
-                    apnType = apnType
-                )
-            }
-            if (apnTypeSelectedOptionsState.contains(APN_TYPES_OPTIONS.indexOf(APN_TYPE_MMS))) {
+            ApnTypeCheckBox(
+                apnData = apnData,
+                onTypeChanged = { apnData = apnData.copy(apnType = it) },
+                onMmsSelectedChanged = { apnTypeMmsSelected = it },
+            )
+            if (apnTypeMmsSelected) {
                 SettingsOutlinedTextField(
                     value = apnData.mmsc,
                     label = stringResource(R.string.apn_mmsc),
@@ -249,13 +217,7 @@
                 selectedOptionIndex = apnData.apnRoaming,
                 enabled = apnData.apnRoamingEnabled
             ) { apnData = apnData.copy(apnRoaming = it) }
-            SettingsExposedDropdownMenuCheckBox(
-                label = stringResource(R.string.network_type),
-                options = getNetworkTypeDisplayNames(),
-                selectedOptionsState = networkTypeSelectedOptionsState,
-                emptyVal = stringResource(R.string.network_type_unspecified),
-                enabled = apnData.networkTypeEnabled
-            ) {}
+            ApnNetworkTypeCheckBox(apnData) { apnData = apnData.copy(networkType = it) }
             SwitchPreference(
                 object : SwitchPreferenceModel {
                     override val title = context.resources.getString(R.string.carrier_enabled)
diff --git a/src/com/android/settings/network/apn/ApnNetworkTypeCheckBox.kt b/src/com/android/settings/network/apn/ApnNetworkTypeCheckBox.kt
new file mode 100644
index 0000000..bc85f55
--- /dev/null
+++ b/src/com/android/settings/network/apn/ApnNetworkTypeCheckBox.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 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.apn
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settingslib.spa.widget.editor.SettingsDropdownCheckBox
+
+@Composable
+fun ApnNetworkTypeCheckBox(apnData: ApnData, onNetworkTypeChanged: (Long) -> Unit) {
+    val options = remember { ApnNetworkTypes.getNetworkTypeOptions() }
+    val selectedStateMap = remember {
+        ApnNetworkTypes.networkTypeToSelectedStateMap(options, apnData.networkType)
+    }
+    SettingsDropdownCheckBox(
+        label = stringResource(R.string.network_type),
+        options = options,
+        emptyText = stringResource(R.string.network_type_unspecified),
+        enabled = apnData.networkTypeEnabled,
+    ) {
+        onNetworkTypeChanged(
+            ApnNetworkTypes.selectedStateMapToNetworkType(options, selectedStateMap)
+        )
+    }
+}
diff --git a/src/com/android/settings/network/apn/ApnNetworkTypes.kt b/src/com/android/settings/network/apn/ApnNetworkTypes.kt
index 0ccd33a..e7a93b3 100644
--- a/src/com/android/settings/network/apn/ApnNetworkTypes.kt
+++ b/src/com/android/settings/network/apn/ApnNetworkTypes.kt
@@ -17,8 +17,9 @@
 package com.android.settings.network.apn
 
 import android.telephony.TelephonyManager
-import androidx.compose.runtime.mutableStateListOf
-import androidx.compose.runtime.snapshots.SnapshotStateList
+import androidx.compose.runtime.mutableStateMapOf
+import androidx.compose.runtime.snapshots.SnapshotStateMap
+import com.android.settingslib.spa.widget.editor.SettingsDropdownCheckOption
 
 object ApnNetworkTypes {
     private val Types = listOf(
@@ -39,32 +40,40 @@
         TelephonyManager.NETWORK_TYPE_NR,
     )
 
-    fun getNetworkTypeDisplayNames(): List<String> =
-        Types.map { TelephonyManager.getNetworkTypeName(it) }
+    fun getNetworkTypeOptions(): List<SettingsDropdownCheckOption> =
+        Types.map { SettingsDropdownCheckOption(TelephonyManager.getNetworkTypeName(it)) }
 
     /**
      * Gets the selected Network type Selected Options according to network type.
      * @param networkType Initialized network type bitmask, often multiple network type options may
      *                    be included.
      */
-    fun getNetworkTypeSelectedOptionsState(networkType: Long): SnapshotStateList<Int> {
-        val networkTypeSelectedOptionsState = mutableStateListOf<Int>()
+    fun networkTypeToSelectedStateMap(
+        options: List<SettingsDropdownCheckOption>,
+        networkType: Long,
+    ): SnapshotStateMap<SettingsDropdownCheckOption, Boolean> {
+        val stateMap = mutableStateMapOf<SettingsDropdownCheckOption, Boolean>()
         Types.forEachIndexed { index, type ->
             if (networkType and TelephonyManager.getBitMaskForNetworkType(type) != 0L) {
-                networkTypeSelectedOptionsState.add(index)
+                stateMap[options[index]] = true
             }
         }
-        return networkTypeSelectedOptionsState
+        return stateMap
     }
 
     /**
      * Gets the network type according to the selected Network type Selected Options.
-     * @param networkTypeSelectedOptionsState the selected Network type Selected Options.
+     * @param stateMap the selected Network type Selected Options.
      */
-    fun getNetworkType(networkTypeSelectedOptionsState: SnapshotStateList<Int>): Long {
+    fun selectedStateMapToNetworkType(
+        options: List<SettingsDropdownCheckOption>,
+        stateMap: SnapshotStateMap<SettingsDropdownCheckOption, Boolean>,
+    ): Long {
         var networkType = 0L
-        networkTypeSelectedOptionsState.forEach { option ->
-            networkType = networkType or TelephonyManager.getBitMaskForNetworkType(Types[option])
+        options.forEachIndexed { index, option ->
+            if (stateMap[option] == true) {
+                networkType = networkType or TelephonyManager.getBitMaskForNetworkType(Types[index])
+            }
         }
         return networkType
     }
diff --git a/src/com/android/settings/network/apn/ApnRepository.kt b/src/com/android/settings/network/apn/ApnRepository.kt
index 2266983..2d41976 100644
--- a/src/com/android/settings/network/apn/ApnRepository.kt
+++ b/src/com/android/settings/network/apn/ApnRepository.kt
@@ -18,6 +18,7 @@
 
 import android.content.ContentValues
 import android.content.Context
+import android.database.Cursor
 import android.net.Uri
 import android.provider.Telephony
 import android.telephony.SubscriptionManager
@@ -27,26 +28,7 @@
 import com.android.settingslib.utils.ThreadUtils
 import java.util.Locale
 
-const val NAME_INDEX = 1
-const val APN_INDEX = 2
-const val PROXY_INDEX = 3
-const val PORT_INDEX = 4
-const val USER_INDEX = 5
-const val SERVER_INDEX = 6
-const val PASSWORD_INDEX = 7
-const val MMSC_INDEX = 8
-const val MMSPROXY_INDEX = 9
-const val MMSPORT_INDEX = 10
-const val AUTH_TYPE_INDEX = 11
-const val TYPE_INDEX = 12
-const val PROTOCOL_INDEX = 13
-const val CARRIER_ENABLED_INDEX = 14
-const val NETWORK_TYPE_INDEX = 15
-const val ROAMING_PROTOCOL_INDEX = 16
-const val EDITED_INDEX = 17
-const val USER_EDITABLE_INDEX = 18
-
-val sProjection = arrayOf(
+val Projection = arrayOf(
     Telephony.Carriers._ID,  // 0
     Telephony.Carriers.NAME,  // 1
     Telephony.Carriers.APN,  // 2
@@ -68,7 +50,7 @@
     Telephony.Carriers.USER_EDITABLE,  // 18
 )
 
-const val TAG = "ApnRepository"
+private const val TAG = "ApnRepository"
 
 /**
  * Query apn related information based on uri.
@@ -79,56 +61,39 @@
 fun getApnDataFromUri(uri: Uri, context: Context): ApnData {
     var apnData = ApnData()
     val contentResolver = context.contentResolver
-    val apnProtocolOptions = context.resources.getStringArray(R.array.apn_protocol_entries).toList()
 
     contentResolver.query(
         uri,
-        sProjection,
+        Projection,
         null /* selection */,
         null /* selectionArgs */,
         null /* sortOrder */
     ).use { cursor ->
         if (cursor != null && cursor.moveToFirst()) {
-            val name = cursor.getString(NAME_INDEX)
-            val apn = cursor.getString(APN_INDEX)
-            val proxy = cursor.getString(PROXY_INDEX)
-            val port = cursor.getString(PORT_INDEX)
-            val userName = cursor.getString(USER_INDEX)
-            val server = cursor.getString(SERVER_INDEX)
-            val passWord = cursor.getString(PASSWORD_INDEX)
-            val mmsc = cursor.getString(MMSC_INDEX)
-            val mmsProxy = cursor.getString(MMSPROXY_INDEX)
-            val mmsPort = cursor.getString(MMSPORT_INDEX)
-            val authType = cursor.getInt(AUTH_TYPE_INDEX)
-            val apnType = cursor.getString(TYPE_INDEX)
-            val apnProtocol = convertProtocol2Options(cursor.getString(PROTOCOL_INDEX), context)
-            val apnRoaming =
-                convertProtocol2Options(cursor.getString(ROAMING_PROTOCOL_INDEX), context)
-            val apnEnable = cursor.getInt(CARRIER_ENABLED_INDEX) == 1
-            val networkType = cursor.getLong(NETWORK_TYPE_INDEX)
-
-            val edited = cursor.getInt(EDITED_INDEX)
-            val userEditable = cursor.getInt(USER_EDITABLE_INDEX)
-
-            apnData = apnData.copy(
-                name = name,
-                apn = apn,
-                proxy = proxy,
-                port = port,
-                userName = userName,
-                passWord = passWord,
-                server = server,
-                mmsc = mmsc,
-                mmsProxy = mmsProxy,
-                mmsPort = mmsPort,
-                authType = authType,
-                apnType = apnType,
-                apnProtocol = apnProtocolOptions.indexOf(apnProtocol),
-                apnRoaming = apnProtocolOptions.indexOf(apnRoaming),
-                apnEnable = apnEnable,
-                networkType = networkType,
-                edited = edited,
-                userEditable = userEditable,
+            apnData = ApnData(
+                id = cursor.getInt(Telephony.Carriers._ID),
+                name = cursor.getString(Telephony.Carriers.NAME),
+                apn = cursor.getString(Telephony.Carriers.APN),
+                proxy = cursor.getString(Telephony.Carriers.PROXY),
+                port = cursor.getString(Telephony.Carriers.PORT),
+                userName = cursor.getString(Telephony.Carriers.USER),
+                passWord = cursor.getString(Telephony.Carriers.PASSWORD),
+                server = cursor.getString(Telephony.Carriers.SERVER),
+                mmsc = cursor.getString(Telephony.Carriers.MMSC),
+                mmsProxy = cursor.getString(Telephony.Carriers.MMSPROXY),
+                mmsPort = cursor.getString(Telephony.Carriers.MMSPORT),
+                authType = cursor.getInt(Telephony.Carriers.AUTH_TYPE),
+                apnType = cursor.getString(Telephony.Carriers.TYPE),
+                apnProtocol = context.convertProtocol2Options(
+                    cursor.getString(Telephony.Carriers.PROTOCOL)
+                ),
+                apnRoaming = context.convertProtocol2Options(
+                    cursor.getString(Telephony.Carriers.ROAMING_PROTOCOL)
+                ),
+                apnEnable = cursor.getInt(Telephony.Carriers.CARRIER_ENABLED) == 1,
+                networkType = cursor.getLong(Telephony.Carriers.NETWORK_TYPE_BITMASK),
+                edited = cursor.getInt(Telephony.Carriers.EDITED_STATUS),
+                userEditable = cursor.getInt(Telephony.Carriers.USER_EDITABLE),
             )
         }
     }
@@ -138,42 +103,23 @@
     return apnData
 }
 
+private fun Cursor.getString(columnName: String) = getString(getColumnIndexOrThrow(columnName))
+private fun Cursor.getInt(columnName: String) = getInt(getColumnIndexOrThrow(columnName))
+private fun Cursor.getLong(columnName: String) = getLong(getColumnIndexOrThrow(columnName))
+
 /**
- * Returns The UI choice (e.g., "IPv4/IPv6") corresponding to the given
- * raw value of the protocol preference (e.g., "IPV4V6"). If unknown,
- * return null.
- *
- * @return UI choice
+ * Returns The UI choice index corresponding to the given raw value of the protocol preference
+ * (e.g., "IPV4V6").
+ * If unknown, return -1.
  */
-private fun convertProtocol2Options(raw: String, context: Context): String {
-    val apnProtocolOptions = context.resources.getStringArray(R.array.apn_protocol_entries).toList()
-    val apnProtocolValues = context.resources.getStringArray(R.array.apn_protocol_values).toList()
-    var uRaw = raw.uppercase(Locale.getDefault())
-    uRaw = if (uRaw == "IPV4") "IP" else uRaw
-    val protocolIndex = apnProtocolValues.indexOf(uRaw)
-    return if (protocolIndex == -1) {
-        ""
-    } else {
-        try {
-            apnProtocolOptions[protocolIndex]
-        } catch (e: ArrayIndexOutOfBoundsException) {
-            ""
-        }
-    }
+private fun Context.convertProtocol2Options(protocol: String): Int {
+    var normalizedProtocol = protocol.uppercase(Locale.getDefault())
+    if (normalizedProtocol == "IPV4") normalizedProtocol = "IP"
+    return resources.getStringArray(R.array.apn_protocol_values).indexOf(normalizedProtocol)
 }
 
-fun convertOptions2Protocol(protocolIndex: Int, context: Context): String {
-    val apnProtocolValues = context.resources.getStringArray(R.array.apn_protocol_values).toList()
-    return if (protocolIndex == -1) {
-        ""
-    } else {
-        try {
-            apnProtocolValues[protocolIndex]
-        } catch (e: ArrayIndexOutOfBoundsException) {
-            ""
-        }
-    }
-}
+fun Context.convertOptions2Protocol(protocolIndex: Int): String =
+    resources.getStringArray(R.array.apn_protocol_values).getOrElse(protocolIndex) { "" }
 
 fun updateApnDataToDatabase(
     newApn: Boolean,
@@ -183,13 +129,13 @@
 ) {
     ThreadUtils.postOnBackgroundThread {
         if (newApn) {
-            // Add a new apn to the database
+            Log.d(TAG, "Adding an new APN to the database $uriInit $values")
             val newUri = context.contentResolver.insert(uriInit, values)
             if (newUri == null) {
                 Log.e(TAG, "Can't add a new apn to database $uriInit")
             }
         } else {
-            // Update the existing apn
+            Log.d(TAG, "Updating an existing APN to the database $uriInit $values")
             context.contentResolver.update(
                 uriInit, values, null /* where */, null /* selection Args */
             )
@@ -210,9 +156,12 @@
 )
 
 fun isItemExist(apnData: ApnData, context: Context): String? {
-    val contentValueMap = apnData.getContentValueMap(context).filterKeys { it in NonDuplicatedKeys }
-    val list = contentValueMap.entries.toList()
-    val selection = list.joinToString(" AND ") { "${it.key} = ?" }
+    val selectionMap = apnData.getContentValueMap(context).filterKeys { it in NonDuplicatedKeys }
+        .mapKeys { "${it.key} = ?" }
+        .toMutableMap()
+    if (apnData.id != -1) selectionMap += "${Telephony.Carriers._ID} != ?" to apnData.id
+    val list = selectionMap.entries.toList()
+    val selection = list.joinToString(" AND ") { it.key }
     val selectionArgs: Array<String> = list.map { it.value.toString() }.toTypedArray()
     context.contentResolver.query(
         Uri.withAppendedPath(Telephony.Carriers.SIM_APN_URI, apnData.subId.toString()),
diff --git a/src/com/android/settings/network/apn/ApnStatus.kt b/src/com/android/settings/network/apn/ApnStatus.kt
index 02e2814..ab16f1c 100644
--- a/src/com/android/settings/network/apn/ApnStatus.kt
+++ b/src/com/android/settings/network/apn/ApnStatus.kt
@@ -22,19 +22,14 @@
 import android.os.Bundle
 import android.provider.Telephony
 import android.telephony.CarrierConfigManager
-import android.text.TextUtils
 import android.util.Log
-import com.android.internal.util.ArrayUtils
 import com.android.settings.R
-import com.android.settings.network.apn.ApnTypes.APN_TYPES
-import com.android.settings.network.apn.ApnTypes.APN_TYPE_ALL
-import com.android.settings.network.apn.ApnTypes.APN_TYPE_EMERGENCY
-import com.android.settings.network.apn.ApnTypes.APN_TYPE_IA
-import com.android.settings.network.apn.ApnTypes.APN_TYPE_IMS
-import com.android.settings.network.apn.ApnTypes.APN_TYPE_MCX
-import java.util.Locale
+import com.android.settings.network.apn.ApnTypes.getPreSelectedApnType
+
+private const val TAG = "ApnStatus"
 
 data class ApnData(
+    val id: Int = -1,
     val name: String = "",
     val apn: String = "",
     val proxy: String = "",
@@ -86,8 +81,8 @@
         Telephony.Carriers.MMSPROXY to mmsProxy,
         Telephony.Carriers.MMSPORT to mmsPort,
         Telephony.Carriers.AUTH_TYPE to authType,
-        Telephony.Carriers.PROTOCOL to convertOptions2Protocol(apnProtocol, context),
-        Telephony.Carriers.ROAMING_PROTOCOL to convertOptions2Protocol(apnRoaming, context),
+        Telephony.Carriers.PROTOCOL to context.convertOptions2Protocol(apnProtocol),
+        Telephony.Carriers.ROAMING_PROTOCOL to context.convertOptions2Protocol(apnRoaming),
         Telephony.Carriers.TYPE to apnType,
         Telephony.Carriers.NETWORK_TYPE_BITMASK to networkType,
         Telephony.Carriers.CARRIER_ENABLED to apnEnable,
@@ -105,7 +100,7 @@
     val isAddApnAllowed: Boolean = true,
     val readOnlyApnTypes: List<String> = emptyList(),
     val readOnlyApnFields: List<String> = emptyList(),
-    val defaultApnTypes: List<String> = emptyList(),
+    val defaultApnTypes: List<String>? = null,
     val defaultApnProtocol: String = "",
     val defaultApnRoamingProtocol: String = "",
 )
@@ -118,19 +113,18 @@
  *
  * @return Initialized CustomizedConfig information.
  */
-fun getApnDataInit(arguments: Bundle, context: Context, uriInit: Uri, subId: Int): ApnData {
-
-    val uriType = arguments.getString(URI_TYPE)!!
+fun getApnDataInit(arguments: Bundle, context: Context, uriInit: Uri, subId: Int): ApnData? {
+    val uriType = arguments.getString(URI_TYPE) ?: return null
 
     if (!uriInit.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) {
         Log.e(TAG, "Insert request not for carrier table. Uri: $uriInit")
-        return ApnData() //TODO: finish
+        return null
     }
 
     var apnDataInit = when (uriType) {
         EDIT_URL -> getApnDataFromUri(uriInit, context)
         INSERT_URL -> ApnData()
-        else -> ApnData() //TODO: finish
+        else -> return null
     }
 
     if (uriType == INSERT_URL) {
@@ -143,13 +137,18 @@
     apnDataInit =
         apnDataInit.copy(customizedConfig = getCarrierCustomizedConfig(apnDataInit, configManager))
 
+    if (apnDataInit.newApn) {
+        apnDataInit = apnDataInit.copy(
+            apnType = getPreSelectedApnType(apnDataInit.customizedConfig)
+        )
+    }
+
     apnDataInit = apnDataInit.copy(
         apnEnableEnabled =
         context.resources.getBoolean(R.bool.config_allow_edit_carrier_enabled)
     )
     // TODO: mIsCarrierIdApn
-    disableInit(apnDataInit)
-    return apnDataInit
+    return disableInit(apnDataInit)
 }
 
 /**
@@ -199,53 +198,7 @@
     if (errorMsg == null) {
         errorMsg = isItemExist(apnData, context)
     }
-    if (errorMsg == null) {
-        errorMsg = validateAPNType(
-            true,
-            apnData.apnType,
-            apnData.customizedConfig.readOnlyApnTypes,
-            context
-        )
-    }
-    return errorMsg
-}
-
-private fun getUserEnteredApnType(apnType: String, readOnlyApnTypes: List<String>): String {
-    // if user has not specified a type, map it to "ALL APN TYPES THAT ARE NOT READ-ONLY"
-    // but if user enter empty type, map it just for default
-    var userEnteredApnType = apnType
-    if (userEnteredApnType != "") userEnteredApnType =
-        userEnteredApnType.trim { it <= ' ' }
-    if (TextUtils.isEmpty(userEnteredApnType) || APN_TYPE_ALL == userEnteredApnType) {
-        userEnteredApnType = getEditableApnType(readOnlyApnTypes)
-    }
-    Log.d(
-        TAG, "getUserEnteredApnType: changed apn type to editable apn types: "
-            + userEnteredApnType
-    )
-    return userEnteredApnType
-}
-
-private fun getEditableApnType(readOnlyApnTypes: List<String>): String {
-    val editableApnTypes = StringBuilder()
-    var first = true
-    for (apnType in APN_TYPES) {
-        // add APN type if it is not read-only and is not wild-cardable
-        if (!readOnlyApnTypes.contains(apnType)
-            && apnType != APN_TYPE_IA
-            && apnType != APN_TYPE_EMERGENCY
-            && apnType != APN_TYPE_MCX
-            && apnType != APN_TYPE_IMS
-        ) {
-            if (first) {
-                first = false
-            } else {
-                editableApnTypes.append(",")
-            }
-            editableApnTypes.append(apnType)
-        }
-    }
-    return editableApnTypes.toString()
+    return errorMsg?.apply { Log.d(TAG, "APN data not valid, reason: $this") }
 }
 
 /**
@@ -258,6 +211,10 @@
     apnInit: ApnData,
     configManager: CarrierConfigManager
 ): CustomizedConfig {
+    fun log(message: String) {
+        Log.d(TAG, "getCarrierCustomizedConfig: $message")
+    }
+
     val b = configManager.getConfigForSubId(
         apnInit.subId,
         CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY,
@@ -270,72 +227,61 @@
     val customizedConfig = CustomizedConfig(
         readOnlyApnTypes = b.getStringArray(
             CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY
-        )?.toList() ?: emptyList(), readOnlyApnFields = b.getStringArray(
+        )?.toList() ?: emptyList(),
+        readOnlyApnFields = b.getStringArray(
             CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY
-        )?.toList() ?: emptyList(), defaultApnTypes = b.getStringArray(
+        )?.toList() ?: emptyList(),
+        defaultApnTypes = b.getStringArray(
             CarrierConfigManager.KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY
-        )?.toList() ?: emptyList(), defaultApnProtocol = b.getString(
+        )?.toList(),
+        defaultApnProtocol = b.getString(
             CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_PROTOCOL_STRING
-        ) ?: "", defaultApnRoamingProtocol = b.getString(
+        ) ?: "",
+        defaultApnRoamingProtocol = b.getString(
             CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_ROAMING_PROTOCOL_STRING
-        ) ?: "", isAddApnAllowed = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL)
+        ) ?: "",
+        isAddApnAllowed = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL),
     )
-    if (!ArrayUtils.isEmpty(customizedConfig.readOnlyApnTypes)) {
-        Log.d(
-            TAG,
-            "getCarrierCustomizedConfig: read only APN type: " + customizedConfig.readOnlyApnTypes.joinToString(
-                ", "
-            )
-        )
+    if (customizedConfig.readOnlyApnTypes.isNotEmpty()) {
+        log("read only APN type: " + customizedConfig.readOnlyApnTypes)
     }
-    if (!ArrayUtils.isEmpty(customizedConfig.defaultApnTypes)) {
-        Log.d(
-            TAG,
-            "getCarrierCustomizedConfig: default apn types: " + customizedConfig.defaultApnTypes.joinToString(
-                ", "
-            )
-        )
+    customizedConfig.defaultApnTypes?.takeIf { it.isNotEmpty() }?.let {
+        log("default apn types: $it")
     }
-    if (!TextUtils.isEmpty(customizedConfig.defaultApnProtocol)) {
-        Log.d(
-            TAG,
-            "getCarrierCustomizedConfig: default apn protocol: ${customizedConfig.defaultApnProtocol}"
-        )
+    if (customizedConfig.defaultApnProtocol.isNotEmpty()) {
+        log("default apn protocol: ${customizedConfig.defaultApnProtocol}")
     }
-    if (!TextUtils.isEmpty(customizedConfig.defaultApnRoamingProtocol)) {
-        Log.d(
-            TAG,
-            "getCarrierCustomizedConfig: default apn roaming protocol: ${customizedConfig.defaultApnRoamingProtocol}"
-        )
+    if (customizedConfig.defaultApnRoamingProtocol.isNotEmpty()) {
+        log("default apn roaming protocol: ${customizedConfig.defaultApnRoamingProtocol}")
     }
     if (!customizedConfig.isAddApnAllowed) {
-        Log.d(TAG, "getCarrierCustomizedConfig: not allow to add new APN")
+        log("not allow to add new APN")
     }
     return customizedConfig
 }
 
-fun disableInit(apnDataInit: ApnData): ApnData {
-    var apnData = apnDataInit
-    val isUserEdited = apnDataInit.edited == Telephony.Carriers.USER_EDITED
-    Log.d(TAG, "disableInit: EDITED $isUserEdited")
+private fun ApnData.isReadOnly(): Boolean {
+    Log.d(TAG, "isReadOnly: edited $edited")
+    if (edited == Telephony.Carriers.USER_EDITED) return false
     // if it's not a USER_EDITED apn, check if it's read-only
-    if (!isUserEdited && (apnDataInit.userEditable == 0
-            || apnTypesMatch(apnDataInit.customizedConfig.readOnlyApnTypes, apnDataInit.apnType))
-    ) {
+    return userEditable == 0 ||
+        ApnTypes.isApnTypeReadOnly(apnType, customizedConfig.readOnlyApnTypes)
+}
+
+fun disableInit(apnDataInit: ApnData): ApnData {
+    if (apnDataInit.isReadOnly()) {
         Log.d(TAG, "disableInit: read-only APN")
-        apnData =
-            apnDataInit.copy(customizedConfig = apnDataInit.customizedConfig.copy(readOnlyApn = true))
-        apnData = disableAllFields(apnData)
-    } else if (!ArrayUtils.isEmpty(apnData.customizedConfig.readOnlyApnFields)) {
-        Log.d(
-            TAG,
-            "disableInit: mReadOnlyApnFields ${
-                apnData.customizedConfig.readOnlyApnFields.joinToString(", ")
-            })"
+        val apnData = apnDataInit.copy(
+            customizedConfig = apnDataInit.customizedConfig.copy(readOnlyApn = true)
         )
-        apnData = disableFields(apnData.customizedConfig.readOnlyApnFields, apnData)
+        return disableAllFields(apnData)
     }
-    return apnData
+    val readOnlyApnFields = apnDataInit.customizedConfig.readOnlyApnFields
+    if (readOnlyApnFields.isNotEmpty()) {
+        Log.d(TAG, "disableInit: readOnlyApnFields $readOnlyApnFields)")
+        return disableFields(readOnlyApnFields, apnDataInit)
+    }
+    return apnDataInit
 }
 
 /**
@@ -402,23 +348,6 @@
     return apnData
 }
 
-private fun apnTypesMatch(apnTypeList: List<String>, apnType: String): Boolean {
-    val normalizeApnTypeList = apnTypeList.map(::normalizeApnType)
-    return hasAllApns(normalizeApnTypeList) ||
-        apnType.split(",").map(::normalizeApnType).all { it in normalizeApnTypeList }
-}
-
-fun hasAllApns(apnTypes: List<String>): Boolean {
-    if (APN_TYPE_ALL in apnTypes) {
-        Log.d(TAG, "hasAllApns: true because apnTypes.contains(APN_TYPE_ALL)")
-        return true
-    }
-    return APN_TYPES.all { it in apnTypes }
-}
-
-private fun normalizeApnType(apnType: String): String =
-    apnType.trim().lowercase(Locale.getDefault())
-
 fun deleteApn(uri: Uri, context: Context) {
     val contentResolver = context.contentResolver
     contentResolver.delete(uri, null, null)
@@ -439,24 +368,3 @@
     return if (validEnabled && (apn == "")) context.resources.getString(R.string.error_apn_empty)
     else null
 }
-
-fun validateAPNType(
-    validEnabled: Boolean,
-    apnType: String,
-    readOnlyApnTypes: List<String>,
-    context: Context
-): String? {
-    // if carrier does not allow editing certain apn types, make sure type does not include those
-    if (validEnabled && !ArrayUtils.isEmpty(readOnlyApnTypes)
-        && apnTypesMatch(
-            readOnlyApnTypes,
-            getUserEnteredApnType(apnType, readOnlyApnTypes)
-        )
-    ) {
-        return String.format(
-            context.resources.getString(R.string.error_adding_apn_type),
-            readOnlyApnTypes.joinToString(", ")
-        )
-    }
-    return null
-}
\ No newline at end of file
diff --git a/src/com/android/settings/network/apn/ApnTypeCheckBox.kt b/src/com/android/settings/network/apn/ApnTypeCheckBox.kt
new file mode 100644
index 0000000..4d0659c
--- /dev/null
+++ b/src/com/android/settings/network/apn/ApnTypeCheckBox.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 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.apn
+
+import android.telephony.data.ApnSetting
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settings.network.apn.ApnTypes.toApnType
+import com.android.settingslib.spa.widget.editor.SettingsDropdownCheckBox
+
+@Composable
+fun ApnTypeCheckBox(
+    apnData: ApnData,
+    onTypeChanged: (String) -> Unit,
+    onMmsSelectedChanged: (Boolean) -> Unit,
+) {
+    val context = LocalContext.current
+    val apnTypeOptions = remember {
+        ApnTypes.getOptions(context, apnData.apnType, apnData.customizedConfig.readOnlyApnTypes)
+    }
+
+    fun updateMmsSelected() {
+        val apnTypeOptionMms = apnTypeOptions.single { it.text == ApnSetting.TYPE_MMS_STRING }
+        onMmsSelectedChanged(apnTypeOptionMms.selected.value)
+    }
+    LaunchedEffect(Unit) { updateMmsSelected() }
+    SettingsDropdownCheckBox(
+        label = stringResource(R.string.apn_type),
+        options = apnTypeOptions,
+        enabled = apnData.apnTypeEnabled,
+    ) {
+        onTypeChanged(apnTypeOptions.toApnType())
+        updateMmsSelected()
+    }
+}
diff --git a/src/com/android/settings/network/apn/ApnTypes.kt b/src/com/android/settings/network/apn/ApnTypes.kt
index d3dbe38..2c8fa2a 100644
--- a/src/com/android/settings/network/apn/ApnTypes.kt
+++ b/src/com/android/settings/network/apn/ApnTypes.kt
@@ -16,128 +16,112 @@
 
 package com.android.settings.network.apn
 
-import androidx.compose.runtime.mutableStateListOf
-import androidx.compose.runtime.snapshots.SnapshotStateList
+import android.content.Context
+import android.telephony.data.ApnSetting
+import android.util.Log
+import android.widget.Toast
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.text.intl.Locale
+import androidx.compose.ui.text.toLowerCase
+import com.android.settings.R
+import com.android.settingslib.spa.widget.editor.SettingsDropdownCheckOption
 
 object ApnTypes {
-    /**
-     * APN types for data connections.  These are usage categories for an APN
-     * entry.  One APN entry may support multiple APN types, eg, a single APN
-     * may service regular internet traffic ("default") as well as MMS-specific
-     * connections.<br></br>
-     * APN_TYPE_ALL is a special type to indicate that this APN entry can
-     * service all data connections.
-     */
-    const val APN_TYPE_ALL = "*"
+    private const val TAG = "ApnTypes"
 
-    /** APN type for default data traffic  */
-    const val APN_TYPE_DEFAULT = "default"
-
-    /** APN type for MMS traffic  */
-    const val APN_TYPE_MMS = "mms"
-
-    /** APN type for SUPL assisted GPS  */
-    const val APN_TYPE_SUPL = "supl"
-
-    /** APN type for DUN traffic  */
-    const val APN_TYPE_DUN = "dun"
-
-    /** APN type for HiPri traffic  */
-    const val APN_TYPE_HIPRI = "hipri"
-
-    /** APN type for FOTA  */
-    const val APN_TYPE_FOTA = "fota"
-
-    /** APN type for IMS  */
-    const val APN_TYPE_IMS = "ims"
-
-    /** APN type for CBS  */
-    const val APN_TYPE_CBS = "cbs"
-
-    /** APN type for IA Initial Attach APN  */
-    const val APN_TYPE_IA = "ia"
-
-    /** APN type for Emergency PDN. This is not an IA apn, but is used
-     * for access to carrier services in an emergency call situation.  */
-    const val APN_TYPE_EMERGENCY = "emergency"
-
-    /** APN type for Mission Critical Services  */
-    const val APN_TYPE_MCX = "mcx"
-
-    /** APN type for XCAP  */
-    const val APN_TYPE_XCAP = "xcap"
-
-    /** APN type for VSIM  */
-    const val APN_TYPE_VSIM = "vsim"
-
-    /** APN type for BIP  */
-    const val APN_TYPE_BIP = "bip"
-
-    /** APN type for ENTERPRISE  */
-    const val APN_TYPE_ENTERPRISE = "enterprise"
-
-    val APN_TYPES = arrayOf(
-        APN_TYPE_DEFAULT,
-        APN_TYPE_MMS,
-        APN_TYPE_SUPL,
-        APN_TYPE_DUN,
-        APN_TYPE_HIPRI,
-        APN_TYPE_FOTA,
-        APN_TYPE_IMS,
-        APN_TYPE_CBS,
-        APN_TYPE_IA,
-        APN_TYPE_EMERGENCY,
-        APN_TYPE_MCX,
-        APN_TYPE_XCAP,
-        APN_TYPE_VSIM,
-        APN_TYPE_BIP,
-        APN_TYPE_ENTERPRISE
+    private val APN_TYPES = arrayOf(
+        ApnSetting.TYPE_DEFAULT_STRING,
+        ApnSetting.TYPE_MMS_STRING,
+        ApnSetting.TYPE_SUPL_STRING,
+        ApnSetting.TYPE_DUN_STRING,
+        ApnSetting.TYPE_HIPRI_STRING,
+        ApnSetting.TYPE_FOTA_STRING,
+        ApnSetting.TYPE_IMS_STRING,
+        ApnSetting.TYPE_CBS_STRING,
+        ApnSetting.TYPE_IA_STRING,
+        ApnSetting.TYPE_EMERGENCY_STRING,
+        ApnSetting.TYPE_MCX_STRING,
+        ApnSetting.TYPE_XCAP_STRING,
+        ApnSetting.TYPE_VSIM_STRING,
+        ApnSetting.TYPE_BIP_STRING,
+        ApnSetting.TYPE_ENTERPRISE_STRING,
     )
 
-    val APN_TYPES_OPTIONS = listOf(APN_TYPE_ALL) + APN_TYPES
-
-    fun getApnTypeSelectedOptionsState(apnType: String): SnapshotStateList<Int> {
-        val apnTypeSelectedOptionsState = mutableStateListOf<Int>()
-        if (apnType.contains(APN_TYPE_ALL))
-            APN_TYPES_OPTIONS.forEachIndexed { index, _ ->
-                apnTypeSelectedOptionsState.add(index)
-            }
-        else {
-            APN_TYPES_OPTIONS.forEachIndexed { index, type ->
-                if (apnType.contains(type)) {
-                    apnTypeSelectedOptionsState.add(index)
-                }
-            }
-            if (apnTypeSelectedOptionsState.size == APN_TYPES.size)
-                apnTypeSelectedOptionsState.add(APN_TYPES_OPTIONS.indexOf(APN_TYPE_ALL))
+    private fun splitToList(apnType: String): List<String> {
+        val types = apnType.split(',').map { it.trim().toLowerCase(Locale.current) }
+        if (ApnSetting.TYPE_ALL_STRING in types || APN_TYPES.all { it in types }) {
+            return listOf(ApnSetting.TYPE_ALL_STRING)
         }
-        return apnTypeSelectedOptionsState
+        return APN_TYPES.filter { it in types }
     }
 
-    fun updateApnType(
-        apnTypeSelectedOptionsState: SnapshotStateList<Int>,
-        defaultApnTypes: List<String>,
-        readOnlyApnTypes: List<String>
-    ): String {
-        val apnType = apnTypeSelectedOptionsState.joinToString { APN_TYPES_OPTIONS[it] }
-        if (apnType.contains(APN_TYPE_ALL)) return APN_TYPE_ALL
-        return if (apnType == "" && defaultApnTypes.isNotEmpty())
-            getEditableApnType(defaultApnTypes, readOnlyApnTypes)
-        else
-            apnType
+    fun isApnTypeReadOnly(apnType: String, readOnlyTypes: List<String>): Boolean {
+        val apnTypes = splitToList(apnType)
+        return ApnSetting.TYPE_ALL_STRING in readOnlyTypes ||
+            ApnSetting.TYPE_ALL_STRING in apnTypes && readOnlyTypes.isNotEmpty() ||
+            apnTypes.any { it in readOnlyTypes }
     }
 
-    private fun getEditableApnType(
-        defaultApnTypes: List<String>,
-        readOnlyApnTypes: List<String>
-    ): String {
-        return defaultApnTypes.filterNot { apnType ->
-            readOnlyApnTypes.contains(apnType) || apnType in listOf(
-                APN_TYPE_IA,
-                APN_TYPE_EMERGENCY,
-                APN_TYPE_MCX,
-                APN_TYPE_IMS,
+    fun getOptions(context: Context, apnType: String, readOnlyTypes: List<String>) = buildList {
+        val apnTypes = splitToList(apnType)
+        add(
+            context.createSettingsDropdownCheckOption(
+                text = ApnSetting.TYPE_ALL_STRING,
+                isSelectAll = true,
+                changeable = readOnlyTypes.isEmpty(),
+                selected = ApnSetting.TYPE_ALL_STRING in apnTypes,
             )
-        }.joinToString()
+        )
+        for (type in APN_TYPES) {
+            add(
+                context.createSettingsDropdownCheckOption(
+                    text = type,
+                    changeable = ApnSetting.TYPE_ALL_STRING !in readOnlyTypes &&
+                        type !in readOnlyTypes,
+                    selected = ApnSetting.TYPE_ALL_STRING in apnTypes || type in apnTypes,
+                )
+            )
+        }
+    }.also { Log.d(TAG, "APN Type options: $it") }
+
+    private fun Context.createSettingsDropdownCheckOption(
+        text: String,
+        isSelectAll: Boolean = false,
+        changeable: Boolean,
+        selected: Boolean,
+    ) = SettingsDropdownCheckOption(
+        text = text,
+        isSelectAll = isSelectAll,
+        changeable = changeable,
+        selected = mutableStateOf(selected),
+    ) {
+        if (!changeable) {
+            val message = resources.getString(R.string.error_adding_apn_type, text)
+            Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
+        }
     }
-}
\ No newline at end of file
+
+    fun List<SettingsDropdownCheckOption>.toApnType(): String {
+        val (selectAllOptions, regularOptions) = partition { it.isSelectAll }
+        for (selectAllOption in selectAllOptions) {
+            if (selectAllOption.selected.value) return ApnSetting.TYPE_ALL_STRING
+        }
+        return regularOptions.filter { it.selected.value }.joinToString(",") { it.text }
+    }
+
+    private val NotPreSelectedTypes = setOf(
+        ApnSetting.TYPE_IMS_STRING,
+        ApnSetting.TYPE_IA_STRING,
+        ApnSetting.TYPE_EMERGENCY_STRING,
+        ApnSetting.TYPE_MCX_STRING,
+    )
+
+    fun getPreSelectedApnType(customizedConfig: CustomizedConfig): String =
+        (customizedConfig.defaultApnTypes
+            ?: defaultPreSelectedApnTypes(customizedConfig.readOnlyApnTypes))
+            .joinToString(",")
+
+    private fun defaultPreSelectedApnTypes(readOnlyApnTypes: List<String>) =
+        if (ApnSetting.TYPE_ALL_STRING in readOnlyApnTypes) emptyList()
+        else APN_TYPES.filter { it !in readOnlyApnTypes + NotPreSelectedTypes }
+}
diff --git a/src/com/android/settings/notification/zen/ZenAccessSettings.java b/src/com/android/settings/notification/zen/ZenAccessSettings.java
index 418a571..f765d6d 100644
--- a/src/com/android/settings/notification/zen/ZenAccessSettings.java
+++ b/src/com/android/settings/notification/zen/ZenAccessSettings.java
@@ -39,8 +39,8 @@
 import com.android.settings.applications.specialaccess.zenaccess.ZenAccessSettingObserverMixin;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.EmptyTextSettings;
+import com.android.settings.widget.RestrictedAppPreference;
 import com.android.settingslib.search.SearchIndexable;
-import com.android.settingslib.widget.AppPreference;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -122,7 +122,7 @@
         for (ApplicationInfo app : apps) {
             final String pkg = app.packageName;
             final CharSequence label = app.loadLabel(mPkgMan);
-            final AppPreference pref = new AppPreference(getPrefContext());
+            final RestrictedAppPreference pref = new RestrictedAppPreference(getPrefContext());
             pref.setKey(pkg);
             pref.setIcon(app.loadIcon(mPkgMan));
             pref.setTitle(label);
@@ -133,6 +133,8 @@
             } else {
                 // Not auto approved, update summary according to notification backend.
                 pref.setSummary(getPreferenceSummary(pkg));
+                pref.checkEcmRestrictionAndSetDisabled(
+                        android.Manifest.permission.MANAGE_NOTIFICATIONS, app.packageName);
             }
             pref.setOnPreferenceClickListener(preference -> {
                 AppInfoBase.startAppInfoFragment(
diff --git a/src/com/android/settings/overlay/FeatureFactory.kt b/src/com/android/settings/overlay/FeatureFactory.kt
index 37507a8..2c4a295 100644
--- a/src/com/android/settings/overlay/FeatureFactory.kt
+++ b/src/com/android/settings/overlay/FeatureFactory.kt
@@ -24,6 +24,7 @@
 import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider
 import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider
 import com.android.settings.bluetooth.BluetoothFeatureProvider
+import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider
 import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider
 import com.android.settings.connecteddevice.stylus.StylusFeatureProvider
 import com.android.settings.dashboard.DashboardFeatureProvider
@@ -182,6 +183,11 @@
      */
     abstract val displayFeatureProvider: DisplayFeatureProvider
 
+    /**
+     * Gets implementation for audio sharing related feature.
+     */
+    abstract val audioSharingFeatureProvider: AudioSharingFeatureProvider
+
     companion object {
         private var _factory: FeatureFactory? = null
 
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.kt b/src/com/android/settings/overlay/FeatureFactoryImpl.kt
index e0313b7..e1519b3 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.kt
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.kt
@@ -34,6 +34,8 @@
 import com.android.settings.biometrics2.factory.BiometricsRepositoryProviderImpl
 import com.android.settings.bluetooth.BluetoothFeatureProvider
 import com.android.settings.bluetooth.BluetoothFeatureProviderImpl
+import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider
+import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProviderImpl
 import com.android.settings.connecteddevice.dock.DockUpdaterFeatureProviderImpl
 import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider
 import com.android.settings.connecteddevice.fastpair.FastPairFeatureProviderImpl
@@ -192,7 +194,12 @@
     override val privateSpaceLoginFeatureProvider: PrivateSpaceLoginFeatureProvider by lazy {
         PrivateSpaceLoginFeatureProviderImpl()
     }
+
     override val displayFeatureProvider: DisplayFeatureProvider by lazy {
         DisplayFeatureProviderImpl()
     }
+
+    override val audioSharingFeatureProvider: AudioSharingFeatureProvider by lazy {
+        AudioSharingFeatureProviderImpl()
+    }
 }
diff --git a/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivity.java b/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivity.java
index 149c0d6..63b1dc9 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivity.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceAuthenticationActivity.java
@@ -18,6 +18,8 @@
 
 import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
 
+import static com.android.internal.app.SetScreenLockDialogActivity.LAUNCH_REASON_PRIVATE_SPACE_SETTINGS_ACCESS;
+
 import android.app.ActivityOptions;
 import android.app.AlertDialog;
 import android.app.KeyguardManager;
@@ -37,6 +39,7 @@
 import androidx.fragment.app.FragmentActivity;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.SetScreenLockDialogActivity;
 import com.android.settings.R;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settingslib.transition.SettingsTransitionHelper;
@@ -112,23 +115,31 @@
 
     private void promptToSetDeviceLock() {
         Log.d(TAG, "Show prompt to set device lock before using private space feature");
-        new AlertDialog.Builder(this)
-                .setTitle(R.string.no_device_lock_title)
-                .setMessage(R.string.no_device_lock_summary)
-                .setPositiveButton(
-                        R.string.no_device_lock_action_label,
-                        (DialogInterface dialog, int which) -> {
-                            Log.d(TAG, "Start activity to set new device lock");
-                            mSetDeviceLock.launch(new Intent(ACTION_SET_NEW_PASSWORD));
-                        })
-                .setNegativeButton(
-                        R.string.no_device_lock_cancel,
-                        (DialogInterface dialog, int which) -> finish())
-                .setOnCancelListener(
-                        (DialogInterface dialog) -> {
-                            finish();
-                        })
-                .show();
+        if (android.multiuser.Flags.showSetScreenLockDialog()) {
+            Intent setScreenLockPromptIntent =
+                    SetScreenLockDialogActivity
+                            .createBaseIntent(LAUNCH_REASON_PRIVATE_SPACE_SETTINGS_ACCESS);
+            startActivity(setScreenLockPromptIntent);
+            finish();
+        } else {
+            new AlertDialog.Builder(this)
+                    .setTitle(R.string.no_device_lock_title)
+                    .setMessage(R.string.no_device_lock_summary)
+                    .setPositiveButton(
+                            R.string.no_device_lock_action_label,
+                            (DialogInterface dialog, int which) -> {
+                                Log.d(TAG, "Start activity to set new device lock");
+                                mSetDeviceLock.launch(new Intent(ACTION_SET_NEW_PASSWORD));
+                            })
+                    .setNegativeButton(
+                            R.string.no_device_lock_cancel,
+                            (DialogInterface dialog, int which) -> finish())
+                    .setOnCancelListener(
+                            (DialogInterface dialog) -> {
+                                finish();
+                            })
+                    .show();
+        }
     }
 
     private KeyguardManager getKeyguardManager() {
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index 0741ce4..b1d04d4 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -56,7 +56,7 @@
      * @throws IllegalArgumentException when caller is null
      * @throws SecurityException        when caller is not allowed to launch search result page
      */
-    void verifyLaunchSearchResultPageCaller(Context context, @NonNull ComponentName caller)
+    void verifyLaunchSearchResultPageCaller(@NonNull Context context, @NonNull String callerPackage)
             throws SecurityException, IllegalArgumentException;
 
     /**
diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java
index 6f90970..3a62ddf 100644
--- a/src/com/android/settings/search/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java
@@ -17,13 +17,14 @@
 
 package com.android.settings.search;
 
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.provider.Settings;
 import android.text.TextUtils;
 
+import androidx.annotation.NonNull;
+
 import com.android.settingslib.search.SearchIndexableResources;
 import com.android.settingslib.search.SearchIndexableResourcesMobile;
 
@@ -32,21 +33,18 @@
  */
 public class SearchFeatureProviderImpl implements SearchFeatureProvider {
 
-    private static final String TAG = "SearchFeatureProvider";
-
     private SearchIndexableResources mSearchIndexableResources;
 
     @Override
-    public void verifyLaunchSearchResultPageCaller(Context context, ComponentName caller) {
-        if (caller == null) {
+    public void verifyLaunchSearchResultPageCaller(@NonNull Context context,
+            @NonNull String callerPackage) {
+        if (TextUtils.isEmpty(callerPackage)) {
             throw new IllegalArgumentException("ExternalSettingsTrampoline intents "
                     + "must be called with startActivityForResult");
         }
-        final String packageName = caller.getPackageName();
-        final boolean isSettingsPackage = TextUtils.equals(packageName, context.getPackageName())
-                || TextUtils.equals(getSettingsIntelligencePkgName(context), packageName);
-        final boolean isAllowlistedPackage =
-                isSignatureAllowlisted(context, caller.getPackageName());
+        final boolean isSettingsPackage = TextUtils.equals(callerPackage, context.getPackageName())
+                || TextUtils.equals(getSettingsIntelligencePkgName(context), callerPackage);
+        final boolean isAllowlistedPackage = isSignatureAllowlisted(context, callerPackage);
         if (isSettingsPackage || isAllowlistedPackage) {
             return;
         }
diff --git a/src/com/android/settings/search/SearchResultTrampoline.java b/src/com/android/settings/search/SearchResultTrampoline.java
index 5d897af..04d9db5 100644
--- a/src/com/android/settings/search/SearchResultTrampoline.java
+++ b/src/com/android/settings/search/SearchResultTrampoline.java
@@ -21,7 +21,6 @@
 import static com.android.settings.activityembedding.EmbeddedDeepLinkUtils.getTrampolineIntent;
 
 import android.app.Activity;
-import android.content.ComponentName;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -53,11 +52,11 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        final ComponentName callingActivity = getCallingActivity();
+        final String callerPackage = getLaunchedFromPackage();
         // First make sure caller has privilege to launch a search result page.
         FeatureFactory.getFeatureFactory()
                 .getSearchFeatureProvider()
-                .verifyLaunchSearchResultPageCaller(this, callingActivity);
+                .verifyLaunchSearchResultPageCaller(this, callerPackage);
         // Didn't crash, proceed and launch the result as a subsetting.
         Intent intent = getIntent();
         final String highlightMenuKey = intent.getStringExtra(
@@ -106,7 +105,7 @@
         if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this)
                 || ActivityEmbeddingUtils.isAlreadyEmbedded(this)) {
             startActivity(intent);
-        } else if (isSettingsIntelligence(callingActivity)) {
+        } else if (isSettingsIntelligence(callerPackage)) {
             if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SETTINGS_SEARCH_ALWAYS_EXPAND)) {
                 startActivity(getTrampolineIntent(intent, highlightMenuKey)
                         .setClass(this, DeepLinkHomepageActivityInternal.class)
@@ -139,9 +138,9 @@
         finish();
     }
 
-    private boolean isSettingsIntelligence(ComponentName callingActivity) {
-        return callingActivity != null && TextUtils.equals(
-                callingActivity.getPackageName(),
+    private boolean isSettingsIntelligence(String callerPackage) {
+        return TextUtils.equals(
+                callerPackage,
                 FeatureFactory.getFeatureFactory().getSearchFeatureProvider()
                         .getSettingsIntelligencePkgName(this));
     }
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettingsMoreOptions.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettingsMoreOptions.kt
index 7f7d8c5..1ed5959 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettingsMoreOptions.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettingsMoreOptions.kt
@@ -17,6 +17,7 @@
 package com.android.settings.spa.app.appinfo
 
 import android.app.AppOpsManager
+import android.app.ecm.EnhancedConfirmationManager
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import android.os.UserManager
@@ -90,12 +91,18 @@
 
 private fun ApplicationInfo.allowRestrictedSettings(context: Context, onSuccess: () -> Unit) {
     AppInfoDashboardFragment.showLockScreen(context) {
-        context.appOpsManager.setMode(
-            AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
-            uid,
-            packageName,
-            AppOpsManager.MODE_ALLOWED,
-        )
+        if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
+                && android.security.Flags.extendEcmToAllSettings()) {
+            val manager = context.getSystemService(EnhancedConfirmationManager::class.java)!!
+            manager.clearRestriction(packageName)
+        } else {
+            context.appOpsManager.setMode(
+                AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
+                uid,
+                packageName,
+                AppOpsManager.MODE_ALLOWED,
+            )
+        }
         onSuccess()
         val toastString = context.getString(
             R.string.toast_allows_restricted_settings_successfully,
@@ -137,7 +144,7 @@
         )
     }
     val shouldShowAccessRestrictedSettingsDeferred = async {
-        shouldShowAccessRestrictedSettings(context.appOpsManager)
+        shouldShowAccessRestrictedSettings(context)
     }
     val isProfileOrDeviceOwner =
         Utils.isProfileOrDeviceOwner(context.userManager, context.devicePolicyManager, packageName)
@@ -169,7 +176,14 @@
     .filter { it.id != userId }
     .any { packageManagers.isPackageInstalledAsUser(packageName, it.id) }
 
-private fun ApplicationInfo.shouldShowAccessRestrictedSettings(appOpsManager: AppOpsManager) =
-    appOpsManager.noteOpNoThrow(
-        AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, uid, packageName, null, null
-    ) == AppOpsManager.MODE_IGNORED
+private fun ApplicationInfo.shouldShowAccessRestrictedSettings(context: Context): Boolean {
+    return if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
+            && android.security.Flags.extendEcmToAllSettings()) {
+        val manager = context.getSystemService(EnhancedConfirmationManager::class.java)!!
+        manager.isClearRestrictionAllowed(packageName)
+    } else {
+        context.appOpsManager.noteOpNoThrow(
+            AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, uid, packageName, null, null
+        ) == AppOpsManager.MODE_IGNORED
+    }
+}
diff --git a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
index b6d83f2..351ac77 100644
--- a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
+++ b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
@@ -219,24 +219,24 @@
             mutableStateOf(false)
         }
         //TODO: Add the Restricted TwoTargetSwitchPreference in SPA
-        TwoTargetSwitchPreference(remember {
-            object : SwitchPreferenceModel {
-                override val title = subInfo.displayName.toString()
-                override val summary = { subInfo.number }
-                override val checked = {
-                    coroutineScope.launch {
-                        withContext(Dispatchers.Default) {
-                            checked.value = subscriptionManager?.isSubscriptionEnabled(
+        TwoTargetSwitchPreference(
+                object : SwitchPreferenceModel {
+                    override val title = subInfo.displayName.toString()
+                    override val summary = { subInfo.number }
+                    override val checked = {
+                        coroutineScope.launch {
+                            withContext(Dispatchers.Default) {
+                                checked.value = subscriptionManager?.isSubscriptionEnabled(
                                     subInfo.subscriptionId)?:false
+                            }
                         }
+                        checked.value
                     }
-                    checked.value
+                    override val onCheckedChange = { newChecked: Boolean ->
+                        startToggleSubscriptionDialog(context, subInfo, newChecked)
+                    }
                 }
-                override val onCheckedChange = { newChecked: Boolean ->
-                    startToggleSubscriptionDialog(context, subInfo, newChecked)
-                }
-            }
-        }) {
+        ) {
             startMobileNetworkSettings(context, subInfo)
         }
     }
@@ -258,7 +258,7 @@
 }
 
 @Composable
-fun PrimarySimSectionImpl(
+fun PrimarySimImpl(
     subscriptionInfoList: List<SubscriptionInfo>,
     callsSelectedId: MutableIntState,
     textsSelectedId: MutableIntState,
@@ -318,15 +318,18 @@
         for (info in subscriptionInfoList) {
             var item = ListPreferenceOption(
                     id = info.subscriptionId,
-                    text = "${info.displayName}"
+                    text = "${info.displayName}",
+                    summary = "${info.number}"
             )
             callsAndSmsList.add(item)
             dataList.add(item)
         }
-        callsAndSmsList.add(ListPreferenceOption(
+        callsAndSmsList.add(
+            ListPreferenceOption(
                 id = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
                 text = stringResource(id = R.string.sim_calls_ask_first_prefs_title)
-        ))
+            )
+        )
     } else {
         // hide the primary sim
         state.value = false
@@ -341,33 +344,31 @@
             mutableStateOf(false)
         }
 
-        Category(title = stringResource(id = R.string.primary_sim_title)) {
-            CreatePrimarySimListPreference(
-                    stringResource(id = R.string.primary_sim_calls_title),
-                    callsAndSmsList,
-                    callsSelectedId,
-                    ImageVector.vectorResource(R.drawable.ic_phone),
-                    actionSetCalls
-            )
-            CreatePrimarySimListPreference(
-                    stringResource(id = R.string.primary_sim_texts_title),
-                    callsAndSmsList,
-                    textsSelectedId,
-                    Icons.AutoMirrored.Outlined.Message,
-                    actionSetTexts
-            )
-            CreatePrimarySimListPreference(
-                    stringResource(id = R.string.mobile_data_settings_title),
-                    dataList,
-                    mobileDataSelectedId,
-                    Icons.Outlined.DataUsage,
-                    actionSetMobileData
-            )
-        }
+        CreatePrimarySimListPreference(
+            stringResource(id = R.string.primary_sim_calls_title),
+            callsAndSmsList,
+            callsSelectedId,
+            ImageVector.vectorResource(R.drawable.ic_phone),
+            actionSetCalls
+        )
+        CreatePrimarySimListPreference(
+            stringResource(id = R.string.primary_sim_texts_title),
+            callsAndSmsList,
+            textsSelectedId,
+            Icons.AutoMirrored.Outlined.Message,
+            actionSetTexts
+        )
+        CreatePrimarySimListPreference(
+            stringResource(id = R.string.mobile_data_settings_title),
+            dataList,
+            mobileDataSelectedId,
+            Icons.Outlined.DataUsage,
+            actionSetMobileData
+        )
 
         val autoDataTitle = stringResource(id = R.string.primary_sim_automatic_data_title)
         val autoDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg)
-        SwitchPreference(remember {
+        SwitchPreference(
             object : SwitchPreferenceModel {
                 override val title = autoDataTitle
                 override val summary = { autoDataSummary }
@@ -375,6 +376,11 @@
                     if (nonDds.intValue != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                         coroutineScope.launch {
                             automaticDataChecked.value = getAutomaticData(telephonyManagerForNonDds)
+                            Log.d(
+                                NetworkCellularGroupProvider.name,
+                                "NonDds:${nonDds.intValue}" +
+                                    "getAutomaticData:${automaticDataChecked.value}"
+                            )
                         }
                     }
                     automaticDataChecked.value
@@ -384,7 +390,26 @@
                     actionSetAutoDataSwitch(it)
                 }
             }
-        })
+        )
+    }
+}
+
+@Composable
+fun PrimarySimSectionImpl(
+    subscriptionInfoList: List<SubscriptionInfo>,
+    callsSelectedId: MutableIntState,
+    textsSelectedId: MutableIntState,
+    mobileDataSelectedId: MutableIntState,
+    nonDds: MutableIntState,
+) {
+    Category(title = stringResource(id = R.string.primary_sim_title)) {
+        PrimarySimImpl(
+            subscriptionInfoList,
+            callsSelectedId,
+            textsSelectedId,
+            mobileDataSelectedId,
+            nonDds
+        )
     }
 }
 
@@ -442,32 +467,42 @@
 }
 
 suspend fun setDefaultVoice(
-        subscriptionManager: SubscriptionManager?,
-        subId: Int): Unit = withContext(Dispatchers.Default) {
-    subscriptionManager?.setDefaultVoiceSubscriptionId(subId)
-}
+    subscriptionManager: SubscriptionManager?,
+    subId: Int
+): Unit =
+    withContext(Dispatchers.Default) {
+        subscriptionManager?.setDefaultVoiceSubscriptionId(subId)
+    }
 
 suspend fun setDefaultSms(
-        subscriptionManager: SubscriptionManager?,
-        subId: Int): Unit = withContext(Dispatchers.Default) {
-    subscriptionManager?.setDefaultSmsSubId(subId)
-}
+    subscriptionManager: SubscriptionManager?,
+    subId: Int
+): Unit =
+    withContext(Dispatchers.Default) {
+        subscriptionManager?.setDefaultSmsSubId(subId)
+    }
 
-suspend fun setDefaultData(context: Context,
-                                   subscriptionManager: SubscriptionManager?,
-                                   wifiPickerTrackerHelper: WifiPickerTrackerHelper?,
-                                   subId: Int): Unit = withContext(Dispatchers.Default) {
-    subscriptionManager?.setDefaultDataSubId(subId)
-    MobileNetworkUtils.setMobileDataEnabled(
+suspend fun setDefaultData(
+    context: Context,
+    subscriptionManager: SubscriptionManager?,
+    wifiPickerTrackerHelper: WifiPickerTrackerHelper?,
+    subId: Int
+): Unit =
+    withContext(Dispatchers.Default) {
+        subscriptionManager?.setDefaultDataSubId(subId)
+        MobileNetworkUtils.setMobileDataEnabled(
             context,
             subId,
             true /* enabled */,
-            true /* disableOtherSubscriptions */)
-    if (wifiPickerTrackerHelper != null
-            && !wifiPickerTrackerHelper.isCarrierNetworkProvisionEnabled(subId)) {
-        wifiPickerTrackerHelper.setCarrierNetworkEnabled(true)
+            true /* disableOtherSubscriptions */
+        )
+        if (wifiPickerTrackerHelper != null
+            && !wifiPickerTrackerHelper.isCarrierNetworkProvisionEnabled(subId)
+        ) {
+            wifiPickerTrackerHelper.setCarrierNetworkEnabled(true)
+        }
     }
-}
+
 suspend fun getAutomaticData(telephonyManagerForNonDds: TelephonyManager?): Boolean =
     withContext(Dispatchers.Default) {
         telephonyManagerForNonDds != null
@@ -478,7 +513,7 @@
 suspend fun setAutomaticData(telephonyManager: TelephonyManager?, newState: Boolean): Unit =
     withContext(Dispatchers.Default) {
         Log.d(
-            "NetworkCellularGroupProvider",
+            NetworkCellularGroupProvider.name,
             "setAutomaticData: MOBILE_DATA_POLICY_AUTO_DATA_SWITCH as $newState"
         )
         telephonyManager?.setMobileDataPolicyEnabled(
diff --git a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
index e88c5c7..3b2d5ec 100644
--- a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
@@ -20,6 +20,7 @@
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.SignalCellularAlt
+import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
@@ -91,11 +92,13 @@
             },
             title = stringResource(R.string.sim_onboarding_label_sim_dialog_title),
             text = {
-                Text(summaryNumber)
+                Text(summaryNumber,
+                    modifier = Modifier.padding(bottom = SettingsDimension.itemPaddingVertical))
                 SettingsOutlinedTextField(
                     value = titleSimName,
                     label = stringResource(R.string.sim_onboarding_label_sim_dialog_label),
-                    enabled = true
+                    enabled = true,
+                    shape = MaterialTheme.shapes.extraLarge
                 ) {
                     titleSimName = it
                 }
diff --git a/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt b/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
index 999abb4..a5f55d0 100644
--- a/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
@@ -24,7 +24,6 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.MutableIntState
 import androidx.compose.runtime.mutableIntStateOf
-import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
@@ -82,7 +81,7 @@
         callsSelectedId.intValue = onboardingService.targetPrimarySimCalls
         textsSelectedId.intValue = onboardingService.targetPrimarySimTexts
         mobileDataSelectedId.intValue = onboardingService.targetPrimarySimMobileData
-        PrimarySimSectionImpl(
+        PrimarySimImpl(
             subscriptionInfoList = selectedSubscriptionInfoList,
             callsSelectedId = callsSelectedId,
             textsSelectedId = textsSelectedId,
@@ -110,7 +109,7 @@
         selectedId: MutableIntState,
         icon: ImageVector,
         onIdSelected: (id: Int) -> Unit
-) = ListPreference(remember {
+) = ListPreference(
     object : ListPreferenceModel {
         override val title = title
         override val options = list
@@ -119,5 +118,4 @@
         override val icon = @Composable {
             SettingsIcon(icon)
         }
-    }
 })
\ No newline at end of file
diff --git a/src/com/android/settings/utils/ManagedServiceSettings.java b/src/com/android/settings/utils/ManagedServiceSettings.java
index d5f0040..9f5fbc5 100644
--- a/src/com/android/settings/utils/ManagedServiceSettings.java
+++ b/src/com/android/settings/utils/ManagedServiceSettings.java
@@ -37,14 +37,14 @@
 import androidx.appcompat.app.AlertDialog;
 import androidx.fragment.app.Fragment;
 import androidx.preference.PreferenceScreen;
-import androidx.preference.TwoStatePreference;
 
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 import com.android.settings.widget.EmptyTextSettings;
+import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.applications.ServiceListing;
-import com.android.settingslib.widget.AppSwitchPreference;
+import com.android.settingslib.widget.TwoTargetPreference;
 
 import java.util.List;
 
@@ -121,10 +121,12 @@
             }
             final CharSequence finalTitle = title;
             final String summary = service.loadLabel(mPm).toString();
-            final TwoStatePreference pref = new AppSwitchPreference(getPrefContext());
+            final RestrictedSwitchPreference pref =
+                    new RestrictedSwitchPreference(getPrefContext());
             pref.setPersistent(false);
             pref.setIcon(mIconDrawableFactory.getBadgedIcon(service, service.applicationInfo,
                     UserHandle.getUserId(service.applicationInfo.uid)));
+            pref.setIconSize(TwoTargetPreference.ICON_SIZE_MEDIUM);
             if (title != null && !title.equals(summary)) {
                 pref.setTitle(title);
                 pref.setSummary(summary);
@@ -150,6 +152,9 @@
                 }
             });
             pref.setKey(cn.flattenToString());
+            if (!pref.isChecked()) {
+                pref.checkEcmRestrictionAndSetDisabled(mConfig.permission, service.packageName);
+            }
             screen.addPreference(pref);
         }
         highlightPreferenceIfNeeded();
diff --git a/src/com/android/settings/widget/RestrictedAppPreference.java b/src/com/android/settings/widget/RestrictedAppPreference.java
index f93b935..c76a5de 100644
--- a/src/com/android/settings/widget/RestrictedAppPreference.java
+++ b/src/com/android/settings/widget/RestrictedAppPreference.java
@@ -21,6 +21,7 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 
+import androidx.annotation.NonNull;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceViewHolder;
 
@@ -72,10 +73,18 @@
 
     @Override
     public void setEnabled(boolean enabled) {
-        if (isDisabledByAdmin() && enabled) {
-            return;
+        boolean changed = false;
+        if (enabled && isDisabledByAdmin()) {
+            mHelper.setDisabledByAdmin(null);
+            changed = true;
         }
-        super.setEnabled(enabled);
+        if (enabled && isDisabledByEcm()) {
+            mHelper.setDisabledByEcm(null);
+            changed = true;
+        }
+        if (!changed) {
+            super.setEnabled(enabled);
+        }
     }
 
     public void setDisabledByAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
@@ -88,6 +97,10 @@
         return mHelper.isDisabledByAdmin();
     }
 
+    public boolean isDisabledByEcm() {
+        return mHelper.isDisabledByEcm();
+    }
+
     public void useAdminDisabledSummary(boolean useSummary) {
         mHelper.useAdminDisabledSummary(useSummary);
     }
@@ -112,4 +125,15 @@
     public void checkRestrictionAndSetDisabled(String userRestriction, int userId) {
         mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
     }
+
+    /**
+     * Checks if the given setting is subject to Enhanced Confirmation Mode restrictions for this
+     * package. Marks the preference as disabled if so.
+     * @param settingIdentifier The key identifying the setting
+     * @param packageName the package to check the settingIdentifier for
+     */
+    public void checkEcmRestrictionAndSetDisabled(@NonNull String settingIdentifier,
+                                                  @NonNull String packageName) {
+        mHelper.checkEcmRestrictionAndSetDisabled(settingIdentifier, packageName);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java
index c105d08..d88a83e 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java
@@ -38,6 +38,7 @@
 
 import com.android.settings.SettingsActivity;
 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 
 import com.google.common.collect.ImmutableList;
 
@@ -57,7 +58,10 @@
 import java.util.List;
 
 /** Tests for {@link AccessibilityDetailsSettingsFragment}. */
-@Config(shadows = ShadowDevicePolicyManager.class)
+@Config(shadows = {
+        ShadowDevicePolicyManager.class,
+        ShadowRestrictedLockUtilsInternal.class
+})
 @RunWith(RobolectricTestRunner.class)
 public class AccessibilityDetailsSettingsFragmentTest {
     private static final String PACKAGE_NAME = "com.foo.bar";
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
index db6f43b..05e56ca 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
@@ -52,6 +52,7 @@
 import com.android.settings.testutils.shadow.ShadowApplicationPackageManager;
 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
 import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 import com.android.settings.testutils.shadow.ShadowUserManager;
 import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -87,6 +88,7 @@
         ShadowUserManager.class,
         ShadowColorDisplayManager.class,
         ShadowApplicationPackageManager.class,
+        ShadowRestrictedLockUtilsInternal.class,
 })
 public class AccessibilitySettingsTest {
     private static final String PACKAGE_NAME = "com.android.test";
diff --git a/tests/robotests/src/com/android/settings/accessibility/RestrictedPreferenceHelperTest.java b/tests/robotests/src/com/android/settings/accessibility/RestrictedPreferenceHelperTest.java
index 99a78cf..bc9c1d8 100644
--- a/tests/robotests/src/com/android/settings/accessibility/RestrictedPreferenceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/RestrictedPreferenceHelperTest.java
@@ -31,9 +31,14 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
 import com.android.settingslib.RestrictedPreference;
 
 import org.junit.Rule;
@@ -45,6 +50,7 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
@@ -53,6 +59,9 @@
 
 /** Test for {@link RestrictedPreferenceHelper}. */
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        ShadowRestrictedLockUtilsInternal.class
+})
 public class RestrictedPreferenceHelperTest {
 
     private static final String PACKAGE_NAME = "com.android.test";
@@ -72,6 +81,11 @@
     private AccessibilityShortcutInfo mShortcutInfo;
     private final RestrictedPreferenceHelper mHelper = new RestrictedPreferenceHelper(mContext);
 
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
     @Test
     public void createAccessibilityServicePreferenceList_hasOneInfo_containsSameKey() {
         final String key = COMPONENT_NAME.flattenToString();
@@ -86,6 +100,37 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
+            android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED})
+    public void createAccessibilityServicePreferenceList_ecmRestricted_prefIsEcmRestricted() {
+        ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(
+                mServiceInfo.getResolveInfo().serviceInfo.packageName);
+        final List<AccessibilityServiceInfo> infoList = new ArrayList<>(
+                singletonList(mServiceInfo));
+
+        final List<RestrictedPreference> preferenceList =
+                mHelper.createAccessibilityServicePreferenceList(infoList);
+        final RestrictedPreference preference = preferenceList.get(0);
+
+        assertThat(preference.isDisabledByEcm()).isTrue();
+    }
+
+    @Test
+    @RequiresFlagsEnabled(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
+            android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED})
+    public void createAccessibilityServicePreferenceList_ecmNotRestricted_prefIsNotEcmRestricted() {
+        ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
+        final List<AccessibilityServiceInfo> infoList = new ArrayList<>(
+                singletonList(mServiceInfo));
+
+        final List<RestrictedPreference> preferenceList =
+                mHelper.createAccessibilityServicePreferenceList(infoList);
+        final RestrictedPreference preference = preferenceList.get(0);
+
+        assertThat(preference.isDisabledByEcm()).isFalse();
+    }
+
+    @Test
     public void createAccessibilityActivityPreferenceList_hasOneInfo_containsSameKey() {
         final String key = COMPONENT_NAME.flattenToString();
         setMockAccessibilityShortcutInfo(mShortcutInfo);
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccessTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccessTest.java
index e91c0fa..46b1910 100644
--- a/tests/robotests/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccessTest.java
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/premiumsms/PremiumSmsAccessTest.java
@@ -16,13 +16,35 @@
 
 package com.android.settings.applications.specialaccess.premiumsms;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.os.Process;
 import android.telephony.SmsManager;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.R;
 
 import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.datausage.AppStateDataUsageBridge;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedDropDownPreference;
+import com.android.settingslib.applications.ApplicationsState;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -30,19 +52,28 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.ArrayList;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        ShadowRestrictedLockUtilsInternal.class
+})
 public class PremiumSmsAccessTest {
 
     private FakeFeatureFactory mFeatureFactory;
     private PremiumSmsAccess mFragment;
+    private Context mContext;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mFeatureFactory = FakeFeatureFactory.setupForTest();
         mFragment = new PremiumSmsAccess();
-        mFragment.onAttach(RuntimeEnvironment.application);
+        mContext = RuntimeEnvironment.application;
+        mFragment.onAttach(mContext);
     }
 
     @Test
@@ -74,4 +105,89 @@
                 "app",
                 SmsManager.PREMIUM_SMS_CONSENT_ALWAYS_ALLOW);
     }
+
+    @Test
+    public void onRebuildComplete_ecmRestricted_shouldBeDisabled() {
+        mFragment = spy(mFragment);
+        mContext = spy(mContext);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        View view = inflater.inflate(R.layout.preference_dropdown, null);
+        PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
+
+        PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        PreferenceScreen preferenceScreen = spy(preferenceManager.createPreferenceScreen(mContext));
+        doReturn(preferenceManager).when(mFragment).getPreferenceManager();
+        doReturn(preferenceScreen).when(mFragment).getPreferenceScreen();
+        final String testPkg = "com.example.disabled";
+        doNothing().when(mContext).startActivity(any());
+        ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(testPkg);
+
+        doAnswer((invocation) -> {
+            final RestrictedDropDownPreference preference = invocation.getArgument(0);
+            // Verify preference is disabled by ecm and the summary is changed accordingly.
+            assertThat(preference.isDisabledByEcm()).isTrue();
+            assertThat(preference.getSummary().toString()).isEqualTo(
+                    mContext.getString(
+                            com.android.settingslib.R.string.disabled_by_app_ops_text));
+            preference.onBindViewHolder(holder);
+            preference.performClick();
+            // Verify that when the preference is clicked, ecm details intent is launched
+            verify(mContext).startActivity(any());
+
+            return null;
+        }).when(preferenceScreen).addPreference(any(RestrictedDropDownPreference.class));
+
+        mFragment.onRebuildComplete(createAppEntries(testPkg));
+        verify(preferenceScreen).addPreference(any(RestrictedDropDownPreference.class));
+    }
+
+    @Test
+    public void onRebuildComplete_ecmNotRestricted_notDisabled() {
+        mFragment = spy(mFragment);
+        mContext = spy(mContext);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        View view = inflater.inflate(R.layout.preference_dropdown, null);
+        PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
+
+        PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        PreferenceScreen preferenceScreen = spy(preferenceManager.createPreferenceScreen(mContext));
+        doReturn(preferenceManager).when(mFragment).getPreferenceManager();
+        doReturn(preferenceScreen).when(mFragment).getPreferenceScreen();
+        final String testPkg = "com.example.enabled";
+        ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
+
+
+        doAnswer((invocation) -> {
+            final RestrictedDropDownPreference preference = invocation.getArgument(0);
+            assertThat(preference.isDisabledByEcm()).isFalse();
+            assertThat(preference.getSummary().toString()).isEqualTo("");
+            preference.onBindViewHolder(holder);
+            preference.performClick();
+            // Verify that when the preference is clicked, ecm details intent is not launched
+            verify(mContext, never()).startActivity(any());
+
+            return null;
+        }).when(preferenceScreen).addPreference(any(RestrictedDropDownPreference.class));
+
+        mFragment.onRebuildComplete(createAppEntries(testPkg));
+        verify(preferenceScreen).addPreference(any(RestrictedDropDownPreference.class));
+    }
+
+    private ArrayList<ApplicationsState.AppEntry> createAppEntries(String... packageNames) {
+        final ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
+        for (int i = 0; i < packageNames.length; ++i) {
+            final ApplicationInfo info = new ApplicationInfo();
+            info.packageName = packageNames[i];
+            info.uid = Process.FIRST_APPLICATION_UID + i;
+            info.sourceDir = info.packageName;
+            final ApplicationsState.AppEntry appEntry =
+                    spy(new ApplicationsState.AppEntry(mContext, info, i));
+            appEntry.extraInfo = new AppStateDataUsageBridge
+                    .DataUsageState(false, false);
+            doNothing().when(appEntry).ensureLabel(any(Context.class));
+            ReflectionHelpers.setField(appEntry, "info", info);
+            appEntries.add(appEntry);
+        }
+        return appEntries;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
index beb7a9f..a56c34c 100644
--- a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
@@ -43,6 +43,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.hardware.face.Face;
+import android.hardware.face.FaceEnrollOptions;
 import android.hardware.face.FaceManager;
 import android.hardware.face.FaceSensorProperties;
 import android.hardware.face.FaceSensorPropertiesInternal;
@@ -196,6 +197,8 @@
         final Intent testIntent = new Intent();
         // Set the challenge token so the confirm screen will not be shown
         testIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
+        testIntent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
+                FaceEnrollOptions.ENROLL_REASON_SETTINGS);
 
         when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any())).thenReturn(
                 null /* Simulate no posture intent */);
@@ -220,6 +223,8 @@
         testIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
         testIntent.putExtra(EXTRA_KEY_NEXT_LAUNCHED, false);
         testIntent.putExtra(EXTRA_LAUNCHED_POSTURE_GUIDANCE, false);
+        testIntent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
+                FaceEnrollOptions.ENROLL_REASON_SETTINGS);
 
         when(mFakeFeatureFactory.mFaceFeatureProvider.getPostureGuidanceIntent(any())).thenReturn(
                 testIntent);
@@ -641,4 +646,14 @@
         final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
         assertThat(dialog).isNull();
     }
+
+    @Test
+    public void testFaceEnrollIntroduction_forwardsEnrollOptions() {
+        setupActivity();
+        final Intent intent = mActivity.getEnrollingIntent();
+
+        assertThat(intent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1))
+                .isEqualTo(FaceEnrollOptions.ENROLL_REASON_SETTINGS);
+    }
+
 }
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
index 4de369e..91707cd 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
@@ -669,7 +669,8 @@
                         any(CancellationSignal.class),
                         anyInt(),
                         callbackCaptor.capture(),
-                        eq(FingerprintManager.ENROLL_ENROLL));
+                        eq(FingerprintManager.ENROLL_ENROLL),
+                        any());
 
         return callbackCaptor.getValue();
     }
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
index 4d13bb6..68395b2 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
@@ -227,7 +227,8 @@
                 any(CancellationSignal.class),
                 anyInt(),
                 callbackCaptor.capture(),
-                eq(FingerprintManager.ENROLL_FIND_SENSOR));
+                eq(FingerprintManager.ENROLL_FIND_SENSOR),
+                any());
 
         return callbackCaptor.getValue();
     }
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
index 3eba91c..89e70d2 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
@@ -40,6 +40,7 @@
 import android.hardware.biometrics.ComponentInfoInternal;
 import android.hardware.biometrics.SensorProperties;
 import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintEnrollOptions;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorProperties;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
@@ -52,6 +53,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.VerifyCredentialResponse;
 import com.android.settings.R;
+import com.android.settings.biometrics.BiometricUtils;
 import com.android.settings.biometrics.GatekeeperPasswordProvider;
 
 import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -289,6 +291,18 @@
         assertThat(mFingerprintEnrollIntroduction.shouldFinishWhenBackgrounded()).isEqualTo(true);
     }
 
+    @Test
+    public void testFingerprintEnrollIntroduction_forwardsEnrollOptions() {
+        final Intent intent = newTokenOnlyIntent();
+        intent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
+                FingerprintEnrollOptions.ENROLL_REASON_SETTINGS);
+        setupFingerprintEnrollIntroWith(intent);
+
+        final Intent enrollingIntent = mFingerprintEnrollIntroduction.getEnrollingIntent();
+        assertThat(enrollingIntent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1))
+                .isEqualTo(FingerprintEnrollOptions.ENROLL_REASON_SUW);
+    }
+
     private Intent newTokenOnlyIntent() {
         return new Intent()
                 .putExtra(EXTRA_KEY_CHALLENGE_TOKEN, new byte[] { 1 });
diff --git a/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java
index dceadeb..5a7e247 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java
@@ -16,7 +16,6 @@
 package com.android.settings.bluetooth;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
@@ -25,36 +24,26 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothStatusCodes;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.util.Pair;
 
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
+import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.flags.Flags;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowAudioManager;
 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
 import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
-import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
-import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -75,9 +64,6 @@
             ShadowBluetoothUtils.class
         })
 public class AvailableMediaBluetoothDeviceUpdaterTest {
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
-
     private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
 
     @Mock private DashboardFragment mDashboardFragment;
@@ -86,11 +72,7 @@
     @Mock private BluetoothDevice mBluetoothDevice;
     @Mock private Drawable mDrawable;
     @Mock private LocalBluetoothManager mLocalBtManager;
-    @Mock private LocalBluetoothProfileManager mLocalBtProfileManager;
     @Mock private CachedBluetoothDeviceManager mCachedDeviceManager;
-    @Mock private LocalBluetoothLeBroadcast mBroadcast;
-    @Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
-    @Mock private BluetoothLeBroadcastReceiveState mBroadcastReceiveState;
 
     private Context mContext;
     private AvailableMediaBluetoothDeviceUpdater mBluetoothDeviceUpdater;
@@ -98,12 +80,14 @@
     private AudioManager mAudioManager;
     private BluetoothDevicePreference mPreference;
     private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+    private AudioSharingFeatureProvider mFeatureProvider;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
         mContext = RuntimeEnvironment.application;
+        mFeatureProvider = FakeFeatureFactory.setupForTest().getAudioSharingFeatureProvider();
         mAudioManager = mContext.getSystemService(AudioManager.class);
         ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
         mLocalBtManager = Utils.getLocalBtManager(mContext);
@@ -267,13 +251,15 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
-    public void onProfileConnectionStateChanged_leAudioDeviceConnected_notInCall_addsPreference() {
-        setUpBroadcast(/* isSupported= */ false, /* isBroadcasting= */ false);
+    public void
+            onProfileConnectionStateChanged_leaDeviceConnected_notInCallNoSharing_addsPreference() {
         mAudioManager.setMode(AudioManager.MODE_NORMAL);
         when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
                 .thenReturn(true);
         when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
+        when(mFeatureProvider.isAudioSharingFilterMatched(
+                        any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class)))
+                .thenReturn(false);
 
         mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
                 mCachedBluetoothDevice,
@@ -284,13 +270,15 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
-    public void onProfileConnectionStateChanged_leAudioDeviceConnected_inCall_addsPreference() {
-        setUpBroadcast(/* isSupported= */ false, /* isBroadcasting= */ false);
+    public void
+            onProfileConnectionStateChanged_leaDeviceConnected_inCallNoSharing_addsPreference() {
         mAudioManager.setMode(AudioManager.MODE_IN_CALL);
         when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
                 .thenReturn(true);
         when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
+        when(mFeatureProvider.isAudioSharingFilterMatched(
+                        any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class)))
+                .thenReturn(false);
 
         mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
                 mCachedBluetoothDevice,
@@ -301,50 +289,16 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
     public void
-            onProfileConnectionStateChanged_leaDeviceConnected_notInCall_notInBroadcast_addsPref() {
-        setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ false);
+            onProfileConnectionStateChanged_leaDeviceConnected_notInCallInSharing_removesPref() {
         mAudioManager.setMode(AudioManager.MODE_NORMAL);
         when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
                 .thenReturn(true);
         when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
-
-        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
-                mCachedBluetoothDevice,
-                BluetoothProfile.STATE_CONNECTED,
-                BluetoothProfile.LE_AUDIO);
-
-        verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
-    public void
-            onProfileConnectionStateChanged_leaDeviceConnected_inCall_notInBroadcast_addsPref() {
-        setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ false);
-        mAudioManager.setMode(AudioManager.MODE_IN_CALL);
-        when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
+        when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
+        when(mFeatureProvider.isAudioSharingFilterMatched(
+                        any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class)))
                 .thenReturn(true);
-        when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
-
-        mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
-                mCachedBluetoothDevice,
-                BluetoothProfile.STATE_CONNECTED,
-                BluetoothProfile.LE_AUDIO);
-
-        verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
-    public void
-            onProfileConnectionStateChanged_leaDeviceConnected_notInCall_inBroadcast_removesPref() {
-        setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ true);
-        mAudioManager.setMode(AudioManager.MODE_NORMAL);
-        when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
-                .thenReturn(true);
-        when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
 
         mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
                 mCachedBluetoothDevice,
@@ -355,14 +309,15 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
-    public void
-            onProfileConnectionStateChanged_leaDeviceConnected_inCall_inBroadcast_removesPref() {
-        setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ true);
-        mAudioManager.setMode(AudioManager.MODE_IN_CALL);
+    public void onProfileConnectionStateChanged_leaDeviceConnected_inCallInSharing_removesPref() {
+        mAudioManager.setMode(AudioManager.MODE_NORMAL);
         when(mBluetoothDeviceUpdater.isDeviceConnected(any(CachedBluetoothDevice.class)))
                 .thenReturn(true);
         when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
+        when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
+        when(mFeatureProvider.isAudioSharingFilterMatched(
+                        any(CachedBluetoothDevice.class), any(LocalBluetoothManager.class)))
+                .thenReturn(true);
 
         mBluetoothDeviceUpdater.onProfileConnectionStateChanged(
                 mCachedBluetoothDevice,
@@ -414,56 +369,9 @@
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
     public void onClick_Preference_setActive() {
-        setUpBroadcast(/* isSupported= */ false, /* isBroadcasting= */ false);
         mBluetoothDeviceUpdater.onPreferenceClick(mPreference);
 
         verify(mCachedBluetoothDevice).setActive();
     }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
-    public void onClick_Preference_isNotBroadcasting_setActive() {
-        setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ false);
-        mBluetoothDeviceUpdater.onPreferenceClick(mPreference);
-
-        verify(mCachedBluetoothDevice).setActive();
-    }
-
-    @Test
-    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
-    public void onClick_Preference_isBroadcasting_stopBroadcastingAndSetActive() {
-        setUpBroadcast(/* isSupported= */ true, /* isBroadcasting= */ true);
-        doNothing().when(mBroadcast).stopBroadcast(anyInt());
-        mBluetoothDeviceUpdater.onPreferenceClick(mPreference);
-
-        verify(mBroadcast).stopBroadcast(anyInt());
-        verify(mCachedBluetoothDevice).setActive();
-    }
-
-    private void setUpBroadcast(boolean isSupported, boolean isBroadcasting) {
-        if (isSupported) {
-            mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
-                    BluetoothStatusCodes.FEATURE_SUPPORTED);
-            mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
-                    BluetoothStatusCodes.FEATURE_SUPPORTED);
-            when(mLocalBtManager.getProfileManager()).thenReturn(mLocalBtProfileManager);
-            when(mLocalBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
-            when(mBroadcast.isEnabled(null)).thenReturn(isBroadcasting);
-            when(mLocalBtProfileManager.getLeAudioBroadcastAssistantProfile())
-                    .thenReturn(mAssistant);
-            if (isBroadcasting) {
-                when(mAssistant.getAllSources(any()))
-                        .thenReturn(ImmutableList.of(mBroadcastReceiveState));
-            } else {
-                when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of());
-            }
-        } else {
-            mShadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
-                    BluetoothStatusCodes.FEATURE_NOT_SUPPORTED);
-            mShadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
-                    BluetoothStatusCodes.FEATURE_NOT_SUPPORTED);
-        }
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothAutoOnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothAutoOnPreferenceControllerTest.java
new file mode 100644
index 0000000..d82dcc4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothAutoOnPreferenceControllerTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 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.bluetooth;
+
+import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.DISABLED;
+import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.ENABLED;
+import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.PREF_KEY;
+import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.SETTING_NAME;
+import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.UNSET;
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+import static com.android.settingslib.flags.Flags.FLAG_BLUETOOTH_QS_TILE_DIALOG_AUTO_ON_TOGGLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Settings;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothAutoOnPreferenceControllerTest {
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+    private Context mContext;
+    private ContentResolver mContentResolver;
+    private BluetoothAutoOnPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        mSetFlagsRule.enableFlags(FLAG_BLUETOOTH_QS_TILE_DIALOG_AUTO_ON_TOGGLE);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mContentResolver = mContext.getContentResolver();
+        mController = new BluetoothAutoOnPreferenceController(mContext, PREF_KEY);
+    }
+
+    @Test
+    public void getAvailability_valueUnset_returnUnsupported() {
+        Settings.Secure.putInt(mContentResolver, SETTING_NAME, UNSET);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
+    public void getAvailability_valueSet_returnAvailable() {
+        Settings.Secure.putInt(mContentResolver, SETTING_NAME, DISABLED);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void isChecked_valueEnabled_returnTrue() {
+        Settings.Secure.putInt(mContentResolver, SETTING_NAME, ENABLED);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+        assertThat(mController.isChecked()).isEqualTo(true);
+    }
+
+    @Test
+    public void setChecked_returnTrue() {
+        Settings.Secure.putInt(mContentResolver, SETTING_NAME, DISABLED);
+
+        mController.setChecked(true);
+        assertThat(mController.isChecked()).isEqualTo(true);
+    }
+
+    @Test
+    public void setChecked_returnFalse() {
+        Settings.Secure.putInt(mContentResolver, SETTING_NAME, ENABLED);
+
+        mController.setChecked(false);
+        assertThat(mController.isChecked()).isEqualTo(false);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImplTest.java
new file mode 100644
index 0000000..0edbc77
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImplTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.connecteddevice.audiosharing;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioSharingFeatureProviderImplTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock private CachedBluetoothDevice mCachedDevice;
+    @Mock private LocalBluetoothManager mLocalBtManager;
+    @Mock private DashboardFragment mFragment;
+    private Context mContext;
+    private AudioSharingFeatureProviderImpl mFeatureProvider;
+
+    @Before
+    public void setUp() {
+        mContext = ApplicationProvider.getApplicationContext();
+        mFeatureProvider = new AudioSharingFeatureProviderImpl();
+    }
+
+    @Test
+    public void createAudioSharingDevicePreferenceController_returnsNull() {
+        assertThat(
+                        mFeatureProvider.createAudioSharingDevicePreferenceController(
+                                mContext, mFragment, /* lifecycle= */ null))
+                .isNull();
+    }
+
+    @Test
+    public void isAudioSharingFilterMatched_returnsFalse() {
+        assertThat(mFeatureProvider.isAudioSharingFilterMatched(mCachedDevice, mLocalBtManager))
+                .isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceControllerTest.java
index 8aa2e5a..ce47052 100644
--- a/tests/robotests/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceControllerTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -163,6 +164,81 @@
         mController.onRebuildComplete(createAppEntries(testPkg1, testPkg2));
     }
 
+    @Test
+    public void onRebuildComplete_ecmRestricted_shouldBeDisabled() {
+        mFragment = spy(new UnrestrictedDataAccess());
+        mContext = spy(mContext);
+        doNothing().when(mFragment).setLoading(anyBoolean(), anyBoolean());
+        mController.setParentFragment(mFragment);
+        mPreferenceManager = new PreferenceManager(mContext);
+        mPreferenceScreen = spy(mPreferenceManager.createPreferenceScreen(mContext));
+        doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
+        doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
+        doReturn(0).when(mPreferenceScreen).getPreferenceCount();
+        final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
+        ReflectionHelpers.setField(mController, "mDataSaverBackend", dataSaverBackend);
+        ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen);
+
+        final String testPkg = "com.example.disabled";
+        doNothing().when(mContext).startActivity(any());
+        ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(testPkg);
+
+        doAnswer((invocation) -> {
+            final UnrestrictedDataAccessPreference preference = invocation.getArgument(0);
+            // Verify preference is disabled by ecm and the summary is changed accordingly.
+            assertThat(preference.isDisabledByEcm()).isTrue();
+            assertThat(preference.getSummary().toString()).isEqualTo(
+                    mContext.getString(
+                            com.android.settingslib.R.string.disabled_by_app_ops_text));
+            assertThat(preference.isChecked()).isFalse();
+            preference.performClick();
+            // Verify that when the preference is clicked, ecm details intent is launched
+            assertThat(preference.isChecked()).isFalse();
+            verify(mContext).startActivity(any());
+
+            return null;
+        }).when(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
+
+        mController.onRebuildComplete(createAppEntries(testPkg));
+        verify(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
+    }
+
+    @Test
+    public void onRebuildComplete_ecmNotRestricted_notDisabled() {
+        mFragment = spy(new UnrestrictedDataAccess());
+        mContext = spy(mContext);
+        doNothing().when(mFragment).setLoading(anyBoolean(), anyBoolean());
+        mController.setParentFragment(mFragment);
+        mPreferenceManager = new PreferenceManager(mContext);
+        mPreferenceScreen = spy(mPreferenceManager.createPreferenceScreen(mContext));
+        doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
+        doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
+        doReturn(0).when(mPreferenceScreen).getPreferenceCount();
+        final DataSaverBackend dataSaverBackend = mock(DataSaverBackend.class);
+        ReflectionHelpers.setField(mController, "mDataSaverBackend", dataSaverBackend);
+        ReflectionHelpers.setField(mController, "mScreen", mPreferenceScreen);
+
+        final String testPkg = "com.example.enabled";
+        doNothing().when(mContext).startActivity(any());
+        ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
+
+        doAnswer((invocation) -> {
+            final UnrestrictedDataAccessPreference preference = invocation.getArgument(0);
+            assertThat(preference.isDisabledByEcm()).isFalse();
+            assertThat(preference.getSummary()).isEqualTo("");
+            assertThat(preference.isChecked()).isFalse();
+            preference.performClick();
+            // Verify that when the preference is clicked, ecm details intent is not launched
+            assertThat(preference.isChecked()).isTrue();
+            verify(mContext, never()).startActivity(any());
+
+            return null;
+        }).when(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
+
+        mController.onRebuildComplete(createAppEntries(testPkg));
+        verify(mPreferenceScreen).addPreference(any(UnrestrictedDataAccessPreference.class));
+    }
+
     private ArrayList<AppEntry> createAppEntries(String... packageNames) {
         final ArrayList<AppEntry> appEntries = new ArrayList<>();
         for (int i = 0; i < packageNames.length; ++i) {
diff --git a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
index f349600..8a7419b 100644
--- a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java
@@ -20,7 +20,6 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.app.settings.SettingsEnums;
-import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ResolveInfo;
@@ -131,20 +130,22 @@
 
     @Test(expected = SecurityException.class)
     public void verifyLaunchSearchResultPageCaller_badCaller_shouldCrash() {
-        final ComponentName cn = new ComponentName("pkg", "class");
-        mProvider.verifyLaunchSearchResultPageCaller(mActivity, cn);
+        final String packageName = "pkg";
+
+        mProvider.verifyLaunchSearchResultPageCaller(mActivity, packageName);
     }
 
     @Test
     public void verifyLaunchSearchResultPageCaller_settingsCaller_shouldNotCrash() {
-        final ComponentName cn = new ComponentName(mActivity.getPackageName(), "class");
-        mProvider.verifyLaunchSearchResultPageCaller(mActivity, cn);
+        final String packageName = mActivity.getPackageName();
+
+        mProvider.verifyLaunchSearchResultPageCaller(mActivity, packageName);
     }
 
     @Test
     public void verifyLaunchSearchResultPageCaller_settingsIntelligenceCaller_shouldNotCrash() {
         final String packageName = mProvider.getSettingsIntelligencePkgName(mActivity);
-        final ComponentName cn = new ComponentName(packageName, "class");
-        mProvider.verifyLaunchSearchResultPageCaller(mActivity, cn);
+
+        mProvider.verifyLaunchSearchResultPageCaller(mActivity, packageName);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsInternal.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsInternal.java
index 5989d49..e03134b 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsInternal.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsInternal.java
@@ -15,9 +15,11 @@
  */
 package com.android.settings.testutils.shadow;
 
+import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
+import android.content.Intent;
 
 import com.android.internal.util.ArrayUtils;
 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -38,6 +40,8 @@
     private static DevicePolicyManager sDevicePolicyManager;
     private static String[] sDisabledTypes;
     private static int sKeyguardDisabledFeatures;
+    private static String[] sEcmRestrictedPkgs;
+    private static boolean sAccessibilityServiceRestricted;
 
     @Resetter
     public static void reset() {
@@ -47,6 +51,8 @@
         sDisabledTypes = new String[0];
         sMaximumTimeToLockIsSet = false;
         sMteOverridden = false;
+        sEcmRestrictedPkgs = new String[0];
+        sAccessibilityServiceRestricted = false;
     }
 
     @Implementation
@@ -108,10 +114,35 @@
         return sMteOverridden ? new EnforcedAdmin() : null;
     }
 
+    public static EnforcedAdmin checkIfAccessibilityServiceDisallowed(Context context,
+            String packageName, int userId) {
+        return sAccessibilityServiceRestricted ? new EnforcedAdmin() : null;
+    }
+
+    @Implementation
+    public static Intent checkIfRequiresEnhancedConfirmation(@NonNull Context context,
+            @NonNull String settingIdentifier, @NonNull String packageName) {
+        if (ArrayUtils.contains(sEcmRestrictedPkgs, packageName)) {
+            return new Intent();
+        }
+
+        return null;
+    }
+
+    @Implementation
+    public static boolean isEnhancedConfirmationRestricted(@NonNull Context context,
+            @NonNull String settingIdentifier, @NonNull String packageName) {
+        return false;
+    }
+
     public static void setRestricted(boolean restricted) {
         sIsRestricted = restricted;
     }
 
+    public static void setEcmRestrictedPkgs(String... pkgs) {
+        sEcmRestrictedPkgs = pkgs;
+    }
+
     public static void setRestrictedPkgs(String... pkgs) {
         sRestrictedPkgs = pkgs;
     }
diff --git a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java
index a11b226..f49cc68 100644
--- a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java
@@ -27,6 +27,7 @@
 import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider;
 import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider;
 import com.android.settings.bluetooth.BluetoothFeatureProvider;
+import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider;
 import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider;
 import com.android.settings.connecteddevice.stylus.StylusFeatureProvider;
 import com.android.settings.dashboard.DashboardFeatureProvider;
@@ -103,6 +104,7 @@
     public FastPairFeatureProvider mFastPairFeatureProvider;
     public PrivateSpaceLoginFeatureProvider mPrivateSpaceLoginFeatureProvider;
     public DisplayFeatureProvider mDisplayFeatureProvider;
+    public AudioSharingFeatureProvider mAudioSharingFeatureProvider;
 
     /**
      * Call this in {@code @Before} method of the test class to use fake factory.
@@ -152,6 +154,7 @@
         mFastPairFeatureProvider = mock(FastPairFeatureProvider.class);
         mPrivateSpaceLoginFeatureProvider =  mock(PrivateSpaceLoginFeatureProvider.class);
         mDisplayFeatureProvider = mock(DisplayFeatureProvider.class);
+        mAudioSharingFeatureProvider = mock(AudioSharingFeatureProvider.class);
     }
 
     @Override
@@ -339,5 +342,10 @@
     public DisplayFeatureProvider getDisplayFeatureProvider() {
         return mDisplayFeatureProvider;
     }
+
+    @Override
+    public AudioSharingFeatureProvider getAudioSharingFeatureProvider() {
+        return mAudioSharingFeatureProvider;
+    }
 }
 
diff --git a/tests/spa_unit/src/com/android/settings/network/apn/ApnRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/apn/ApnRepositoryTest.kt
index ec3b754..4155318 100644
--- a/tests/spa_unit/src/com/android/settings/network/apn/ApnRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/apn/ApnRepositoryTest.kt
@@ -58,7 +58,7 @@
     @Test
     fun getApnDataFromUri() {
         // mock out resources and the feature provider
-        val cursor = MatrixCursor(sProjection)
+        val cursor = MatrixCursor(Projection)
         cursor.addRow(
             arrayOf<Any>(
                 0,
@@ -82,7 +82,7 @@
                 1,
             )
         )
-        whenever(contentResolver.query(uri, sProjection, null, null, null)).thenReturn(cursor)
+        whenever(contentResolver.query(uri, Projection, null, null, null)).thenReturn(cursor)
 
         val apnData = getApnDataFromUri(uri, context)
 
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppInfoSettingsMoreOptionsTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppInfoSettingsMoreOptionsTest.kt
index 7103516..9e7ec9b 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppInfoSettingsMoreOptionsTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppInfoSettingsMoreOptionsTest.kt
@@ -19,11 +19,16 @@
 import android.app.AppOpsManager
 import android.app.KeyguardManager
 import android.app.admin.DevicePolicyManager
+import android.app.ecm.EnhancedConfirmationManager
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageManager
 import android.content.pm.UserInfo
 import android.os.UserManager
+import android.platform.test.annotations.RequiresFlagsDisabled
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.CheckFlagsRule
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.test.assertIsNotDisplayed
@@ -61,6 +66,9 @@
     @get:Rule
     val composeTestRule = createComposeRule()
 
+    @get:Rule
+    val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
     private lateinit var mockSession: MockitoSession
 
     @Spy
@@ -82,6 +90,9 @@
     private lateinit var appOpsManager: AppOpsManager
 
     @Mock
+    private lateinit var enhancedConfirmationManager: EnhancedConfirmationManager
+
+    @Mock
     private lateinit var keyguardManager: KeyguardManager
 
     @Spy
@@ -103,6 +114,8 @@
         whenever(context.devicePolicyManager).thenReturn(devicePolicyManager)
         whenever(context.appOpsManager).thenReturn(appOpsManager)
         whenever(context.getSystemService(KeyguardManager::class.java)).thenReturn(keyguardManager)
+        whenever(context.getSystemService(EnhancedConfirmationManager::class.java))
+                .thenReturn(enhancedConfirmationManager)
         whenever(keyguardManager.isKeyguardSecure).thenReturn(false)
         whenever(Utils.isProfileOrDeviceOwner(userManager, devicePolicyManager, PACKAGE_NAME))
             .thenReturn(false)
@@ -158,7 +171,9 @@
     }
 
     @Test
-    fun shouldShowAccessRestrictedSettings() {
+    @RequiresFlagsDisabled(android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
+        android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
+    fun shouldShowAccessRestrictedSettings_appOp() {
         whenever(
             appOpsManager.noteOpNoThrow(
                 AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, UID, PACKAGE_NAME, null, null
@@ -186,6 +201,31 @@
         )
     }
 
+    @Test
+    @RequiresFlagsEnabled(android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
+        android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
+    fun shouldShowAccessRestrictedSettings() {
+        whenever(
+            enhancedConfirmationManager.isClearRestrictionAllowed(PACKAGE_NAME)
+        ).thenReturn(true)
+        val app = ApplicationInfo().apply {
+            packageName = PACKAGE_NAME
+            uid = UID
+        }
+
+        setContent(app)
+        composeTestRule.onRoot().performClick()
+
+        composeTestRule.waitUntilExists(
+            hasText(context.getString(R.string.app_restricted_settings_lockscreen_title))
+        )
+        composeTestRule
+            .onNodeWithText(context
+                .getString(R.string.app_restricted_settings_lockscreen_title))
+            .performClick()
+        verify(enhancedConfirmationManager).clearRestriction(PACKAGE_NAME)
+    }
+
     private fun setContent(app: ApplicationInfo) {
         composeTestRule.setContent {
             CompositionLocalProvider(LocalContext provides context) {
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
index 8e12b20..44a5037 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
@@ -47,7 +47,6 @@
         on { activeSubInfoList }.doReturn(listOf())
         on { slotInfoList }.doReturn(listOf())
         on { uiccCardInfoList }.doReturn(listOf())
-        on { selectedSubInfoList }.doReturn(mutableListOf())
 
         on { targetPrimarySimCalls }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
         on { targetPrimarySimTexts }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt
index 82dba76..d1847c8 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt
@@ -47,7 +47,6 @@
         on { activeSubInfoList }.doReturn(listOf())
         on { slotInfoList }.doReturn(listOf())
         on { uiccCardInfoList }.doReturn(listOf())
-        on { selectedSubInfoList }.doReturn(mutableListOf())
 
         on { targetPrimarySimCalls }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
         on { targetPrimarySimTexts }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPrimarySimTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPrimarySimTest.kt
index 9cb8909..d9c762d 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPrimarySimTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPrimarySimTest.kt
@@ -48,7 +48,6 @@
         on { activeSubInfoList }.doReturn(listOf())
         on { slotInfoList }.doReturn(listOf())
         on { uiccCardInfoList }.doReturn(listOf())
-        on { selectedSubInfoList }.doReturn(mutableListOf())
 
         on { targetPrimarySimCalls }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
         on { targetPrimarySimTexts }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
index 45667ef..e063f69 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
@@ -47,7 +47,6 @@
         on { activeSubInfoList }.doReturn(listOf())
         on { slotInfoList }.doReturn(listOf())
         on { uiccCardInfoList }.doReturn(listOf())
-        on { selectedSubInfoList }.doReturn(mutableListOf())
 
         on { targetPrimarySimCalls }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
         on { targetPrimarySimTexts }.doReturn(PRIMARY_SIM_ASK_EVERY_TIME)
diff --git a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt
index 4048c24..606db8e 100644
--- a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt
+++ b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt
@@ -25,6 +25,7 @@
 import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider
 import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider
 import com.android.settings.bluetooth.BluetoothFeatureProvider
+import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider
 import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider
 import com.android.settings.connecteddevice.stylus.StylusFeatureProvider
 import com.android.settings.dashboard.DashboardFeatureProvider
@@ -149,4 +150,6 @@
         get() = TODO("Not yet implemented")
     override val displayFeatureProvider: DisplayFeatureProvider
         get() = TODO("Not yet implemented")
+    override val audioSharingFeatureProvider: AudioSharingFeatureProvider
+        get() = TODO("Not yet implemented")
 }
diff --git a/tests/uitests/src/com/android/settings/ui/privatespace/PrivateSpaceAuthenticationActivityTest.kt b/tests/uitests/src/com/android/settings/ui/privatespace/PrivateSpaceAuthenticationActivityTest.kt
index 8751471..8eadd9d 100644
--- a/tests/uitests/src/com/android/settings/ui/privatespace/PrivateSpaceAuthenticationActivityTest.kt
+++ b/tests/uitests/src/com/android/settings/ui/privatespace/PrivateSpaceAuthenticationActivityTest.kt
@@ -18,9 +18,11 @@
 
 
 import android.os.Flags
+import android.platform.test.annotations.RequiresFlagsDisabled
 import android.platform.test.annotations.RequiresFlagsEnabled
 import android.platform.test.flag.junit.DeviceFlagsValueProvider
 import android.provider.Settings
+import android.util.Log
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.uiautomator.By
@@ -77,15 +79,18 @@
         Thread.sleep(1000)
         device.assertHasTexts(listOf(SET_LOCK_BUTTON,CANCEL_TEXT))
         device.clickObject(By.text(SET_LOCK_BUTTON))
-        device.assertHasTexts(listOf(LOCK_SCREEN_TITLE))
+        Thread.sleep(1000)
+        device.assertHasTexts(listOf(PATTERN_TEXT, PIN_TEXT, PASSWORD_TEXT))
     }
 
     private companion object {
         // Items we really want to always show
-        val PRIVATE_SPACE_SETTING = "Private Space"
+        val PRIVATE_SPACE_SETTING = "Private space"
         const val SET_LOCK_BUTTON = "Set screen lock"
         val CANCEL_TEXT = "Cancel"
         val DIALOG_TITLE = "Set a screen lock"
-        val LOCK_SCREEN_TITLE = "Choose screen lock"
+        val PATTERN_TEXT = "Pattern"
+        val PIN_TEXT = "PIN"
+        val PASSWORD_TEXT = "Password"
     }
 }
diff --git a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
index fa5af6d..eb23685 100644
--- a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
@@ -36,6 +36,9 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.platform.test.annotations.EnableFlags;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.test.core.app.ApplicationProvider;
@@ -45,6 +48,7 @@
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.RestrictedSwitchPreference;
 
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -58,6 +62,8 @@
     @Rule
     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(
             SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT);
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
 
     private Context mContext;
     private FakeFeatureFactory mFeatureFactory;
@@ -122,6 +128,7 @@
     }
 
     @Test
+    @RequiresFlagsDisabled(android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS)
     public void updateState_checked() {
         when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
                 AppOpsManager.MODE_ALLOWED);
@@ -136,19 +143,26 @@
     }
 
     @Test
+    @RequiresFlagsDisabled(android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS)
     public void restrictedSettings_appOpsDisabled() {
-        when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
-                AppOpsManager.MODE_ERRORED);
+        Assert.assertFalse(android.security.Flags.extendEcmToAllSettings());
+        when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString()))
+                .thenReturn(AppOpsManager.MODE_ERRORED);
+        doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE);
         when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(false);
         RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
                 mContext);
         pref.setAppOps(mAppOpsManager);
+        mController.setSettingIdentifier(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS);
 
         mController.updateState(pref);
+
+        verify(mAppOpsManager).noteOpNoThrow(anyInt(), anyInt(), anyString());
         assertThat(pref.isEnabled()).isFalse();
     }
 
     @Test
+    @RequiresFlagsDisabled(android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS)
     public void restrictedSettings_serviceAlreadyEnabled() {
         when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
                 AppOpsManager.MODE_ERRORED);
diff --git a/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java b/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java
index 9190d0a..1701eaa 100644
--- a/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
+import android.content.Intent;
 import android.hardware.face.Face;
 import android.hardware.face.FaceEnrollCell;
 import android.hardware.face.FaceEnrollStages;
@@ -93,7 +94,7 @@
         ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
                 ArgumentCaptor.forClass(FaceManager.EnrollmentCallback.class);
         mFaceUpdater.enroll(USER_ID, HARDWARE_AUTH_TOKEN, CANCELLATION_SIGNAL, mEnrollmentCallback,
-                DISABLED_FEATURES);
+                DISABLED_FEATURES, new Intent());
         verify(mFaceManager).enroll(
                 eq(USER_ID),
                 same(HARDWARE_AUTH_TOKEN),
@@ -101,7 +102,8 @@
                 callbackCaptor.capture(),
                 same(DISABLED_FEATURES),
                 same(null),
-                eq(false));
+                eq(false),
+                any());
         FaceManager.EnrollmentCallback callback = callbackCaptor.getValue();
 
         callback.onEnrollmentError(ERR_MSG_ID, ERR_STRING);
@@ -121,7 +123,7 @@
         ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
                 ArgumentCaptor.forClass(FaceManager.EnrollmentCallback.class);
         mFaceUpdater.enroll(USER_ID, HARDWARE_AUTH_TOKEN, CANCELLATION_SIGNAL, mEnrollmentCallback,
-                DISABLED_FEATURES);
+                DISABLED_FEATURES, new Intent());
         verify(mFaceManager).enroll(
                 eq(USER_ID),
                 same(HARDWARE_AUTH_TOKEN),
@@ -129,7 +131,8 @@
                 callbackCaptor.capture(),
                 same(DISABLED_FEATURES),
                 same(null),
-                eq(false));
+                eq(false),
+                any());
         FaceManager.EnrollmentCallback callback = callbackCaptor.getValue();
 
         callback.onEnrollmentProgress(/* remaining= */ 0);
@@ -142,7 +145,7 @@
         ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
                 ArgumentCaptor.forClass(FaceManager.EnrollmentCallback.class);
         mFaceUpdater.enroll(USER_ID, HARDWARE_AUTH_TOKEN, CANCELLATION_SIGNAL, mEnrollmentCallback,
-                DISABLED_FEATURES);
+                DISABLED_FEATURES, new Intent());
         verify(mFaceManager).enroll(
                 eq(USER_ID),
                 same(HARDWARE_AUTH_TOKEN),
@@ -150,7 +153,8 @@
                 callbackCaptor.capture(),
                 same(DISABLED_FEATURES),
                 same(null),
-                eq(false));
+                eq(false),
+                any());
         FaceManager.EnrollmentCallback callback = callbackCaptor.getValue();
 
         callback.onEnrollmentProgress(/* remaining= */ 1);
@@ -163,7 +167,7 @@
         ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
                 ArgumentCaptor.forClass(FaceManager.EnrollmentCallback.class);
         mFaceUpdater.enroll(USER_ID, HARDWARE_AUTH_TOKEN, CANCELLATION_SIGNAL, mEnrollmentCallback,
-                DISABLED_FEATURES, PREVIEW_SURFACE, DEBUG_CONSENT);
+                DISABLED_FEATURES, PREVIEW_SURFACE, DEBUG_CONSENT, new Intent());
         verify(mFaceManager).enroll(
                 eq(USER_ID),
                 same(HARDWARE_AUTH_TOKEN),
@@ -171,7 +175,8 @@
                 callbackCaptor.capture(),
                 same(DISABLED_FEATURES),
                 same(PREVIEW_SURFACE),
-                eq(DEBUG_CONSENT));
+                eq(DEBUG_CONSENT),
+                any());
         FaceManager.EnrollmentCallback callback = callbackCaptor.getValue();
 
         callback.onEnrollmentError(ERR_MSG_ID, ERR_STRING);
@@ -191,7 +196,7 @@
         ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
                 ArgumentCaptor.forClass(FaceManager.EnrollmentCallback.class);
         mFaceUpdater.enroll(USER_ID, HARDWARE_AUTH_TOKEN, CANCELLATION_SIGNAL, mEnrollmentCallback,
-                DISABLED_FEATURES, PREVIEW_SURFACE, DEBUG_CONSENT);
+                DISABLED_FEATURES, PREVIEW_SURFACE, DEBUG_CONSENT, new Intent());
         verify(mFaceManager).enroll(
                 eq(USER_ID),
                 same(HARDWARE_AUTH_TOKEN),
@@ -199,7 +204,8 @@
                 callbackCaptor.capture(),
                 same(DISABLED_FEATURES),
                 same(PREVIEW_SURFACE),
-                eq(DEBUG_CONSENT));
+                eq(DEBUG_CONSENT),
+                any());
         FaceManager.EnrollmentCallback callback = callbackCaptor.getValue();
 
         callback.onEnrollmentProgress(/* remaining= */ 0);
@@ -212,7 +218,7 @@
         ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
                 ArgumentCaptor.forClass(FaceManager.EnrollmentCallback.class);
         mFaceUpdater.enroll(USER_ID, HARDWARE_AUTH_TOKEN, CANCELLATION_SIGNAL, mEnrollmentCallback,
-                DISABLED_FEATURES, PREVIEW_SURFACE, DEBUG_CONSENT);
+                DISABLED_FEATURES, PREVIEW_SURFACE, DEBUG_CONSENT, new Intent());
         verify(mFaceManager).enroll(
                 eq(USER_ID),
                 same(HARDWARE_AUTH_TOKEN),
@@ -220,7 +226,8 @@
                 callbackCaptor.capture(),
                 same(DISABLED_FEATURES),
                 same(PREVIEW_SURFACE),
-                eq(DEBUG_CONSENT));
+                eq(DEBUG_CONSENT),
+                any());
         FaceManager.EnrollmentCallback callback = callbackCaptor.getValue();
 
         callback.onEnrollmentProgress(/* remaining= */ 1);
diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintUpdaterTest.java b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintUpdaterTest.java
index 62435b4..6218efb 100644
--- a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintUpdaterTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintUpdaterTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
+import android.content.Intent;
 import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.CancellationSignal;
@@ -78,13 +79,14 @@
         ArgumentCaptor<FingerprintManager.EnrollmentCallback> callbackCaptor =
                 ArgumentCaptor.forClass(FingerprintManager.EnrollmentCallback.class);
         mFingerprintUpdater.enroll(HARDWARE_AUTH_TOKEN, CANCELLATION_SIGNAL, USER_ID,
-                mEnrollmentCallback, ENROLL_REASON);
+                mEnrollmentCallback, ENROLL_REASON, new Intent());
         verify(mFingerprintManager).enroll(
                 same(HARDWARE_AUTH_TOKEN),
                 same(CANCELLATION_SIGNAL),
                 eq(USER_ID),
                 callbackCaptor.capture(),
-                eq(ENROLL_REASON));
+                eq(ENROLL_REASON),
+                any());
         FingerprintManager.EnrollmentCallback callback = callbackCaptor.getValue();
 
         callback.onEnrollmentError(ERR_MSG_ID, ERR_STRING);
@@ -101,13 +103,14 @@
         ArgumentCaptor<FingerprintManager.EnrollmentCallback> callbackCaptor =
                 ArgumentCaptor.forClass(FingerprintManager.EnrollmentCallback.class);
         mFingerprintUpdater.enroll(HARDWARE_AUTH_TOKEN, CANCELLATION_SIGNAL, USER_ID,
-                mEnrollmentCallback, ENROLL_REASON);
+                mEnrollmentCallback, ENROLL_REASON, new Intent());
         verify(mFingerprintManager).enroll(
                 same(HARDWARE_AUTH_TOKEN),
                 same(CANCELLATION_SIGNAL),
                 eq(USER_ID),
                 callbackCaptor.capture(),
-                eq(ENROLL_REASON));
+                eq(ENROLL_REASON),
+                any());
         FingerprintManager.EnrollmentCallback callback = callbackCaptor.getValue();
 
         callback.onEnrollmentProgress(/* remaining= */ 0);
@@ -120,13 +123,14 @@
         ArgumentCaptor<FingerprintManager.EnrollmentCallback> callbackCaptor =
                 ArgumentCaptor.forClass(FingerprintManager.EnrollmentCallback.class);
         mFingerprintUpdater.enroll(HARDWARE_AUTH_TOKEN, CANCELLATION_SIGNAL, USER_ID,
-                mEnrollmentCallback, ENROLL_REASON);
+                mEnrollmentCallback, ENROLL_REASON, new Intent());
         verify(mFingerprintManager).enroll(
                 same(HARDWARE_AUTH_TOKEN),
                 same(CANCELLATION_SIGNAL),
                 eq(USER_ID),
                 callbackCaptor.capture(),
-                eq(ENROLL_REASON));
+                eq(ENROLL_REASON),
+                any());
         FingerprintManager.EnrollmentCallback callback = callbackCaptor.getValue();
 
         callback.onEnrollmentProgress(/* remaining= */ 1);
diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImplTest.kt b/tests/unit/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImplTest.kt
index 794cfec..f7256b9 100644
--- a/tests/unit/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImplTest.kt
+++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImplTest.kt
@@ -44,16 +44,24 @@
 
 @RunWith(AndroidJUnit4::class)
 class SfpsEnrollmentFeatureImplTest {
+    private val STAGE_0 = 0
+    private val STAGE_1 = 1
+    private val STAGE_2 = 2
+    private val STAGE_3 = 3
+    private val STAGE_4 = 4
+
+    private val THRESHOLD_0 = 0f
+    private val THRESHOLD_1 = .36f
+    private val THRESHOLD_2 = .52f
+    private val THRESHOLD_3 = .76f
+    private val THRESHOLD_4 = 1f
+
     @get:Rule
     val mockito: MockitoRule = MockitoJUnit.rule()
 
     @Spy
     private val context: Context = ApplicationProvider.getApplicationContext()
 
-    private val settingsPackageName = "com.android.settings"
-
-    private lateinit var settingsContext: Context
-
     @Mock
     private lateinit var mockFingerprintManager: FingerprintManager
 
@@ -61,31 +69,34 @@
 
     @Before
     fun setUp() {
-        assertThat(mSfpsEnrollmentFeatureImpl).isInstanceOf(SfpsEnrollmentFeatureImpl::class.java)
         whenever(context.getSystemService(FingerprintManager::class.java))
             .thenReturn(mockFingerprintManager)
-        doReturn(0f).`when`(mockFingerprintManager).getEnrollStageThreshold(0)
-        doReturn(0.36f).`when`(mockFingerprintManager).getEnrollStageThreshold(1)
-        doReturn(0.52f).`when`(mockFingerprintManager).getEnrollStageThreshold(2)
-        doReturn(0.76f).`when`(mockFingerprintManager).getEnrollStageThreshold(3)
-        doReturn(1f).`when`(mockFingerprintManager).getEnrollStageThreshold(4)
-        settingsContext = context.createPackageContext(settingsPackageName, 0)
+        doReturn(THRESHOLD_0).`when`(mockFingerprintManager).getEnrollStageThreshold(STAGE_0)
+        doReturn(THRESHOLD_1).`when`(mockFingerprintManager).getEnrollStageThreshold(STAGE_1)
+        doReturn(THRESHOLD_2).`when`(mockFingerprintManager).getEnrollStageThreshold(STAGE_2)
+        doReturn(THRESHOLD_3).`when`(mockFingerprintManager).getEnrollStageThreshold(STAGE_3)
+        doReturn(THRESHOLD_4).`when`(mockFingerprintManager).getEnrollStageThreshold(STAGE_4)
     }
 
     @Test
     fun testGetEnrollStageThreshold() {
-        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 0)).isEqualTo(0f)
-        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 1)).isEqualTo(0.36f)
-        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 2)).isEqualTo(0.52f)
-        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 3)).isEqualTo(0.76f)
-        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 4)).isEqualTo(1f)
+        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, STAGE_0))
+            .isEqualTo(THRESHOLD_0)
+        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, STAGE_1))
+            .isEqualTo(THRESHOLD_1)
+        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, STAGE_2))
+            .isEqualTo(THRESHOLD_2)
+        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, STAGE_3))
+            .isEqualTo(THRESHOLD_3)
+        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, STAGE_4))
+            .isEqualTo(THRESHOLD_4)
     }
 
     @Test
     fun testGetHelpAnimator() {
         val mockView: View = mock(View::class.java)
         val animator: Animator = mSfpsEnrollmentFeatureImpl.getHelpAnimator(mockView)
-        assertThat(animator.duration).isEqualTo(550)
+        assertThat(animator.duration).isEqualTo(SfpsEnrollmentFeatureImpl.HELP_ANIMATOR_DURATION)
     }
 
     @Test
@@ -115,42 +126,27 @@
         assertThat(
             mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_NO_ANIMATION)
         ).isEqualTo(
-            settingsContext.resources.getIdentifier(
-                "security_settings_fingerprint_enroll_repeat_title",
-                type,
-                settingsPackageName)
+            getSettingsResourcesId(type, "security_settings_fingerprint_enroll_repeat_title")
         )
         assertThat(
             mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_CENTER)
         ).isEqualTo(
-            settingsContext.resources.getIdentifier(
-                "security_settings_sfps_enroll_finger_center_title",
-                type,
-                settingsPackageName)
+            getSettingsResourcesId(type, "security_settings_sfps_enroll_finger_center_title")
         )
         assertThat(
             mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_FINGERTIP)
         ).isEqualTo(
-            settingsContext.resources.getIdentifier(
-                "security_settings_sfps_enroll_fingertip_title",
-                type,
-                settingsPackageName)
+            getSettingsResourcesId(type, "security_settings_sfps_enroll_fingertip_title")
         )
         assertThat(
             mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_LEFT_EDGE)
         ).isEqualTo(
-            settingsContext.resources.getIdentifier(
-                "security_settings_sfps_enroll_left_edge_title",
-                type,
-                settingsPackageName)
+            getSettingsResourcesId(type, "security_settings_sfps_enroll_left_edge_title")
         )
         assertThat(
             mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_RIGHT_EDGE)
         ).isEqualTo(
-            settingsContext.resources.getIdentifier(
-                "security_settings_sfps_enroll_right_edge_title",
-                type,
-                settingsPackageName)
+            getSettingsResourcesId(type, "security_settings_sfps_enroll_right_edge_title")
         )
     }
 
@@ -159,43 +155,22 @@
         val type = "raw"
         assertThat(
             mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_NO_ANIMATION)
-        ).isEqualTo(
-            settingsContext.resources.getIdentifier(
-                "sfps_lottie_no_animation",
-                type,
-                settingsPackageName)
-        )
+        ).isEqualTo(getSettingsResourcesId(type, "sfps_lottie_no_animation"))
         assertThat(
             mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_CENTER)
-        ).isEqualTo(
-            settingsContext.resources.getIdentifier(
-                "sfps_lottie_pad_center",
-                type,
-                settingsPackageName)
-        )
+        ).isEqualTo(getSettingsResourcesId(type, "sfps_lottie_pad_center"))
         assertThat(
             mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_FINGERTIP)
-        ).isEqualTo(
-            settingsContext.resources.getIdentifier(
-                "sfps_lottie_tip",
-                type,
-                settingsPackageName)
-        )
+        ).isEqualTo(getSettingsResourcesId(type, "sfps_lottie_tip"))
         assertThat(
             mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_LEFT_EDGE)
-        ).isEqualTo(
-            settingsContext.resources.getIdentifier(
-                "sfps_lottie_left_edge",
-                type,
-                settingsPackageName)
-        )
+        ).isEqualTo(getSettingsResourcesId(type, "sfps_lottie_left_edge"))
         assertThat(
             mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_RIGHT_EDGE)
-        ).isEqualTo(
-            settingsContext.resources.getIdentifier(
-                "sfps_lottie_right_edge",
-                type,
-                settingsPackageName)
-        )
+        ).isEqualTo(getSettingsResourcesId(type, "sfps_lottie_right_edge"))
+    }
+
+    private fun getSettingsResourcesId(type: String, name: String) : Int {
+        return context.resources.getIdentifier(name, type, context.packageName)
     }
 }
\ No newline at end of file
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModelTest.java
index 418db04..2c7afa6 100644
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModelTest.java
+++ b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModelTest.java
@@ -98,7 +98,7 @@
             mCallbackWrapper.mValue = invocation.getArgument(3);
             return null;
         }).when(mFingerprintUpdater).enroll(any(byte[].class), any(CancellationSignal.class),
-                eq(TEST_USER_ID), any(EnrollmentCallback.class), anyInt());
+                eq(TEST_USER_ID), any(EnrollmentCallback.class), anyInt(), any());
     }
 
     @Test
@@ -112,7 +112,7 @@
 
         assertThat(ret).isNotNull();
         verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
-                eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason));
+                eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason), any());
         assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
     }
 
@@ -127,7 +127,7 @@
 
         assertThat(ret).isNotNull();
         verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
-                eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason));
+                eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason), any());
         assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
     }
 
@@ -146,7 +146,7 @@
 
         assertThat(ret).isNotNull();
         verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
-                eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason));
+                eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason), any());
         assertThat(mCallbackWrapper.mValue).isNotNull();
 
         assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isTrue();
@@ -158,7 +158,7 @@
 
         // Shall not use the same MessageDisplayController
         verify(mFingerprintUpdater, times(2)).enroll(eq(token), any(CancellationSignal.class),
-                eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason));
+                eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason), any());
         assertThat(mCallbackWrapper.mValue).isNotNull();
         assertThat(callback1).isNotEqualTo(mCallbackWrapper.mValue);
     }
@@ -170,7 +170,8 @@
 
         assertThat(ret).isNull();
         verify(mFingerprintUpdater, never()).enroll(any(byte[].class),
-                any(CancellationSignal.class), anyInt(), any(EnrollmentCallback.class), anyInt());
+                any(CancellationSignal.class), anyInt(), any(EnrollmentCallback.class), anyInt(),
+                any());
     }
 
     @Test
diff --git a/tests/unit/src/com/android/settings/fingerprint2/domain/interactor/FingerprintManagerInteractorTest.kt b/tests/unit/src/com/android/settings/fingerprint2/domain/interactor/FingerprintManagerInteractorTest.kt
index c284a6f..2b4bff7 100644
--- a/tests/unit/src/com/android/settings/fingerprint2/domain/interactor/FingerprintManagerInteractorTest.kt
+++ b/tests/unit/src/com/android/settings/fingerprint2/domain/interactor/FingerprintManagerInteractorTest.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.content.Intent
 import android.hardware.fingerprint.Fingerprint
+import android.hardware.fingerprint.FingerprintEnrollOptions
 import android.hardware.fingerprint.FingerprintManager
 import android.hardware.fingerprint.FingerprintManager.CryptoObject
 import android.hardware.fingerprint.FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT
@@ -99,6 +100,7 @@
         gateKeeperPasswordProvider,
         pressToAuthInteractor,
         Default,
+        Intent(),
       )
   }
 
@@ -312,7 +314,8 @@
           any(CancellationSignal::class.java),
           anyInt(),
           capture(enrollCallback),
-          eq(FingerprintManager.ENROLL_FIND_SENSOR)
+          eq(FingerprintManager.ENROLL_FIND_SENSOR),
+          any(FingerprintEnrollOptions::class.java),
         )
       enrollCallback.value.onEnrollmentProgress(1)
       runCurrent()
@@ -336,7 +339,8 @@
           any(CancellationSignal::class.java),
           anyInt(),
           capture(enrollCallback),
-          eq(FingerprintManager.ENROLL_FIND_SENSOR)
+          eq(FingerprintManager.ENROLL_FIND_SENSOR),
+          any(FingerprintEnrollOptions::class.java),
         )
       enrollCallback.value.onEnrollmentHelp(-1, "help")
       runCurrent()
@@ -360,7 +364,8 @@
           any(CancellationSignal::class.java),
           anyInt(),
           capture(enrollCallback),
-          eq(FingerprintManager.ENROLL_FIND_SENSOR)
+          eq(FingerprintManager.ENROLL_FIND_SENSOR),
+          any(FingerprintEnrollOptions::class.java),
         )
       enrollCallback.value.onEnrollmentError(-1, "error")
       runCurrent()
diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
index 9e7948c..4f17a3a 100644
--- a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -27,6 +27,7 @@
 import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider;
 import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider;
 import com.android.settings.bluetooth.BluetoothFeatureProvider;
+import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider;
 import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider;
 import com.android.settings.connecteddevice.stylus.StylusFeatureProvider;
 import com.android.settings.dashboard.DashboardFeatureProvider;
@@ -102,6 +103,7 @@
     public FastPairFeatureProvider mFastPairFeatureProvider;
     public PrivateSpaceLoginFeatureProvider mPrivateSpaceLoginFeatureProvider;
     public DisplayFeatureProvider mDisplayFeatureProvider;
+    public AudioSharingFeatureProvider mAudioSharingFeatureProvider;
 
     /** Call this in {@code @Before} method of the test class to use fake factory. */
     public static FakeFeatureFactory setupForTest() {
@@ -153,6 +155,7 @@
         mFastPairFeatureProvider = mock(FastPairFeatureProvider.class);
         mPrivateSpaceLoginFeatureProvider = mock(PrivateSpaceLoginFeatureProvider.class);
         mDisplayFeatureProvider = mock(DisplayFeatureProvider.class);
+        mAudioSharingFeatureProvider = mock(AudioSharingFeatureProvider.class);
     }
 
     @Override
@@ -340,4 +343,9 @@
     public DisplayFeatureProvider getDisplayFeatureProvider() {
         return mDisplayFeatureProvider;
     }
+
+    @Override
+    public AudioSharingFeatureProvider getAudioSharingFeatureProvider() {
+        return mAudioSharingFeatureProvider;
+    }
 }