Merge "Renew the API getCallState" into main
diff --git a/aconfig/settings_flag_declarations.aconfig b/aconfig/settings_flag_declarations.aconfig
index c4c33b0..56c4b32 100644
--- a/aconfig/settings_flag_declarations.aconfig
+++ b/aconfig/settings_flag_declarations.aconfig
@@ -6,3 +6,10 @@
     description: "This flag controls whether to show a Cancel button when factory reset"
     bug: "300634367"
 }
+
+flag {
+    name: "mainline_module_explicit_intent"
+    namespace: "android_settings"
+    description: "Enabling will provide an explicit package name for Intent to update mainline modules"
+    bug: "278987474"
+}
diff --git a/res/drawable/accessibility_text_reading_preview.xml b/res/drawable/accessibility_text_reading_preview.xml
index 040ccdf..1c9e752 100644
--- a/res/drawable/accessibility_text_reading_preview.xml
+++ b/res/drawable/accessibility_text_reading_preview.xml
@@ -20,5 +20,5 @@
     android:shape="rectangle">
 
     <corners android:radius="28dp" />
-    <solid android:color="?androidprv:attr/materialColorSurfaceContainer" />
+    <solid android:color="@color/accessibility_text_reading_background" />
 </shape>
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index 9334d19..a572841 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -69,6 +69,8 @@
     <color name="udfps_enroll_progress_help">#607DA7F1</color>
     <color name="udfps_enroll_progress_help_with_talkback">#FFEE675C</color>
 
+    <!-- Accessibility colors -->
+    <color name="accessibility_text_reading_background">@android:color/black</color>
     <!-- Flash notifications colors -->
     <!-- Screen flash notification color selected stroke in color selection dialog -->
     <color name="screen_flash_color_button_outer_circle_stroke_color">#FFFFFF</color>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index f76f46e..03225a5 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -137,6 +137,8 @@
     <color name="SIM_dark_mode_color_pink">#ffff8bcb</color> <!-- Material Pink 300 -->
     <color name="SIM_dark_mode_color_orange">#fffcad70</color> <!-- Material Orange 300 -->
 
+    <!-- Accessibility colors -->
+    <color name="accessibility_text_reading_background">@android:color/white</color>
     <!-- Accessibility Settings icon background colors -->
     <color name="accessibility_feature_background">#5F6368</color> <!-- Google grey 700 -->
     <color name="accessibility_magnification_background">#F50D60</color>
diff --git a/res/values/config.xml b/res/values/config.xml
old mode 100755
new mode 100644
index 7af29c8..73ee108
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -782,4 +782,7 @@
         <item>@layout/screen_zoom_preview_1</item>
         <item>@layout/accessibility_text_reading_preview_mail_content</item>
     </array>
+
+    <!-- Package responsible for updating Mainline Modules -->
+    <string name="config_mainline_module_update_package" translatable="false">com.android.vending</string>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 52be658..6739a71 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5269,15 +5269,12 @@
     <string name="accessibility_dialog_button_deny">Deny</string>
 
     <!-- String for the allow button in accessibility permission dialog. [CHAR LIMIT=10] -->
-    <string name="accessibility_dialog_button_stop">Stop</string>
+    <string name="accessibility_dialog_button_stop">Turn off</string>
     <!-- String for the deny button in accessibility permission dialog. [CHAR LIMIT=10] -->
-    <string name="accessibility_dialog_button_cancel">Cancel</string>
+    <string name="accessibility_dialog_button_cancel">Keep on</string>
 
     <!-- Title for a warning about disabling an accessibility service. [CHAR LIMIT=NONE] -->
-    <string name="disable_service_title">Stop <xliff:g id="service" example="TalkBack">%1$s</xliff:g>?</string>
-    <!-- Message for a warning about disabling accessibility service. [CHAR LIMIT=NONE] -->
-    <string name="disable_service_message">Tapping <xliff:g id="stop" example="Stop">%1$s</xliff:g> will
-        stop <xliff:g id="service" example="TalkBack">%2$s</xliff:g>.</string>
+    <string name="disable_service_title">Turn off <xliff:g id="service" example="TalkBack">%1$s</xliff:g>?</string>
 
     <!-- Title for the prompt shown as a placeholder if no accessibility services are installed. [CHAR LIMIT=50] -->
     <string name="accessibility_no_services_installed">No services installed</string>
@@ -6540,6 +6537,11 @@
 
     <!-- Dialog subtitle warning for a VPN app that has an insecure type. [CHAR LIMIT=100]  -->
     <string name="vpn_insecure_dialog_subtitle">Not secure. Update to an IKEv2 VPN</string>
+    <!-- Dialog message when user attempted to start a VPN type that is no longer supported. It is
+         very unlikely, but not impossible, that a user has a very old VPN configuration that the
+         newer device no longer supports. This message is displayed when the user tries to start
+         this unsupported VPN. [CHAR LIMIT=NONE]  -->
+    <string name="vpn_start_unsupported">Failed to start unsupported VPN.</string>
 
     <!-- Summary describing the always-on VPN feature. [CHAR LIMIT=NONE] -->
     <string name="vpn_lockdown_summary">Select a VPN profile to always remain connected to. Network traffic will only be allowed when connected to this VPN.</string>
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 2113b5d..eeca139 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -42,7 +42,6 @@
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.UserProperties;
 import android.content.res.Configuration;
@@ -107,8 +106,6 @@
 import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
 import androidx.fragment.app.Fragment;
 import androidx.lifecycle.Lifecycle;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
 
 import com.android.internal.app.UnlaunchableAppActivity;
 import com.android.internal.util.ArrayUtils;
@@ -180,61 +177,6 @@
             "delete_all_app_clones_enabled";
 
     /**
-     * Finds a matching activity for a preference's intent. If a matching
-     * activity is not found, it will remove the preference.
-     *
-     * @param context The context.
-     * @param parentPreferenceGroup The preference group that contains the
-     *            preference whose intent is being resolved.
-     * @param preferenceKey The key of the preference whose intent is being
-     *            resolved.
-     * @param flags 0 or one or more of
-     *            {@link #UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY}
-     *            .
-     * @return Whether an activity was found. If false, the preference was
-     *         removed.
-     */
-    public static boolean updatePreferenceToSpecificActivityOrRemove(Context context,
-            PreferenceGroup parentPreferenceGroup, String preferenceKey, int flags) {
-
-        final Preference preference = parentPreferenceGroup.findPreference(preferenceKey);
-        if (preference == null) {
-            return false;
-        }
-
-        final Intent intent = preference.getIntent();
-        if (intent != null) {
-            // Find the activity that is in the system image
-            final PackageManager pm = context.getPackageManager();
-            final List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
-            final int listSize = list.size();
-            for (int i = 0; i < listSize; i++) {
-                final ResolveInfo resolveInfo = list.get(i);
-                if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
-                        != 0) {
-
-                    // Replace the intent with this specific activity
-                    preference.setIntent(new Intent().setClassName(
-                            resolveInfo.activityInfo.packageName,
-                            resolveInfo.activityInfo.name));
-
-                    if ((flags & UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY) != 0) {
-                        // Set the preference title to the activity's label
-                        preference.setTitle(resolveInfo.loadLabel(pm));
-                    }
-
-                    return true;
-                }
-            }
-        }
-
-        // Did not find a matching activity, so remove the preference
-        parentPreferenceGroup.removePreference(preference);
-
-        return false;
-    }
-
-    /**
      * Returns true if Monkey is running.
      */
     public static boolean isMonkeyRunning() {
diff --git a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
index 9022ebf..fb50ef1 100644
--- a/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
+++ b/src/com/android/settings/accessibility/AccessibilityServiceWarning.java
@@ -139,9 +139,6 @@
 
         return new AlertDialog.Builder(context)
                 .setTitle(context.getString(R.string.disable_service_title, serviceName))
-                .setMessage(context.getString(R.string.disable_service_message,
-                        context.getString(R.string.accessibility_dialog_button_stop),
-                        serviceName))
                 .setCancelable(true)
                 .setPositiveButton(R.string.accessibility_dialog_button_stop, listener)
                 .setNegativeButton(R.string.accessibility_dialog_button_cancel, listener)
diff --git a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
index 5defe98..ccba9e7f 100644
--- a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
@@ -25,6 +25,7 @@
 import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.Settings;
@@ -37,17 +38,22 @@
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.SettingsMainSwitchPreference;
 import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.search.SearchIndexableRaw;
 
 import java.util.ArrayList;
 import java.util.List;
 
-/** Settings page for color inversion. */
+/**
+ * Settings page for color inversion.
+ */
 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
 public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePreferenceFragment {
 
     private static final String TAG = "ToggleColorInversionPreferenceFragment";
     private static final String ENABLED = Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED;
 
+    private static final String KEY_SHORTCUT_PREFERENCE = "color_inversion_shortcut_key";
+
     @Override
     protected void registerKeysToObserverCallback(
             AccessibilitySettingsContentObserver contentObserver) {
@@ -67,9 +73,9 @@
         mHtmlDescription = getText(R.string.accessibility_display_inversion_preference_subtitle);
         mTopIntroTitle = getText(R.string.accessibility_display_inversion_preference_intro_text);
         mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
-                .authority(getPrefContext().getPackageName())
-                .appendPath(String.valueOf(R.raw.a11y_color_inversion_banner))
-                .build();
+            .authority(getPrefContext().getPackageName())
+            .appendPath(String.valueOf(R.raw.a11y_color_inversion_banner))
+            .build();
         final View view = super.onCreateView(inflater, container, savedInstanceState);
         updateFooterPreference();
         return view;
@@ -159,7 +165,7 @@
     @Override
     int getUserShortcutTypes() {
         return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(),
-                mComponentName);
+            mComponentName);
     }
 
     @Override
@@ -170,8 +176,8 @@
     @Override
     CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
         return getText(type == QuickSettingsTooltipType.GUIDE_TO_EDIT
-                ? R.string.accessibility_color_inversion_qs_tooltip_content
-                : R.string.accessibility_color_inversion_auto_added_qs_tooltip_content);
+            ? R.string.accessibility_color_inversion_qs_tooltip_content
+            : R.string.accessibility_color_inversion_auto_added_qs_tooltip_content);
     }
 
     @Override
@@ -184,5 +190,17 @@
     }
 
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-            new BaseSearchIndexProvider(R.xml.accessibility_color_inversion_settings);
+            new BaseSearchIndexProvider(R.xml.accessibility_color_inversion_settings) {
+                @Override
+                public List<SearchIndexableRaw> getRawDataToIndex(Context context,
+                        boolean enabled) {
+                    final List<SearchIndexableRaw> rawData = new ArrayList<>();
+                    SearchIndexableRaw raw = new SearchIndexableRaw(context);
+                    raw.key = KEY_SHORTCUT_PREFERENCE;
+                    raw.title = context.getString(
+                        R.string.accessibility_display_inversion_shortcut_title);
+                    rawData.add(raw);
+                    return rawData;
+                }
+            };
 }
diff --git a/src/com/android/settings/accounts/ManagedProfileQuietModeEnabler.java b/src/com/android/settings/accounts/ManagedProfileQuietModeEnabler.java
index 989be09..df30637 100644
--- a/src/com/android/settings/accounts/ManagedProfileQuietModeEnabler.java
+++ b/src/com/android/settings/accounts/ManagedProfileQuietModeEnabler.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.accounts;
 
+import android.app.admin.flags.Flags;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -58,7 +59,14 @@
     }
 
     public void setQuietModeEnabled(boolean enabled) {
-        if (mManagedProfile != null) {
+        if (mManagedProfile == null) {
+            return;
+        }
+        if (Flags.quietModeCredentialBugFix()) {
+            if (isQuietModeEnabled() != enabled) {
+                mUserManager.requestQuietModeEnabled(enabled, mManagedProfile);
+            }
+        } else {
             mUserManager.requestQuietModeEnabled(enabled, mManagedProfile);
         }
     }
diff --git a/src/com/android/settings/accounts/WorkModePreferenceController.java b/src/com/android/settings/accounts/WorkModePreferenceController.java
index ae910f7..2aea27d 100644
--- a/src/com/android/settings/accounts/WorkModePreferenceController.java
+++ b/src/com/android/settings/accounts/WorkModePreferenceController.java
@@ -70,6 +70,9 @@
     @Override
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
         mQuietModeEnabler.setQuietModeEnabled(!isChecked);
+        if (android.app.admin.flags.Flags.quietModeCredentialBugFix()) {
+            updateState(mPreference);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java b/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java
index 67d56e0..74a9673 100644
--- a/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java
+++ b/src/com/android/settings/activityembedding/ActivityEmbeddingUtils.java
@@ -53,7 +53,7 @@
      * @see androidx.window.embedding.SplitController.SplitSupportStatus#SPLIT_UNAVAILABLE
      */
     private static final boolean SHOULD_ENABLE_LARGE_SCREEN_OPTIMIZATION =
-            SystemProperties.getBoolean("persist.settings.large_screen_opt.enabled", true);
+            SystemProperties.getBoolean("persist.settings.large_screen_opt.enabled", false);
 
     private static final String TAG = "ActivityEmbeddingUtils";
 
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index a3dace6..3b162b6 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -353,15 +353,23 @@
         }
 
         LocalBluetoothProfile asha = mProfileManager.getHearingAidProfile();
+        LocalBluetoothProfile broadcastAssistant =
+                mProfileManager.getLeAudioBroadcastAssistantProfile();
 
         for (CachedBluetoothDevice leAudioDevice : mProfileDeviceMap.get(profile.toString())) {
             Log.d(TAG,
                     "device:" + leAudioDevice.getDevice().getAnonymizedAddress()
-                            + "disable LE profile");
+                            + " disable LE profile");
             profile.setEnabled(leAudioDevice.getDevice(), false);
             if (asha != null) {
                 asha.setEnabled(leAudioDevice.getDevice(), true);
             }
+            if (broadcastAssistant != null) {
+                Log.d(TAG,
+                        "device:" + leAudioDevice.getDevice().getAnonymizedAddress()
+                                + " disable LE broadcast assistant profile");
+                broadcastAssistant.setEnabled(leAudioDevice.getDevice(), false);
+            }
         }
 
         if (!SystemProperties.getBoolean(ENABLE_DUAL_MODE_AUDIO, false)) {
@@ -388,15 +396,23 @@
             disableProfileBeforeUserEnablesLeAudio(mProfileManager.getHeadsetProfile());
         }
         LocalBluetoothProfile asha = mProfileManager.getHearingAidProfile();
+        LocalBluetoothProfile broadcastAssistant =
+                mProfileManager.getLeAudioBroadcastAssistantProfile();
 
         for (CachedBluetoothDevice leAudioDevice : mProfileDeviceMap.get(profile.toString())) {
             Log.d(TAG,
                     "device:" + leAudioDevice.getDevice().getAnonymizedAddress()
-                            + "enable LE profile");
+                            + " enable LE profile");
             profile.setEnabled(leAudioDevice.getDevice(), true);
             if (asha != null) {
                 asha.setEnabled(leAudioDevice.getDevice(), false);
             }
+            if (broadcastAssistant != null) {
+                Log.d(TAG,
+                        "device:" + leAudioDevice.getDevice().getAnonymizedAddress()
+                                + " enable LE broadcast assistant profile");
+                broadcastAssistant.setEnabled(leAudioDevice.getDevice(), true);
+            }
         }
     }
 
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
index 0d2b53a..1855667 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDevicePreferenceController.java
@@ -49,6 +49,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
@@ -174,6 +175,13 @@
                                     + source
                                     + ", reason = "
                                     + reason);
+                    AudioSharingUtils.toastMessage(
+                            mContext,
+                            String.format(
+                                    Locale.US,
+                                    "Fail to add source to %s reason %d",
+                                    sink.getAddress(),
+                                    reason));
                 }
 
                 @Override
@@ -209,6 +217,13 @@
                                     + sourceId
                                     + ", reason = "
                                     + reason);
+                    AudioSharingUtils.toastMessage(
+                            mContext,
+                            String.format(
+                                    Locale.US,
+                                    "Fail to remove source from %s reason %d",
+                                    sink.getAddress(),
+                                    reason));
                 }
 
                 @Override
@@ -284,7 +299,7 @@
         mPreferenceGroup.setVisible(false);
         mAudioSharingSettingsPreference.setVisible(false);
 
-        if (isAvailable()) {
+        if (isAvailable() && mBluetoothDeviceUpdater != null) {
             mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
             mBluetoothDeviceUpdater.forceUpdate();
         }
@@ -379,8 +394,8 @@
                 // Show audio sharing switch or join dialog according to device count in the sharing
                 // session.
                 ArrayList<AudioSharingDeviceItem> deviceItemsInSharingSession =
-                        AudioSharingUtils.buildOrderedDeviceItemsInSharingSession(
-                                groupedDevices, mLocalBtManager);
+                        AudioSharingUtils.buildOrderedConnectedLeadAudioSharingDeviceItem(
+                                mLocalBtManager, groupedDevices, /* filterByInSharing= */ true);
                 // Show audio sharing switch dialog when the third eligible (LE audio) remote device
                 // connected during a sharing session.
                 if (deviceItemsInSharingSession.size() >= 2) {
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java
index a0d44ff..53e095b 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingUtils.java
@@ -19,18 +19,22 @@
 import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothLeBroadcastReceiveState;
+import android.content.Context;
 import android.util.Log;
+import android.widget.Toast;
 
 import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
 import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 public class AudioSharingUtils {
     private static final String TAG = "AudioSharingUtils";
@@ -73,48 +77,102 @@
     }
 
     /**
-     * Fetch a list of {@link AudioSharingDeviceItem}s in the audio sharing session.
+     * Fetch a list of ordered connected lead {@link CachedBluetoothDevice}s eligible for audio
+     * sharing. The active device is placed in the first place if it exists. The devices can be
+     * filtered by whether it is already in the audio sharing session.
      *
+     * @param localBtManager The BT manager to provide BT functions. *
      * @param groupedConnectedDevices devices connected to broadcast assistant grouped by CSIP group
      *     id.
-     * @param localBtManager The BT manager to provide BT functions.
-     * @return A list of connected devices in the audio sharing session.
+     * @param filterByInSharing Whether to filter the device by if is already in the sharing
+     *     session.
+     * @return A list of ordered connected devices eligible for the audio sharing. The active device
+     *     is placed in the first place if it exists.
      */
-    public static ArrayList<AudioSharingDeviceItem> buildOrderedDeviceItemsInSharingSession(
+    public static ArrayList<CachedBluetoothDevice> buildOrderedConnectedLeadDevices(
+            LocalBluetoothManager localBtManager,
             Map<Integer, List<CachedBluetoothDevice>> groupedConnectedDevices,
-            LocalBluetoothManager localBtManager) {
-        ArrayList<AudioSharingDeviceItem> deviceItems = new ArrayList<>();
+            boolean filterByInSharing) {
+        ArrayList<CachedBluetoothDevice> orderedDevices = new ArrayList<>();
         LocalBluetoothLeBroadcastAssistant assistant =
                 localBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
-        if (assistant == null) return deviceItems;
-        CachedBluetoothDevice activeDevice = null;
-        List<CachedBluetoothDevice> inactiveDevices = new ArrayList<>();
+        if (assistant == null) return orderedDevices;
         for (List<CachedBluetoothDevice> devices : groupedConnectedDevices.values()) {
+            CachedBluetoothDevice leadDevice = null;
             for (CachedBluetoothDevice device : devices) {
-                List<BluetoothLeBroadcastReceiveState> sourceList =
-                        assistant.getAllSources(device.getDevice());
-                if (!sourceList.isEmpty()) {
-                    // Use random device in the group within the sharing session to
-                    // represent the group.
-                    if (BluetoothUtils.isActiveLeAudioDevice(device)) {
-                        activeDevice = device;
-                    } else {
-                        inactiveDevices.add(device);
-                    }
+                if (!device.getMemberDevice().isEmpty()) {
+                    leadDevice = device;
                     break;
                 }
             }
+            if (leadDevice == null && !devices.isEmpty()) {
+                leadDevice = devices.get(0);
+                Log.d(
+                        TAG,
+                        "Empty member device, pick arbitrary device as the lead: "
+                                + leadDevice.getDevice().getAnonymizedAddress());
+            }
+            if (leadDevice == null) {
+                Log.d(TAG, "Skip due to no lead device");
+                continue;
+            }
+            if (filterByInSharing && !hasBroadcastSource(leadDevice, localBtManager)) {
+                Log.d(
+                        TAG,
+                        "Filtered the device due to not in sharing session: "
+                                + leadDevice.getDevice().getAnonymizedAddress());
+                continue;
+            }
+            orderedDevices.add(leadDevice);
         }
-        if (activeDevice != null) {
-            deviceItems.add(buildAudioSharingDeviceItem(activeDevice));
-        }
-        inactiveDevices.stream()
-                .sorted(CachedBluetoothDevice::compareTo)
-                .forEach(
-                        device -> {
-                            deviceItems.add(buildAudioSharingDeviceItem(device));
-                        });
-        return deviceItems;
+        orderedDevices.sort(
+                (CachedBluetoothDevice d1, CachedBluetoothDevice d2) -> {
+                    // Active above not inactive
+                    int comparison =
+                            (isActiveLeAudioDevice(d2) ? 1 : 0)
+                                    - (isActiveLeAudioDevice(d1) ? 1 : 0);
+                    if (comparison != 0) return comparison;
+                    // Bonded above not bonded
+                    comparison =
+                            (d2.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0)
+                                    - (d1.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0);
+                    if (comparison != 0) return comparison;
+                    // Bond timestamp available above unavailable
+                    comparison =
+                            (d2.getBondTimestamp() != null ? 1 : 0)
+                                    - (d1.getBondTimestamp() != null ? 1 : 0);
+                    if (comparison != 0) return comparison;
+                    // Order by bond timestamp if it is available
+                    // Otherwise order by device name
+                    return d1.getBondTimestamp() != null
+                            ? d1.getBondTimestamp().compareTo(d2.getBondTimestamp())
+                            : d1.getName().compareTo(d2.getName());
+                });
+        return orderedDevices;
+    }
+
+    /**
+     * Fetch a list of ordered connected lead {@link AudioSharingDeviceItem}s eligible for audio
+     * sharing. The active device is placed in the first place if it exists. The devices can be
+     * filtered by whether it is already in the audio sharing session.
+     *
+     * @param localBtManager The BT manager to provide BT functions. *
+     * @param groupedConnectedDevices devices connected to broadcast assistant grouped by CSIP group
+     *     id.
+     * @param filterByInSharing Whether to filter the device by if is already in the sharing
+     *     session.
+     * @return A list of ordered connected devices eligible for the audio sharing. The active device
+     *     is placed in the first place if it exists.
+     */
+    public static ArrayList<AudioSharingDeviceItem> buildOrderedConnectedLeadAudioSharingDeviceItem(
+            LocalBluetoothManager localBtManager,
+            Map<Integer, List<CachedBluetoothDevice>> groupedConnectedDevices,
+            boolean filterByInSharing) {
+        return buildOrderedConnectedLeadDevices(
+                        localBtManager, groupedConnectedDevices, filterByInSharing)
+                .stream()
+                .map(device -> buildAudioSharingDeviceItem(device))
+                .collect(Collectors.toCollection(ArrayList::new));
     }
 
     /** Build {@link AudioSharingDeviceItem} from {@link CachedBluetoothDevice}. */
@@ -123,6 +181,57 @@
         return new AudioSharingDeviceItem(
                 cachedDevice.getName(),
                 cachedDevice.getGroupId(),
-                BluetoothUtils.isActiveLeAudioDevice(cachedDevice));
+                isActiveLeAudioDevice(cachedDevice));
+    }
+
+    /**
+     * Check if {@link CachedBluetoothDevice} is in an audio sharing session.
+     *
+     * @param cachedDevice The cached bluetooth device to check.
+     * @param localBtManager The BT manager to provide BT functions.
+     * @return Whether the device is in an audio sharing session.
+     */
+    public static boolean hasBroadcastSource(
+            CachedBluetoothDevice cachedDevice, LocalBluetoothManager localBtManager) {
+        LocalBluetoothLeBroadcastAssistant assistant =
+                localBtManager.getProfileManager().getLeAudioBroadcastAssistantProfile();
+        if (assistant == null) {
+            return false;
+        }
+        List<BluetoothLeBroadcastReceiveState> sourceList =
+                assistant.getAllSources(cachedDevice.getDevice());
+        if (!sourceList.isEmpty()) return true;
+        // Return true if member device is in broadcast.
+        for (CachedBluetoothDevice device : cachedDevice.getMemberDevice()) {
+            List<BluetoothLeBroadcastReceiveState> list =
+                    assistant.getAllSources(device.getDevice());
+            if (!list.isEmpty()) return true;
+        }
+        return false;
+    }
+
+    /**
+     * Check if {@link CachedBluetoothDevice} is an active le audio device.
+     *
+     * @param cachedDevice The cached bluetooth device to check.
+     * @return Whether the device is an active le audio device.
+     */
+    public static boolean isActiveLeAudioDevice(CachedBluetoothDevice cachedDevice) {
+        if (BluetoothUtils.isActiveLeAudioDevice(cachedDevice)) {
+            return true;
+        }
+        // Return true if member device is an active le audio device.
+        for (CachedBluetoothDevice device : cachedDevice.getMemberDevice()) {
+            if (BluetoothUtils.isActiveLeAudioDevice(device)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** Toast message on main thread. */
+    public static void toastMessage(Context context, String message) {
+        ThreadUtils.postOnMainThread(
+                () -> Toast.makeText(context, message, Toast.LENGTH_LONG).show());
     }
 }
diff --git a/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceController.java
index a7d18e7..a6adf8a 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceController.java
@@ -62,14 +62,6 @@
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        updateDeviceItemsInSharingSession();
-        // mDeviceItemsInSharingSession is ordered. The active device is the first place if exits.
-        if (!mDeviceItemsInSharingSession.isEmpty()
-                && mDeviceItemsInSharingSession.get(0).isActive()) {
-            mPreference.setSummary(mDeviceItemsInSharingSession.get(0).getName());
-        } else {
-            mPreference.setSummary("");
-        }
         mPreference.setOnPreferenceClickListener(
                 preference -> {
                     if (mFragment == null) {
@@ -107,6 +99,22 @@
     }
 
     @Override
+    public void updateVisibility(boolean isVisible) {
+        super.updateVisibility(isVisible);
+        if (isVisible && mPreference != null) {
+            updateDeviceItemsInSharingSession();
+            // mDeviceItemsInSharingSession is ordered. The active device is the first place if
+            // exits.
+            if (!mDeviceItemsInSharingSession.isEmpty()
+                    && mDeviceItemsInSharingSession.get(0).isActive()) {
+                mPreference.setSummary(mDeviceItemsInSharingSession.get(0).getName());
+            } else {
+                mPreference.setSummary("");
+            }
+        }
+    }
+
+    @Override
     public void onActiveDeviceChanged(
             @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {
         if (bluetoothProfile != BluetoothProfile.LE_AUDIO) {
@@ -129,7 +137,7 @@
         mGroupedConnectedDevices =
                 AudioSharingUtils.fetchConnectedDevicesByGroupId(mLocalBtManager);
         mDeviceItemsInSharingSession =
-                AudioSharingUtils.buildOrderedDeviceItemsInSharingSession(
-                        mGroupedConnectedDevices, mLocalBtManager);
+                AudioSharingUtils.buildOrderedConnectedLeadAudioSharingDeviceItem(
+                        mLocalBtManager, mGroupedConnectedDevices, /* filterByInSharing= */ true);
     }
 }
diff --git a/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java b/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java
index ec19e8d..d8e8887 100644
--- a/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java
+++ b/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java
@@ -108,10 +108,15 @@
             return null;
         }
 
-        boolean doesStylusSupportTailButton = mInputDevice.hasKeys(
-                KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL)[0];
-        if (!doesStylusSupportTailButton) {
-            return null;
+        // Check if the connected stylus supports the tail button. A connected device is when input
+        // device is available (mInputDevice != null). For a cached device (mInputDevice == null)
+        // there isn't way to check if the device supports the button so assume it does.
+        if (mInputDevice != null) {
+            boolean doesStylusSupportTailButton =
+                    mInputDevice.hasKeys(KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL)[0];
+            if (!doesStylusSupportTailButton) {
+                return null;
+            }
         }
 
         Preference pref = preference == null ? new Preference(mContext) : preference;
diff --git a/src/com/android/settings/dashboard/profileselector/UserAdapter.java b/src/com/android/settings/dashboard/profileselector/UserAdapter.java
index 66ba815..fa07ebc 100644
--- a/src/com/android/settings/dashboard/profileselector/UserAdapter.java
+++ b/src/com/android/settings/dashboard/profileselector/UserAdapter.java
@@ -59,7 +59,7 @@
             mUserManager = um;
             UserInfo userInfo = um.getUserInfo(mUserHandle.getIdentifier());
             int tintColor = Utils.getColorAttrDefaultColor(context,
-                    com.android.internal.R.attr.materialColorPrimaryContainer);
+                    com.android.internal.R.attr.materialColorPrimary);
             if (userInfo.isManagedProfile()) {
                 mIcon = context.getPackageManager().getUserBadgeForDensityNoBackground(
                         userHandle, /* density= */ 0);
diff --git a/src/com/android/settings/development/quarantine/QuarantinedAppsScreenController.java b/src/com/android/settings/development/quarantine/QuarantinedAppsScreenController.java
index c3cb38d..4d4834b 100644
--- a/src/com/android/settings/development/quarantine/QuarantinedAppsScreenController.java
+++ b/src/com/android/settings/development/quarantine/QuarantinedAppsScreenController.java
@@ -18,6 +18,7 @@
 
 import android.app.Application;
 import android.content.Context;
+import android.content.pm.Flags;
 import android.content.pm.PackageManager;
 import android.content.pm.SuspendDialogInfo;
 import android.os.UserHandle;
@@ -198,7 +199,7 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return AVAILABLE;
+        return Flags.quarantinedEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
     }
 
     @Override
diff --git a/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java
index fb17eca..39b8290 100644
--- a/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java
@@ -28,6 +28,7 @@
 import androidx.preference.Preference;
 
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.flags.Flags;
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
@@ -43,14 +44,15 @@
     private static final String TAG = "MainlineModuleControl";
     private static final List<String> VERSION_NAME_DATE_PATTERNS = Arrays.asList("yyyy-MM-dd",
             "yyyy-MM");
-
     @VisibleForTesting
-    static final Intent MODULE_UPDATE_INTENT =
-            new Intent("android.settings.MODULE_UPDATE_SETTINGS");
+    static final String MODULE_UPDATE_INTENT_ACTION =
+        "android.settings.MODULE_UPDATE_SETTINGS";
     @VisibleForTesting
-    static final Intent MODULE_UPDATE_V2_INTENT =
-            new Intent("android.settings.MODULE_UPDATE_VERSIONS");
+    static final String MODULE_UPDATE_V2_INTENT_ACTION =
+        "android.settings.MODULE_UPDATE_VERSIONS";
 
+    private final Intent mModuleUpdateIntent;
+    private final Intent mModuleUpdateV2Intent;
     private final PackageManager mPackageManager;
 
     private String mModuleVersion;
@@ -58,6 +60,14 @@
     public MainlineModuleVersionPreferenceController(Context context, String key) {
         super(context, key);
         mPackageManager = mContext.getPackageManager();
+        mModuleUpdateIntent = new Intent(MODULE_UPDATE_INTENT_ACTION);
+        mModuleUpdateV2Intent = new Intent(MODULE_UPDATE_V2_INTENT_ACTION);
+        if (Flags.mainlineModuleExplicitIntent()) {
+          String packageName = mContext
+              .getString(com.android.settings.R.string.config_mainline_module_update_package);
+          mModuleUpdateIntent.setPackage(packageName);
+          mModuleUpdateV2Intent.setPackage(packageName);
+        }
         initModules();
     }
 
@@ -86,17 +96,17 @@
         super.updateState(preference);
 
         final ResolveInfo resolvedV2 =
-                mPackageManager.resolveActivity(MODULE_UPDATE_V2_INTENT, 0 /* flags */);
+                mPackageManager.resolveActivity(mModuleUpdateV2Intent, 0 /* flags */);
         if (resolvedV2 != null) {
-            preference.setIntent(MODULE_UPDATE_V2_INTENT);
+            preference.setIntent(mModuleUpdateV2Intent);
             preference.setSelectable(true);
             return;
         }
 
         final ResolveInfo resolved =
-                mPackageManager.resolveActivity(MODULE_UPDATE_INTENT, 0 /* flags */);
+                mPackageManager.resolveActivity(mModuleUpdateIntent, 0 /* flags */);
         if (resolved != null) {
-            preference.setIntent(MODULE_UPDATE_INTENT);
+            preference.setIntent(mModuleUpdateIntent);
             preference.setSelectable(true);
         } else {
             Log.d(TAG, "The ResolveInfo of the update intent is null.");
diff --git a/src/com/android/settings/inputmethod/SpellCheckerPreference.java b/src/com/android/settings/inputmethod/SpellCheckerPreference.java
index 116f1c7..8c8942a 100644
--- a/src/com/android/settings/inputmethod/SpellCheckerPreference.java
+++ b/src/com/android/settings/inputmethod/SpellCheckerPreference.java
@@ -47,6 +47,9 @@
         super(context, null);
         mScis = scis;
         setWidgetLayoutResource(R.layout.preference_widget_gear);
+        if (scis == null) {
+            return;
+        }
         CharSequence[] labels = new CharSequence[scis.length];
         CharSequence[] values = new CharSequence[scis.length];
         for (int i = 0 ; i < scis.length; i++) {
diff --git a/src/com/android/settings/inputmethod/SpellCheckersSettings.java b/src/com/android/settings/inputmethod/SpellCheckersSettings.java
index bcb527b..b4d7570 100644
--- a/src/com/android/settings/inputmethod/SpellCheckersSettings.java
+++ b/src/com/android/settings/inputmethod/SpellCheckersSettings.java
@@ -133,6 +133,7 @@
             if (preference instanceof SpellCheckerPreference) {
                 final SpellCheckerPreference pref = (SpellCheckerPreference) preference;
                 pref.setSelected(mCurrentSci);
+                pref.setEnabled(mEnabledScis != null);
             }
         }
         mSpellCheckerLanaguagePref.setEnabled(isSpellCheckerEnabled && mCurrentSci != null);
diff --git a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
index 2fcb06a..1b3a4f2 100644
--- a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
+++ b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
@@ -232,8 +232,7 @@
 
         if (fromPosition != toPosition) {
             FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
-                    .action(mContext, SettingsEnums.ACTION_REORDER_LANGUAGE,
-                            mDragLocale.getLocale().toLanguageTag() + " move to " + toPosition);
+                    .action(mContext, SettingsEnums.ACTION_REORDER_LANGUAGE);
         }
 
         notifyItemChanged(fromPosition); // to update the numbers
@@ -275,8 +274,7 @@
             localeInfo = mFeedItemList.get(i);
             if (localeInfo.getChecked()) {
                 FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
-                        .action(mContext, SettingsEnums.ACTION_REMOVE_LANGUAGE,
-                                localeInfo.getLocale().toLanguageTag());
+                        .action(mContext, SettingsEnums.ACTION_REMOVE_LANGUAGE);
                 mFeedItemList.remove(i);
             }
         }
diff --git a/src/com/android/settings/localepicker/LocaleListEditor.java b/src/com/android/settings/localepicker/LocaleListEditor.java
index 59a39c8..1c22fd9 100644
--- a/src/com/android/settings/localepicker/LocaleListEditor.java
+++ b/src/com/android/settings/localepicker/LocaleListEditor.java
@@ -224,8 +224,7 @@
             localeInfo = mayAppendUnicodeTags(localeInfo, preferencesTags);
             mAdapter.addLocale(localeInfo);
             updateVisibilityOfRemoveMenu();
-            mMetricsFeatureProvider.action(getContext(), SettingsEnums.ACTION_ADD_LANGUAGE,
-                    localeInfo.getLocale().toLanguageTag());
+            mMetricsFeatureProvider.action(getContext(), SettingsEnums.ACTION_ADD_LANGUAGE);
         } else if (requestCode == DIALOG_CONFIRM_SYSTEM_DEFAULT) {
             localeInfo = mAdapter.getFeedItemList().get(0);
             if (resultCode == Activity.RESULT_OK) {
@@ -239,8 +238,7 @@
                     localeDialogFragment.setArguments(args);
                     localeDialogFragment.show(mFragmentManager, TAG_DIALOG_NOT_AVAILABLE);
                     mMetricsFeatureProvider.action(getContext(),
-                            SettingsEnums.ACTION_NOT_SUPPORTED_SYSTEM_LANGUAGE,
-                            localeInfo.getLocale().toLanguageTag());
+                            SettingsEnums.ACTION_NOT_SUPPORTED_SYSTEM_LANGUAGE);
                 }
             } else {
                 mAdapter.notifyListChanged(localeInfo);
diff --git a/src/com/android/settings/network/apn/ApnEditPageProvider.kt b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
index 0ed54e7..86d7456 100644
--- a/src/com/android/settings/network/apn/ApnEditPageProvider.kt
+++ b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
@@ -38,10 +38,13 @@
 import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeDisplayNames
 import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeSelectedOptionsState
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.LocalNavController
 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.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
 import com.android.settingslib.spa.widget.preference.SwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import com.android.settingslib.spa.widget.scaffold.RegularScaffold
@@ -199,6 +202,18 @@
                 emptyVal = stringResource(R.string.network_type_unspecified),
                 enabled = apnData.networkTypeEnabled
             ) {}
+            if (!apnData.newApn) {
+                val navController = LocalNavController.current
+                Preference(
+                    object : PreferenceModel {
+                        override val title = stringResource(R.string.menu_delete)
+                        override val onClick = {
+                            deleteApn(uriInit, context)
+                            navController.navigateBack()
+                        }
+                    }
+                )
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/network/apn/ApnStatus.kt b/src/com/android/settings/network/apn/ApnStatus.kt
index 3ccd71e..a479868 100644
--- a/src/com/android/settings/network/apn/ApnStatus.kt
+++ b/src/com/android/settings/network/apn/ApnStatus.kt
@@ -93,6 +93,12 @@
         values.put(Telephony.Carriers.NETWORK_TYPE_BITMASK, networkType)
         values.put(Telephony.Carriers.CARRIER_ENABLED, apnEnable)
         values.put(Telephony.Carriers.EDITED_STATUS, Telephony.Carriers.USER_EDITED)
+        if (newApn) {
+            val simCarrierId =
+                context.getSystemService(TelephonyManager::class.java)!!.createForSubscriptionId(subId)
+                    .getSimCarrierId()
+            values.put(Telephony.Carriers.CARRIER_ID, simCarrierId)
+        }
         return values
     }
 }
@@ -513,4 +519,9 @@
             APN_TYPE_IMS,
         )
     }.joinToString()
+}
+
+fun deleteApn(uri: Uri, context: Context) {
+    val contentResolver = context.contentResolver
+    contentResolver.delete(uri, null, null)
 }
\ No newline at end of file
diff --git a/src/com/android/settings/regionalpreferences/NumberingSystemItemController.java b/src/com/android/settings/regionalpreferences/NumberingSystemItemController.java
index a608fbf..de0d386 100644
--- a/src/com/android/settings/regionalpreferences/NumberingSystemItemController.java
+++ b/src/com/android/settings/regionalpreferences/NumberingSystemItemController.java
@@ -153,7 +153,7 @@
     private void handleLanguageSelect(Preference preference) {
         String selectedLanguage = preference.getKey();
         mMetricsFeatureProvider.action(mContext,
-                SettingsEnums.ACTION_CHOOSE_LANGUAGE_FOR_NUMBERS_PREFERENCES, selectedLanguage);
+                SettingsEnums.ACTION_CHOOSE_LANGUAGE_FOR_NUMBERS_PREFERENCES);
         final Bundle extra = new Bundle();
         extra.putString(RegionalPreferencesEntriesFragment.ARG_KEY_REGIONAL_PREFERENCE,
                 ARG_VALUE_NUMBERING_SYSTEM_SELECT);
@@ -177,8 +177,7 @@
                         saveNumberingSystemToLocale(Locale.forLanguageTag(mSelectedLanguage),
                                 numberingSystem);
                 mMetricsFeatureProvider.action(mContext,
-                        SettingsEnums.ACTION_SET_NUMBERS_PREFERENCES,
-                        updatedLocale.getDisplayName() + ": " + numberingSystem);
+                        SettingsEnums.ACTION_SET_NUMBERS_PREFERENCES);
                 // After updated locale to framework, this fragment will recreate,
                 // so it needs to update the argument of selected language.
                 Bundle bundle = new Bundle();
diff --git a/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java b/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java
index ac0e7ee..8be0043 100644
--- a/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java
+++ b/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.regionalpreferences;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 
 import androidx.preference.PreferenceCategory;
@@ -65,8 +66,10 @@
                 RegionalPreferencesDataUtils.savePreference(mContext, getExtensionTypes(),
                         item.equals(RegionalPreferencesDataUtils.DEFAULT_VALUE)
                                 ? null : item);
-                mMetricsFeatureProvider.action(mContext, getMetricsActionKey(),
-                        getPreferenceTitle(value) + " > " +  getPreferenceTitle(item));
+                String metrics =
+                        getMetricsActionKey() == SettingsEnums.ACTION_SET_FIRST_DAY_OF_WEEK ? ""
+                                : getPreferenceTitle(value) + " > " + getPreferenceTitle(item);
+                mMetricsFeatureProvider.action(mContext, getMetricsActionKey(), metrics);
                 return true;
             });
             pref.setSelected(!value.isEmpty() && item.equals(value));
diff --git a/src/com/android/settings/system/SystemUpdatePreferenceController.kt b/src/com/android/settings/system/SystemUpdatePreferenceController.kt
index fa135aa..87a402e 100644
--- a/src/com/android/settings/system/SystemUpdatePreferenceController.kt
+++ b/src/com/android/settings/system/SystemUpdatePreferenceController.kt
@@ -28,7 +28,6 @@
 import androidx.preference.Preference
 import androidx.preference.PreferenceScreen
 import com.android.settings.R
-import com.android.settings.Utils
 import com.android.settings.core.BasePreferenceController
 import com.android.settingslib.spaprivileged.framework.common.userManager
 import kotlinx.coroutines.launch
@@ -36,6 +35,7 @@
 open class SystemUpdatePreferenceController(context: Context, preferenceKey: String) :
     BasePreferenceController(context, preferenceKey) {
     private val userManager: UserManager = context.userManager
+    private val systemUpdateRepository = SystemUpdateRepository(context)
     private val clientInitiatedActionRepository = ClientInitiatedActionRepository(context)
     private lateinit var preference: Preference
 
@@ -48,12 +48,12 @@
         super.displayPreference(screen)
         preference = screen.findPreference(preferenceKey)!!
         if (isAvailable) {
-            Utils.updatePreferenceToSpecificActivityOrRemove(
-                mContext,
-                screen,
-                preferenceKey,
-                Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY,
-            )
+            val intent = systemUpdateRepository.getSystemUpdateIntent()
+            if (intent != null) {  // Replace the intent with this specific activity
+                preference.intent = intent
+            } else { // Did not find a matching activity, so remove the preference
+                screen.removePreference(preference)
+            }
         }
     }
 
diff --git a/src/com/android/settings/system/SystemUpdateRepository.kt b/src/com/android/settings/system/SystemUpdateRepository.kt
new file mode 100644
index 0000000..f8804be
--- /dev/null
+++ b/src/com/android/settings/system/SystemUpdateRepository.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.system
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.provider.Settings
+
+class SystemUpdateRepository(context: Context) {
+    private val packageManager = context.packageManager
+
+    /**
+     * Finds a matching activity for the system update intent.
+     */
+    fun getSystemUpdateIntent(): Intent? {
+        val intent = Intent(Settings.ACTION_SYSTEM_UPDATE_SETTINGS)
+        return packageManager.resolveActivity(intent, PackageManager.MATCH_SYSTEM_ONLY)
+            ?.activityInfo
+            ?.let { activityInfo ->
+                Intent().setClassName(activityInfo.packageName, activityInfo.name)
+            }
+    }
+}
diff --git a/src/com/android/settings/vpn2/ConfigDialogFragment.java b/src/com/android/settings/vpn2/ConfigDialogFragment.java
index 860fc4e..559003a 100644
--- a/src/com/android/settings/vpn2/ConfigDialogFragment.java
+++ b/src/com/android/settings/vpn2/ConfigDialogFragment.java
@@ -209,8 +209,8 @@
                 Toast.makeText(mContext, R.string.vpn_no_network, Toast.LENGTH_LONG).show();
             } catch (UnsupportedOperationException e) {
                 Log.e(TAG, "Attempted to start an unsupported VPN type.");
-                final AlertDialog dialog = new AlertDialog.Builder(mContext)
-                        .setMessage(R.string.vpn_insecure_dialog_subtitle)
+                final AlertDialog unusedDialog = new AlertDialog.Builder(mContext)
+                        .setMessage(R.string.vpn_start_unsupported)
                         .setPositiveButton(android.R.string.ok, null)
                         .show();
             }
diff --git a/tests/robotests/src/com/android/settings/accounts/ManagedProfileQuietModeEnablerTest.java b/tests/robotests/src/com/android/settings/accounts/ManagedProfileQuietModeEnablerTest.java
index 81c44df..305b03a 100644
--- a/tests/robotests/src/com/android/settings/accounts/ManagedProfileQuietModeEnablerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/ManagedProfileQuietModeEnablerTest.java
@@ -19,18 +19,22 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.admin.flags.Flags;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.UserInfo;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.RequiresFlagsEnabled;
 
 import androidx.lifecycle.Lifecycle;
 import androidx.lifecycle.LifecycleOwner;
@@ -42,13 +46,15 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
+import org.robolectric.ParameterizedRobolectricTestRunner;
 import org.robolectric.annotation.LooperMode;
 
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(ParameterizedRobolectricTestRunner.class)
 @LooperMode(LooperMode.Mode.LEGACY)
 public class ManagedProfileQuietModeEnablerTest {
     private static final int MANAGED_USER_ID = 10;
@@ -63,6 +69,12 @@
         }
     };
 
+    @ParameterizedRobolectricTestRunner.Parameters
+    public static List<?> params() {
+        return Arrays.asList(true, false);
+    }
+    final boolean mEnable;
+
     @Mock
     private ManagedProfileQuietModeEnabler.QuietModeChangeListener mOnQuietModeChangeListener;
     @Mock
@@ -72,6 +84,10 @@
     @Mock
     private UserInfo mUserInfo;
 
+    public ManagedProfileQuietModeEnablerTest(boolean enable) {
+        mEnable = enable;
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -88,10 +104,21 @@
 
     @Test
     public void onSetQuietMode_shouldRequestQuietModeEnabled() {
-        mQuietModeEnabler.setQuietModeEnabled(false);
-        verify(mUserManager).requestQuietModeEnabled(false, mManagedUser);
-        mQuietModeEnabler.setQuietModeEnabled(true);
-        verify(mUserManager).requestQuietModeEnabled(true, mManagedUser);
+        when(mUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(!mEnable);
+
+        mQuietModeEnabler.setQuietModeEnabled(mEnable);
+
+        verify(mUserManager).requestQuietModeEnabled(mEnable, mManagedUser);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_QUIET_MODE_CREDENTIAL_BUG_FIX)
+    public void onSetQuietMode_ifQuietModeAlreadyInDesiredState_shouldNotRequestQuietModeEnabled() {
+        when(mUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(mEnable);
+
+        mQuietModeEnabler.setQuietModeEnabled(mEnable);
+
+        verify(mUserManager, never()).requestQuietModeEnabled(anyBoolean(), any());
     }
 
     @Test
@@ -107,6 +134,7 @@
                 Intent.EXTRA_USER_HANDLE, MANAGED_USER_ID));
         mContext.sendBroadcast(new Intent(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE).putExtra(
                 Intent.EXTRA_USER_HANDLE, MANAGED_USER_ID));
+
         verify(mOnQuietModeChangeListener, times(2)).onQuietModeChanged();
     }
 
@@ -123,6 +151,7 @@
                 Context.RECEIVER_EXPORTED/*UNAUDITED*/);
 
         mQuietModeEnabler.onStop(mLifecycleOwner);
+
         verify(mContext).unregisterReceiver(mQuietModeEnabler.mReceiver);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/accounts/WorkModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/WorkModePreferenceControllerTest.java
index e53ed10..8b4ebca 100644
--- a/tests/robotests/src/com/android/settings/accounts/WorkModePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/WorkModePreferenceControllerTest.java
@@ -40,9 +40,12 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.ParameterizedRobolectricTestRunner;
 import org.robolectric.RobolectricTestRunner;
 
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
 public class WorkModePreferenceControllerTest {
@@ -54,6 +57,11 @@
     private WorkModePreferenceController mController;
     private MainSwitchPreference mPreference;
 
+    @ParameterizedRobolectricTestRunner.Parameters
+    public static List<?> params() {
+        return Arrays.asList(true, false);
+    }
+    final boolean mEnable;
     @Mock
     private UserManager mUserManager;
     @Mock
@@ -65,6 +73,10 @@
     @Mock
     Switch mSwitch;
 
+    public WorkModePreferenceControllerTest(boolean enable) {
+        mEnable = enable;
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -99,28 +111,19 @@
     @Test
     public void updateState_shouldRefreshContent() {
         when(mUserManager.isQuietModeEnabled(any(UserHandle.class)))
-                .thenReturn(false);
+                .thenReturn(mEnable);
 
         mController.updateState(mPreference);
 
-        assertThat(mPreference.isChecked()).isTrue();
-
-        when(mUserManager.isQuietModeEnabled(any(UserHandle.class)))
-                .thenReturn(true);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isChecked()).isFalse();
+        assertThat(mPreference.isChecked()).isEqualTo(!mEnable);
     }
 
     @Test
     public void onPreferenceChange_shouldRequestQuietModeEnabled() {
-        mController.onCheckedChanged(mSwitch, true);
+        when(mUserManager.isQuietModeEnabled(any(UserHandle.class))).thenReturn(mEnable);
 
-        verify(mUserManager).requestQuietModeEnabled(false, mManagedUser);
+        mController.onCheckedChanged(mSwitch, mEnable);
 
-        mController.onCheckedChanged(mSwitch, false);
-
-        verify(mUserManager).requestQuietModeEnabled(true, mManagedUser);
+        verify(mUserManager).requestQuietModeEnabled(!mEnable, mManagedUser);
     }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppCounterTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppCounterTest.java
index 78cfd36..85d1b78 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppCounterTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppCounterTest.java
@@ -98,7 +98,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
         mFakeFeatureFlags = new FakeFeatureFlagsImpl();
         mFakeFeatureFlags.setFlag(Flags.FLAG_ARCHIVING, true);
 
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDevicesControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDevicesControllerTest.java
index 047a7d5..a540d28 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDevicesControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDevicesControllerTest.java
@@ -54,7 +54,7 @@
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.settings.R;
@@ -518,7 +518,8 @@
                 Settings.Secure.STYLUS_BUTTONS_ENABLED, 0);
 
         showScreen(mController);
-        SwitchPreference buttonsPref = (SwitchPreference) mPreferenceContainer.getPreference(2);
+        SwitchPreferenceCompat buttonsPref =
+                (SwitchPreferenceCompat) mPreferenceContainer.getPreference(2);
 
         assertThat(buttonsPref.isChecked()).isEqualTo(true);
     }
@@ -529,7 +530,8 @@
                 Settings.Secure.STYLUS_BUTTONS_ENABLED, 1);
 
         showScreen(mController);
-        SwitchPreference buttonsPref = (SwitchPreference) mPreferenceContainer.getPreference(2);
+        SwitchPreferenceCompat buttonsPref =
+                (SwitchPreferenceCompat) mPreferenceContainer.getPreference(2);
 
         assertThat(buttonsPref.isChecked()).isEqualTo(false);
     }
@@ -539,7 +541,8 @@
         Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.STYLUS_BUTTONS_ENABLED, 0);
         showScreen(mController);
-        SwitchPreference buttonsPref = (SwitchPreference) mPreferenceContainer.getPreference(2);
+        SwitchPreferenceCompat buttonsPref =
+                (SwitchPreferenceCompat) mPreferenceContainer.getPreference(2);
 
         buttonsPref.performClick();
 
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java
index 9129906..a326061 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java
@@ -18,8 +18,8 @@
 
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
 import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
-import static com.android.settings.deviceinfo.firmwareversion.MainlineModuleVersionPreferenceController.MODULE_UPDATE_INTENT;
-import static com.android.settings.deviceinfo.firmwareversion.MainlineModuleVersionPreferenceController.MODULE_UPDATE_V2_INTENT;
+import static com.android.settings.deviceinfo.firmwareversion.MainlineModuleVersionPreferenceController.MODULE_UPDATE_INTENT_ACTION;
+import static com.android.settings.deviceinfo.firmwareversion.MainlineModuleVersionPreferenceController.MODULE_UPDATE_V2_INTENT_ACTION;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -29,13 +29,18 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 
 import androidx.preference.Preference;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -46,6 +51,15 @@
 @RunWith(RobolectricTestRunner.class)
 public class MainlineModuleVersionPreferenceControllerTest {
 
+    private static final String MODULE_PACKAGE = "com.android.vending";
+    private static final Intent MODULE_UPDATE_V2_INTENT =
+        new Intent(MODULE_UPDATE_V2_INTENT_ACTION).setPackage(MODULE_PACKAGE);
+    private static final Intent MODULE_UPDATE_INTENT =
+        new Intent(MODULE_UPDATE_INTENT_ACTION).setPackage(MODULE_PACKAGE);
+
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
     @Mock
     private PackageManager mPackageManager;
 
@@ -58,6 +72,9 @@
         mContext = spy(RuntimeEnvironment.application);
         mPreference = new Preference(mContext);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mContext
+                 .getString(com.android.settings.R.string.config_mainline_module_update_package))
+                .thenReturn(MODULE_PACKAGE);
     }
 
     @Test
@@ -123,6 +140,7 @@
         assertThat(mPreference.isSelectable()).isTrue();
     }
 
+    @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_MAINLINE_MODULE_EXPLICIT_INTENT)
     @Test
     public void updateState_canHandleIntent_setIntentToPreference() throws Exception {
         setupModulePackage("test version 123");
@@ -137,6 +155,7 @@
         assertThat(mPreference.getIntent()).isEqualTo(MODULE_UPDATE_INTENT);
     }
 
+    @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_MAINLINE_MODULE_EXPLICIT_INTENT)
     @Test
     public void updateState_canHandleIntent_preferenceShouldBeSelectable() throws Exception {
         setupModulePackage("test version 123");
@@ -151,6 +170,7 @@
         assertThat(mPreference.isSelectable()).isTrue();
     }
 
+    @RequiresFlagsEnabled(com.android.settings.flags.Flags.FLAG_MAINLINE_MODULE_EXPLICIT_INTENT)
     @Test
     public void updateState_cannotHandleIntent_setNullToPreference() throws Exception {
         setupModulePackage("test version 123");
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/legal/ModuleLicensePreferenceTest.java b/tests/robotests/src/com/android/settings/deviceinfo/legal/ModuleLicensePreferenceTest.java
index 08eec9e..1352402 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/legal/ModuleLicensePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/legal/ModuleLicensePreferenceTest.java
@@ -24,7 +24,6 @@
 import android.content.pm.ModuleInfo;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
@@ -57,7 +56,6 @@
     }
 
     @Test
-    @Ignore
     public void onClick_sendsCorrectIntent() {
         ModuleLicensePreference pref = new ModuleLicensePreference(mContext, mModuleInfo);
 
@@ -69,7 +67,7 @@
                 .isEqualTo(ModuleLicenseProvider.getUriForPackage(PACKAGE_NAME));
         assertThat(intent.getType()).isEqualTo(ModuleLicenseProvider.LICENSE_FILE_MIME_TYPE);
         assertThat(intent.getCharSequenceExtra(Intent.EXTRA_TITLE)).isEqualTo(NAME);
-        assertThat(intent.getFlags()).isEqualTo(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        assertThat((intent.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION)).isNotEqualTo(0);
         assertThat(intent.getCategories()).contains(Intent.CATEGORY_DEFAULT);
         assertThat(intent.getPackage()).isEqualTo("com.android.htmlviewer");
     }
diff --git a/tests/spa_unit/src/com/android/settings/system/SystemUpdateRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/system/SystemUpdateRepositoryTest.kt
new file mode 100644
index 0000000..ea4617a
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/system/SystemUpdateRepositoryTest.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 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.system
+
+import android.content.Context
+import android.content.pm.ActivityInfo
+import android.content.pm.PackageManager
+import android.content.pm.ResolveInfo
+import android.provider.Settings
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.kotlin.argThat
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+
+@RunWith(AndroidJUnit4::class)
+class SystemUpdateRepositoryTest {
+    private val mockPackageManager = mock<PackageManager>()
+
+    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+        on { packageManager } doReturn mockPackageManager
+    }
+
+    private val repository = SystemUpdateRepository(context)
+
+    @Test
+    fun getSystemUpdateIntent_noResolveActivity_returnNull() {
+        val intent = repository.getSystemUpdateIntent()
+
+        assertThat(intent).isNull()
+    }
+
+    @Test
+    fun getSystemUpdateIntent_hasResolveActivity_returnIntent() {
+        mockPackageManager.stub {
+            on {
+                resolveActivity(
+                    argThat { action == Settings.ACTION_SYSTEM_UPDATE_SETTINGS },
+                    eq(PackageManager.MATCH_SYSTEM_ONLY),
+                )
+            } doReturn RESOLVE_INFO
+        }
+
+        val intent = repository.getSystemUpdateIntent()
+
+        assertThat(intent?.component?.packageName).isEqualTo(PACKAGE_NAME)
+        assertThat(intent?.component?.className).isEqualTo(ACTIVITY_NAME)
+    }
+
+    private companion object {
+        const val PACKAGE_NAME = "package.name"
+        const val ACTIVITY_NAME = "ActivityName"
+        val RESOLVE_INFO = ResolveInfo().apply {
+            activityInfo = ActivityInfo().apply {
+                packageName = PACKAGE_NAME
+                name = ACTIVITY_NAME
+            }
+        }
+    }
+}
diff --git a/tests/unit/src/com/android/settings/regionalpreferences/NumberingSystemItemControllerTest.java b/tests/unit/src/com/android/settings/regionalpreferences/NumberingSystemItemControllerTest.java
index 5c42ad9..50e21fe 100644
--- a/tests/unit/src/com/android/settings/regionalpreferences/NumberingSystemItemControllerTest.java
+++ b/tests/unit/src/com/android/settings/regionalpreferences/NumberingSystemItemControllerTest.java
@@ -99,8 +99,7 @@
         assertTrue(isCallingStartActivity);
         verify(mFeatureFactory.metricsFeatureProvider).action(
                 mApplicationContext,
-                SettingsEnums.ACTION_CHOOSE_LANGUAGE_FOR_NUMBERS_PREFERENCES,
-                "I_am_the_key");
+                SettingsEnums.ACTION_CHOOSE_LANGUAGE_FOR_NUMBERS_PREFERENCES);
     }
 
     @Test
@@ -122,8 +121,7 @@
 
         verify(mFragment).setArguments(any());
         verify(mFeatureFactory.metricsFeatureProvider).action(
-                mApplicationContext, SettingsEnums.ACTION_SET_NUMBERS_PREFERENCES,
-                "test_key");
+                mApplicationContext, SettingsEnums.ACTION_SET_NUMBERS_PREFERENCES);
     }
 
     @Test