Merge "Identity Check API" into main
diff --git a/Android.bp b/Android.bp
index 8f7bd1b..087030b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -132,6 +132,7 @@
     flags_packages: [
         "aconfig_settings_flags",
         "android.app.flags-aconfig",
+        "android.provider.flags-aconfig",
     ],
 }
 
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 11d9779..cdd9535 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -5297,7 +5297,7 @@
             android:name="Settings$ContactsStorageSettingsActivity"
             android:label="@string/contacts_storage_settings_title"
             android:exported="true"
-            android:featureFlag="com.android.settings.flags.enable_contacts_default_account_in_settings">
+            android:featureFlag="android.provider.new_default_account_api_enabled">
             <intent-filter>
                 <action android:name="android.provider.action.SET_DEFAULT_ACCOUNT" />
                 <category android:name="android.intent.category.DEFAULT" />
diff --git a/aconfig/catalyst/network_and_internet.aconfig b/aconfig/catalyst/network_and_internet.aconfig
index 130905f..e8943e6 100644
--- a/aconfig/catalyst/network_and_internet.aconfig
+++ b/aconfig/catalyst/network_and_internet.aconfig
@@ -35,3 +35,11 @@
   description: "Flag for Wi-Fi calling screen"
   bug: "323791114"
 }
+
+flag {
+  name: "catalyst_restrict_background_parent_entry"
+  namespace: "android_settings"
+  description: "Flag for Data Saver"
+  bug: "323791114"
+}
+
diff --git a/aconfig/catalyst/system.aconfig b/aconfig/catalyst/system.aconfig
new file mode 100644
index 0000000..f87ff44
--- /dev/null
+++ b/aconfig/catalyst/system.aconfig
@@ -0,0 +1,9 @@
+package: "com.android.settings.flags"
+container: "system"
+
+flag {
+    name: "catalyst_language_setting"
+    namespace: "android_settings"
+    description: "Flag for System -> Languages screen"
+    bug: "323791114"
+}
diff --git a/aconfig/settings_telephony_flag_declarations.aconfig b/aconfig/settings_telephony_flag_declarations.aconfig
index dab1b45..0279125 100644
--- a/aconfig/settings_telephony_flag_declarations.aconfig
+++ b/aconfig/settings_telephony_flag_declarations.aconfig
@@ -14,3 +14,19 @@
     description: "Control the Dual SIM onobarding feature"
     bug: "298898436"
 }
+
+# OWNER=yomna TARGET=25Q2
+flag {
+    name: "mobile_network_security_2g"
+    namespace: "cellular_security"
+    description: "Exposing 2G toggles in Mobile Network Security page"
+    bug: "355062720"
+}
+
+# OWNER=yomna TARGET=25Q2
+flag {
+    name: "add_security_transparency_to_eng_menu"
+    namespace: "cellular_security"
+    description: "Exposing security transparency features to field engineering menu"
+    bug: "355062720"
+}
diff --git a/res/xml/language_settings.xml b/res/xml/language_settings.xml
index 4613cb0..7618399 100644
--- a/res/xml/language_settings.xml
+++ b/res/xml/language_settings.xml
@@ -19,7 +19,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/languages_settings"
-    android:key="languages_settings">
+    android:key="language_settings">
     <PreferenceCategory
         android:key="languages_category"
         android:title="@string/locale_picker_category_title">
diff --git a/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java b/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
index 0550a9a..db239aa 100644
--- a/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
+++ b/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
@@ -36,6 +36,7 @@
 import android.app.AppGlobals;
 import android.app.compat.CompatChanges;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.LauncherApps;
@@ -44,6 +45,7 @@
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.util.SparseIntArray;
 
 import androidx.annotation.NonNull;
@@ -71,6 +73,7 @@
     private static final boolean DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_FULLSCREEN = true;
 
     final boolean mIsUserMinAspectRatioAppDefaultFlagEnabled = Flags.userMinAspectRatioAppDefault();
+    private final boolean mIgnoreActivityOrientationRequest;
 
     private final Context mContext;
     private final IPackageManager mIPm;
@@ -90,6 +93,8 @@
         mUserAspectRatioA11yMap = new ArrayMap<>();
         mUserAspectRatioOrder = new SparseIntArray();
         mUserAspectRatioMap = getUserMinAspectRatioMapping();
+        mIgnoreActivityOrientationRequest = getValueFromDeviceConfig(
+                "ignore_activity_orientation_request", false);
     }
 
     /**
@@ -113,6 +118,24 @@
                 ? aspectRatio : USER_MIN_ASPECT_RATIO_UNSET;
     }
 
+    // TODO b/374903057 reuse method from ActivityRecord
+    boolean isUniversalResizeable(@NonNull String packageName, int userId) {
+        try {
+            final ApplicationInfo info = mIPm.getApplicationInfo(
+                    packageName, 0 /* flags */, userId);
+            if (info == null || info.category == ApplicationInfo.CATEGORY_GAME) {
+                return false;
+            }
+            final boolean compatEnabled = Flags.universalResizableByDefault()
+                    && info.isChangeEnabled(ActivityInfo.UNIVERSAL_RESIZABLE_BY_DEFAULT);
+            return compatEnabled || mIgnoreActivityOrientationRequest;
+        } catch (RemoteException e) {
+            Log.e("UserAspectRatioManager", "Could not access application info for "
+                    + packageName + ":\n" + e);
+            return false;
+        }
+    }
+
     /**
      * @return corresponding string for {@link PackageManager.UserMinAspectRatio} value
      */
@@ -127,7 +150,7 @@
             return appDefault;
         }
 
-        return isCurrentSelectionFromManufacturerOverride(packageName, userId, aspectRatio)
+        return isUnsetAndRequiresFullscreenOverride(packageName, userId, aspectRatio)
                 ? getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN, packageName, userId)
                 : mUserAspectRatioMap.getOrDefault(aspectRatio, appDefault);
     }
@@ -139,7 +162,7 @@
     public CharSequence getAccessibleEntry(@PackageManager.UserMinAspectRatio int aspectRatio,
             @NonNull String packageName) {
         final int userId = mContext.getUserId();
-        return isCurrentSelectionFromManufacturerOverride(packageName, userId, aspectRatio)
+        return isUnsetAndRequiresFullscreenOverride(packageName, userId, aspectRatio)
                 ? getAccessibleEntry(USER_MIN_ASPECT_RATIO_FULLSCREEN, packageName)
                 : mUserAspectRatioA11yMap.getOrDefault(aspectRatio,
                         getUserMinAspectRatioEntry(aspectRatio, packageName, userId));
@@ -203,7 +226,7 @@
             @PackageManager.UserMinAspectRatio int userOverride) {
         return (userOverride != USER_MIN_ASPECT_RATIO_UNSET
                     && userOverride != USER_MIN_ASPECT_RATIO_APP_DEFAULT)
-                || isCurrentSelectionFromManufacturerOverride(app.packageName, getUserId(app.uid),
+                || isUnsetAndRequiresFullscreenOverride(app.packageName, getUserId(app.uid),
                     userOverride);
     }
 
@@ -224,7 +247,7 @@
     /**
      * Whether the device manufacturer has overridden app's orientation to
      * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_USER} to force app to fullscreen
-     * and app has not opted-out from the treatment
+     * or app is universal resizeable, and app has not opted-out from the treatment
      */
     boolean isOverrideToFullscreenEnabled(String pkgName, int userId) {
         Boolean appAllowsOrientationOverride = readComponentProperty(mContext.getPackageManager(),
@@ -232,7 +255,8 @@
         return mIsUserMinAspectRatioAppDefaultFlagEnabled
                 && hasAspectRatioOption(USER_MIN_ASPECT_RATIO_FULLSCREEN, pkgName)
                 && !FALSE.equals(appAllowsOrientationOverride)
-                && isFullscreenCompatChangeEnabled(pkgName, userId);
+                && (isFullscreenCompatChangeEnabled(pkgName, userId)
+                    || isUniversalResizeable(pkgName, userId));
     }
 
     boolean isFullscreenCompatChangeEnabled(String pkgName, int userId) {
@@ -240,7 +264,11 @@
                 OVERRIDE_ANY_ORIENTATION_TO_USER, pkgName, UserHandle.of(userId));
     }
 
-    private boolean isCurrentSelectionFromManufacturerOverride(String pkgName, int userId,
+    /**
+     * Whether the aspect ratio is unset and we desire to interpret it as fullscreen rather than
+     * app default because of manufacturer override or because the app is universal resizeable
+     */
+    private boolean isUnsetAndRequiresFullscreenOverride(String pkgName, int userId,
             @PackageManager.UserMinAspectRatio int aspectRatio) {
         return aspectRatio == USER_MIN_ASPECT_RATIO_UNSET
                 && isOverrideToFullscreenEnabled(pkgName, userId);
diff --git a/src/com/android/settings/applications/contacts/ContactsStoragePreferenceController.java b/src/com/android/settings/applications/contacts/ContactsStoragePreferenceController.java
index 6c179da..e4343e5 100644
--- a/src/com/android/settings/applications/contacts/ContactsStoragePreferenceController.java
+++ b/src/com/android/settings/applications/contacts/ContactsStoragePreferenceController.java
@@ -21,11 +21,11 @@
 import android.content.Context;
 import android.os.UserHandle;
 import android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState;
+import android.provider.Flags;
 import android.util.Log;
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
-import com.android.settings.flags.Flags;
 import com.android.settingslib.accounts.AuthenticatorHelper;
 
 /**
@@ -54,7 +54,7 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return (Flags.enableContactsDefaultAccountInSettings()
+        return (Flags.newDefaultAccountApiEnabled()
                 && mCurrentDefaultAccountAndState != null) ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
     }
 
@@ -71,7 +71,12 @@
                     == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_LOCAL) {
                 return mContext.getResources().getString(
                         R.string.contacts_storage_local_account_summary);
-            } else if (currentDefaultAccount != null) {
+            } else if (currentDefaultAccountState
+                    == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_SIM) {
+                return mContext.getResources().getString(
+                        R.string.sim_card_label);
+            } else if (currentDefaultAccountState
+                    == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD) {
                 String accountTypeLabel = (String) mAuthenticatorHelper.getLabelForType(mContext,
                         currentDefaultAccount.type);
                 // If there's no account type, or the account type is the same as the
diff --git a/src/com/android/settings/applications/contacts/ContactsStorageSettings.java b/src/com/android/settings/applications/contacts/ContactsStorageSettings.java
index 3d449cf..8e71d08 100644
--- a/src/com/android/settings/applications/contacts/ContactsStorageSettings.java
+++ b/src/com/android/settings/applications/contacts/ContactsStorageSettings.java
@@ -28,7 +28,9 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState;
+import android.util.Log;
 import android.widget.Toast;
+
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
@@ -79,10 +81,16 @@
         for (String preferenceKey : mAccountMap.keySet()) {
             if (selectedPreferenceKey.equals(preferenceKey)) {
                 try {
+                    DefaultAccountAndState currentDefaultAccount = mAccountMap.get(preferenceKey);
                     DefaultAccount.setDefaultAccountForNewContacts(getContentResolver(),
-                            mAccountMap.get(preferenceKey));
+                            currentDefaultAccount);
                     selectedPref.setChecked(true);
+                    if (currentDefaultAccount.getState()
+                            == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD) {
+                        startMoveLocalAndSimContactsActivity();
+                    }
                 } catch (RuntimeException e) {
+                    Log.e(TAG, "Error setting the default account " + e);
                     Toast.makeText(getContext(),
                             R.string.contacts_storage_set_default_account_error_message,
                             Toast.LENGTH_SHORT).show();
@@ -123,9 +131,14 @@
         // when creating eligible account preferences.
         mAccountMap.clear();
         final PreferenceScreen screen = getPreferenceScreen();
+        // If the default account is SIM, we should show in the page, otherwise don't show.
+        SelectorWithWidgetPreference simAccountPreference = buildSimAccountPreference();
+        if (simAccountPreference != null) {
+            getPreferenceScreen().addPreference(simAccountPreference);
+        }
         List<Account> accounts = DefaultAccount.getEligibleCloudAccounts(getContentResolver());
         for (int i = 0; i < accounts.size(); i++) {
-            screen.addPreference(buildAccountPreference(accounts.get(i), /*order=*/i));
+            screen.addPreference(buildCloudAccountPreference(accounts.get(i), /*order=*/i));
         }
         // If there's no eligible account types, the "Add Account" preference should
         // not be shown to the users.
@@ -156,7 +169,7 @@
         if (mAccountMap.containsKey(preferenceKey)) {
             preference = getPreferenceScreen().findPreference(preferenceKey);
         } else if (preferenceKey != null && currentDefaultAccount != null) {
-            preference = buildAccountPreference(currentDefaultAccount, mAccountMap.size());
+            preference = buildCloudAccountPreference(currentDefaultAccount, mAccountMap.size());
             getPreferenceScreen().addPreference(preference);
         }
         if (preference != null) {
@@ -165,7 +178,7 @@
     }
 
     //TODO: Add preference category on account preferences.
-    private SelectorWithWidgetPreference buildAccountPreference(Account account, int order) {
+    private SelectorWithWidgetPreference buildCloudAccountPreference(Account account, int order) {
         SelectorWithWidgetPreference preference = new SelectorWithWidgetPreference(
                 getPrefContext());
         DefaultAccountAndState accountAndState = DefaultAccountAndState.ofCloud(account);
@@ -180,6 +193,26 @@
         return preference;
     }
 
+    @Nullable
+    private SelectorWithWidgetPreference buildSimAccountPreference() {
+        DefaultAccountAndState currentDefaultAccountAndState =
+                DefaultAccount.getDefaultAccountForNewContacts(getContentResolver());
+        if (currentDefaultAccountAndState.getState()
+                == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_SIM) {
+            String preferenceKey = getAccountHashCode(currentDefaultAccountAndState);
+            SelectorWithWidgetPreference preference = new SelectorWithWidgetPreference(
+                    getPrefContext());
+            preference.setTitle(R.string.sim_card_label);
+            preference.setIcon(R.drawable.ic_sim_card);
+            preference.setSummary(R.string.sim_card_label);
+            preference.setKey(preferenceKey);
+            preference.setOnClickListener(this);
+            mAccountMap.put(preferenceKey, currentDefaultAccountAndState);
+            return preference;
+        }
+        return null;
+    }
+
     private RestrictedPreference buildAddAccountPreference(boolean noAccountBeenAdded) {
         RestrictedPreference preference = new RestrictedPreference(getPrefContext());
         preference.setKey(PREF_KEY_ADD_ACCOUNT);
@@ -194,7 +227,17 @@
         return preference;
     }
 
-    private @Nullable String getAccountHashCode(DefaultAccountAndState currentDefaultAccountAndState) {
+    private void startMoveLocalAndSimContactsActivity() {
+        Intent intent = new Intent()
+                .setAction(DefaultAccount.ACTION_MOVE_CONTACTS_TO_DEFAULT_ACCOUNT)
+                .setPackage("com.android.providers.contacts")
+                .addFlags(FLAG_ACTIVITY_NEW_TASK);
+        getContext().startActivity(intent);
+    }
+
+    @Nullable
+    private String getAccountHashCode(
+            DefaultAccountAndState currentDefaultAccountAndState) {
         Account currentDefaultAccount = currentDefaultAccountAndState.getAccount();
         if (currentDefaultAccount != null && (currentDefaultAccountAndState.getState()
                 == DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index 0e51d17..2860ce8 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -421,11 +421,13 @@
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         List<String> invisibleProfiles = List.of();
         if (Flags.enableBluetoothDeviceDetailsPolish()) {
-            mFormatter =
-                    FeatureFactory.getFeatureFactory()
-                            .getBluetoothFeatureProvider()
-                            .getDeviceDetailsFragmentFormatter(
-                                    requireContext(), this, mBluetoothAdapter, mCachedDevice);
+            if (mFormatter == null) {
+                mFormatter =
+                        FeatureFactory.getFeatureFactory()
+                                .getBluetoothFeatureProvider()
+                                .getDeviceDetailsFragmentFormatter(
+                                        requireContext(), this, mBluetoothAdapter, mCachedDevice);
+            }
             invisibleProfiles =
                     mFormatter.getInvisibleBluetoothProfiles(
                             FragmentTypeModel.DeviceDetailsMainFragment.INSTANCE);
diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
index be0f6f3..1bad5e5 100644
--- a/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
+++ b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
@@ -25,7 +25,6 @@
 import android.net.Uri;
 
 import androidx.annotation.NonNull;
-import androidx.lifecycle.LifecycleCoroutineScope;
 import androidx.preference.Preference;
 
 import com.android.settings.SettingsPreferenceFragment;
@@ -34,12 +33,12 @@
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import java.util.List;
 import java.util.Set;
 
-/**
- * Provider for bluetooth related features.
- */
+/** Provider for bluetooth related features. */
 public interface BluetoothFeatureProvider {
 
     /**
@@ -86,26 +85,25 @@
     /**
      * Gets the bluetooth profile preference keys which should be hidden in the device details page.
      *
-     * @param context         Context
+     * @param context Context
      * @param bluetoothDevice the bluetooth device
      * @return the profiles which should be hidden
      */
-    Set<String> getInvisibleProfilePreferenceKeys(
-            Context context, BluetoothDevice bluetoothDevice);
+    Set<String> getInvisibleProfilePreferenceKeys(Context context, BluetoothDevice bluetoothDevice);
 
     /** Gets DeviceSettingRepository. */
     @NonNull
     DeviceSettingRepository getDeviceSettingRepository(
             @NonNull Context context,
             @NonNull BluetoothAdapter bluetoothAdapter,
-            @NonNull LifecycleCoroutineScope scope);
+            @NonNull CoroutineScope scope);
 
     /** Gets spatial audio interactor. */
     @NonNull
     SpatialAudioInteractor getSpatialAudioInteractor(
             @NonNull Context context,
             @NonNull AudioManager audioManager,
-            @NonNull LifecycleCoroutineScope scope);
+            @NonNull CoroutineScope scope);
 
     /** Gets device details fragment layout formatter. */
     @NonNull
diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt
index 25c586e..6f967a2 100644
--- a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt
+++ b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt
@@ -22,6 +22,7 @@
 import android.media.AudioManager
 import android.media.Spatializer
 import android.net.Uri
+import android.util.Log
 import androidx.lifecycle.LifecycleCoroutineScope
 import androidx.preference.Preference
 import com.android.settings.SettingsPreferenceFragment
@@ -37,6 +38,7 @@
 import com.android.settingslib.media.domain.interactor.SpatializerInteractor
 import com.google.common.collect.ImmutableList
 import com.google.common.collect.ImmutableSet
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 
 /** Impl of [BluetoothFeatureProvider] */
@@ -76,14 +78,14 @@
     override fun getDeviceSettingRepository(
         context: Context,
         bluetoothAdapter: BluetoothAdapter,
-        scope: LifecycleCoroutineScope
+        scope: CoroutineScope
     ): DeviceSettingRepository =
         DeviceSettingRepositoryImpl(context, bluetoothAdapter, scope, Dispatchers.IO)
 
     override fun getSpatialAudioInteractor(
         context: Context,
         audioManager: AudioManager,
-        scope: LifecycleCoroutineScope
+        scope: CoroutineScope,
     ): SpatialAudioInteractor {
         return SpatialAudioInteractorImpl(
             context, audioManager,
diff --git a/src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractor.kt b/src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractor.kt
index 6b72b53..4b91716a 100644
--- a/src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractor.kt
+++ b/src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractor.kt
@@ -147,7 +147,7 @@
     }
 
     companion object {
-        private const val TAG = "SpatialAudioInteractorImpl"
+        private const val TAG = "SpatialAudioInteractor"
         private const val INDEX_SPATIAL_AUDIO_OFF = 0
         private const val INDEX_SPATIAL_AUDIO_ON = 1
         private const val INDEX_HEAD_TRACKING_ENABLED = 2
diff --git a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt
index ad4176f..13c3b50 100644
--- a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt
+++ b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt
@@ -19,11 +19,10 @@
 import android.bluetooth.BluetoothAdapter
 import android.content.Context
 import android.content.Intent
-import android.media.AudioManager
 import android.os.Bundle
 import androidx.compose.animation.AnimatedVisibility
-import androidx.compose.animation.expandVertically
-import androidx.compose.animation.shrinkVertically
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.padding
@@ -33,14 +32,12 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import androidx.lifecycle.lifecycleScope
 import androidx.preference.Preference
 import com.android.settings.R
 import com.android.settings.SettingsPreferenceFragment
@@ -52,7 +49,6 @@
 import com.android.settings.bluetooth.ui.view.DeviceDetailsMoreSettingsFragment.Companion.KEY_DEVICE_ADDRESS
 import com.android.settings.bluetooth.ui.viewmodel.BluetoothDeviceDetailsViewModel
 import com.android.settings.core.SubSettingLauncher
-import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
 import com.android.settings.spa.preference.ComposePreference
 import com.android.settingslib.bluetooth.CachedBluetoothDevice
 import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingActionModel
@@ -97,29 +93,17 @@
 class DeviceDetailsFragmentFormatterImpl(
     private val context: Context,
     private val fragment: SettingsPreferenceFragment,
-    bluetoothAdapter: BluetoothAdapter,
+    private val bluetoothAdapter: BluetoothAdapter,
     private val cachedDevice: CachedBluetoothDevice,
     private val backgroundCoroutineContext: CoroutineContext,
 ) : DeviceDetailsFragmentFormatter {
-    private val repository =
-        featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository(
-            fragment.requireActivity().application,
-            bluetoothAdapter,
-            fragment.lifecycleScope,
-        )
-    private val spatialAudioInteractor =
-        featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor(
-            fragment.requireActivity().application,
-            context.getSystemService(AudioManager::class.java),
-            fragment.lifecycleScope,
-        )
+
     private val viewModel: BluetoothDeviceDetailsViewModel =
         ViewModelProvider(
                 fragment,
                 BluetoothDeviceDetailsViewModel.Factory(
                     fragment.requireActivity().application,
-                    repository,
-                    spatialAudioInteractor,
+                    bluetoothAdapter,
                     cachedDevice,
                     backgroundCoroutineContext,
                 ),
@@ -224,8 +208,8 @@
         val settings = contents
         AnimatedVisibility(
             visible = settings.isNotEmpty(),
-            enter = expandVertically(expandFrom = Alignment.Top),
-            exit = shrinkVertically(shrinkTowards = Alignment.Top),
+            enter = fadeIn(),
+            exit = fadeOut(),
         ) {
             Box {
                 Box(
diff --git a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsMoreSettingsFragment.kt b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsMoreSettingsFragment.kt
index 7cb1c0d..66fba70 100644
--- a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsMoreSettingsFragment.kt
+++ b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsMoreSettingsFragment.kt
@@ -120,13 +120,15 @@
                     finish()
                     return emptyList()
                 }
-        formatter =
-            featureFactory.bluetoothFeatureProvider.getDeviceDetailsFragmentFormatter(
-                requireContext(),
-                this,
-                bluetoothManager.adapter,
-                cachedDevice,
-            )
+        if (!this::formatter.isInitialized) {
+            formatter =
+                featureFactory.bluetoothFeatureProvider.getDeviceDetailsFragmentFormatter(
+                    requireContext(),
+                    this,
+                    bluetoothManager.adapter,
+                    cachedDevice,
+                )
+        }
         helpItem =
             formatter
                 .getMenuItem(FragmentTypeModel.DeviceDetailsMoreSettingsFragment)
diff --git a/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt b/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt
index 3b7a582..1ea2da3 100644
--- a/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt
+++ b/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt
@@ -17,20 +17,22 @@
 package com.android.settings.bluetooth.ui.viewmodel
 
 import android.app.Application
+import android.bluetooth.BluetoothAdapter
+import android.media.AudioManager
+import android.util.Log
 import androidx.lifecycle.AndroidViewModel
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.viewModelScope
 import com.android.settings.R
-import com.android.settings.bluetooth.domain.interactor.SpatialAudioInteractor
 import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout
 import com.android.settings.bluetooth.ui.layout.DeviceSettingLayoutColumn
 import com.android.settings.bluetooth.ui.layout.DeviceSettingLayoutRow
 import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel
 import com.android.settings.bluetooth.ui.model.FragmentTypeModel
+import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
 import com.android.settingslib.bluetooth.CachedBluetoothDevice
 import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId
-import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository
 import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel
 import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
 import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel
@@ -47,12 +49,24 @@
 
 class BluetoothDeviceDetailsViewModel(
     private val application: Application,
-    private val deviceSettingRepository: DeviceSettingRepository,
-    private val spatialAudioInteractor: SpatialAudioInteractor,
+    private val bluetoothAdapter: BluetoothAdapter,
     private val cachedDevice: CachedBluetoothDevice,
     backgroundCoroutineContext: CoroutineContext,
 ) : AndroidViewModel(application) {
 
+    private val deviceSettingRepository =
+        featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository(
+            application,
+            bluetoothAdapter,
+            viewModelScope,
+        )
+    private val spatialAudioInteractor =
+        featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor(
+            application,
+            application.getSystemService(AudioManager::class.java),
+            viewModelScope,
+        )
+
     private val items =
         viewModelScope.async(backgroundCoroutineContext, start = CoroutineStart.LAZY) {
             deviceSettingRepository.getDeviceSettingsConfig(cachedDevice)
@@ -202,8 +216,7 @@
 
     class Factory(
         private val application: Application,
-        private val deviceSettingRepository: DeviceSettingRepository,
-        private val spatialAudioInteractor: SpatialAudioInteractor,
+        private val bluetoothAdapter: BluetoothAdapter,
         private val cachedDevice: CachedBluetoothDevice,
         private val backgroundCoroutineContext: CoroutineContext,
     ) : ViewModelProvider.Factory {
@@ -211,8 +224,7 @@
             @Suppress("UNCHECKED_CAST")
             return BluetoothDeviceDetailsViewModel(
                 application,
-                deviceSettingRepository,
-                spatialAudioInteractor,
+                bluetoothAdapter,
                 cachedDevice,
                 backgroundCoroutineContext,
             )
diff --git a/src/com/android/settings/datausage/DataSaverScreen.kt b/src/com/android/settings/datausage/DataSaverScreen.kt
new file mode 100644
index 0000000..171f002
--- /dev/null
+++ b/src/com/android/settings/datausage/DataSaverScreen.kt
@@ -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.datausage
+
+import android.content.Context
+import com.android.settings.R
+import com.android.settings.flags.Flags
+import com.android.settingslib.metadata.ProvidePreferenceScreen
+import com.android.settingslib.metadata.preferenceHierarchy
+import com.android.settingslib.preference.PreferenceScreenCreator
+
+@ProvidePreferenceScreen
+class DataSaverScreen : PreferenceScreenCreator {
+    override val key
+        get() = KEY
+
+    override val title
+        get() = R.string.data_saver_title
+
+    override val icon: Int
+        get() = R.drawable.ic_settings_data_usage
+
+    override fun order(context: Context) = 10
+
+    override fun isFlagEnabled(context: Context) = Flags.catalystRestrictBackgroundParentEntry()
+
+    override fun fragmentClass() = DataSaverSummary::class.java
+
+    override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
+
+    override fun hasCompleteHierarchy() = false
+
+    companion object {
+        const val KEY = "restrict_background_parent_entry"
+    }
+}
diff --git a/src/com/android/settings/datausage/DataSaverSummary.kt b/src/com/android/settings/datausage/DataSaverSummary.kt
index e118bd6..8db6333 100644
--- a/src/com/android/settings/datausage/DataSaverSummary.kt
+++ b/src/com/android/settings/datausage/DataSaverSummary.kt
@@ -79,6 +79,8 @@
     override fun getHelpResource() = R.string.help_url_data_saver
     override fun getLogTag() = TAG
 
+    override fun getPreferenceScreenBindingKey(context: Context) = DataSaverScreen.KEY
+
     private val dataSaverBackendListener = object : DataSaverBackend.Listener {
         override fun onDataSaverChanged(isDataSaving: Boolean) {
             synchronized(this) {
diff --git a/src/com/android/settings/language/LanguageSettingScreen.kt b/src/com/android/settings/language/LanguageSettingScreen.kt
new file mode 100644
index 0000000..09ca11b
--- /dev/null
+++ b/src/com/android/settings/language/LanguageSettingScreen.kt
@@ -0,0 +1,54 @@
+/*
+ * 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.language
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.PackageManager
+import com.android.settings.R
+import com.android.settings.Settings.LanguageSettingsActivity
+import com.android.settings.flags.Flags
+import com.android.settingslib.metadata.PreferenceAvailabilityProvider
+import com.android.settingslib.metadata.ProvidePreferenceScreen
+import com.android.settingslib.metadata.preferenceHierarchy
+import com.android.settingslib.preference.PreferenceScreenCreator
+
+@ProvidePreferenceScreen
+class LanguageSettingScreen: PreferenceScreenCreator {
+    override val key: String
+        get() = KEY
+
+    override val title: Int
+        get() = R.string.languages_settings
+
+    override val summary: Int
+        get() = R.string.languages_setting_summary
+
+    override val icon: Int
+        get() = R.drawable.ic_settings_languages
+
+    override fun isFlagEnabled(context: Context) = Flags.catalystLanguageSetting()
+
+    override fun hasCompleteHierarchy() = false
+
+    override fun fragmentClass() = LanguageSettings::class.java
+
+    override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
+
+    companion object {
+        const val KEY = "language_setting"
+    }
+}
diff --git a/src/com/android/settings/language/LanguageSettings.java b/src/com/android/settings/language/LanguageSettings.java
index a5adb02..d992ff2 100644
--- a/src/com/android/settings/language/LanguageSettings.java
+++ b/src/com/android/settings/language/LanguageSettings.java
@@ -67,6 +67,11 @@
     }
 
     @Override
+    public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
+        return LanguageSettingScreen.KEY;
+    }
+
+    @Override
     protected int getPreferenceScreenResId() {
         return R.xml.language_settings;
     }
diff --git a/src/com/android/settings/network/SimOnboardingService.kt b/src/com/android/settings/network/SimOnboardingService.kt
index e4f17e2..0882b81 100644
--- a/src/com/android/settings/network/SimOnboardingService.kt
+++ b/src/com/android/settings/network/SimOnboardingService.kt
@@ -74,8 +74,11 @@
         }
     var isEsimProfileEnabled: Boolean = false
         get() {
-            activeSubInfoList.stream().anyMatch { it.isEmbedded }
-            return false
+            return activeSubInfoList.stream().anyMatch { it.isEmbedded }
+        }
+    var isRemovableSimProfileEnabled: Boolean = false
+        get() {
+            return activeSubInfoList.stream().anyMatch { !it.isEmbedded }
         }
     var doesTargetSimActive = false
         get() {
@@ -288,8 +291,8 @@
             Log.d(TAG, "Hardware does not support DSDS.")
             return false
         }
-        val isActiveSim = activeSubInfoList.isNotEmpty()
-        if (isMultipleEnabledProfilesSupported && isActiveSim) {
+        val anyActiveSim = activeSubInfoList.isNotEmpty()
+        if (isMultipleEnabledProfilesSupported && anyActiveSim) {
             Log.d(TAG,
                 "Device supports MEP and eSIM operation and eSIM profile is enabled."
                         + " DSDS condition satisfied."
@@ -297,15 +300,13 @@
             return true
         }
 
-        if (doesTargetSimHaveEsimOperation) {
-            if (UiccSlotRepository(telephonyManager).anyRemovablePhysicalSimEnabled()) {
-                Log.d(
-                    TAG,
-                    "eSIM operation and removable PSIM is enabled. DSDS condition satisfied."
-                )
-                return true
-            }
-        } else if (isEsimProfileEnabled) {
+        if (doesTargetSimHaveEsimOperation && isRemovableSimProfileEnabled) {
+            Log.d(TAG,
+                "eSIM operation and removable PSIM is enabled. DSDS condition satisfied."
+            )
+            return true
+        }
+        if (!doesTargetSimHaveEsimOperation && isEsimProfileEnabled) {
             Log.d(TAG,
                 "Removable SIM operation and eSIM profile is enabled. DSDS condition"
                         + " satisfied."
diff --git a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
index f9751f1..f4d2ce2 100644
--- a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
+++ b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
@@ -557,15 +557,17 @@
             Log.d(TAG, "Hardware does not support DSDS.");
             return false;
         }
-        boolean isActiveSim = SubscriptionUtil.getActiveSubscriptions(
+        boolean anyActiveSim = SubscriptionUtil.getActiveSubscriptions(
                 mSubscriptionManager).size() > 0;
-        if (isMultipleEnabledProfilesSupported() && isActiveSim) {
+        if (isMultipleEnabledProfilesSupported() && anyActiveSim) {
             Log.d(TAG,
                     "Device supports MEP and eSIM operation and eSIM profile is enabled."
                             + " DSDS condition satisfied.");
             return true;
         }
-        boolean isRemovableSimEnabled = isRemovableSimEnabled();
+        boolean isRemovableSimEnabled =
+                SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager).stream()
+                        .anyMatch(subInfo-> !subInfo.isEmbedded());
         if (mIsEsimOperation && isRemovableSimEnabled) {
             Log.d(TAG, "eSIM operation and removable SIM is enabled. DSDS condition satisfied.");
             return true;
@@ -583,7 +585,7 @@
     }
 
     private boolean isRemovableSimEnabled() {
-        return new UiccSlotRepository(mTelMgr).anyRemovablePhysicalSimEnabled();
+        return new UiccSlotRepository(mTelMgr).anyRemovablePhysicalSimSlotActiveAndInserted();
     }
 
     private boolean isMultipleEnabledProfilesSupported() {
diff --git a/src/com/android/settings/network/telephony/UiccSlotRepository.kt b/src/com/android/settings/network/telephony/UiccSlotRepository.kt
index 3a83805..8a20329 100644
--- a/src/com/android/settings/network/telephony/UiccSlotRepository.kt
+++ b/src/com/android/settings/network/telephony/UiccSlotRepository.kt
@@ -22,17 +22,17 @@
 
 class UiccSlotRepository(private val telephonyManager: TelephonyManager?) {
 
-    /** Returns whether any removable physical sim is enabled. */
-    fun anyRemovablePhysicalSimEnabled(): Boolean {
+    /** Returns whether any removable physical sim slot is active and the sim is inserted. */
+    fun anyRemovablePhysicalSimSlotActiveAndInserted(): Boolean {
         val result =
             telephonyManager?.uiccSlotsInfo?.any { uiccSlotInfo: UiccSlotInfo? ->
-                uiccSlotInfo.isRemovablePhysicalSimEnabled()
+                uiccSlotInfo.isRemovablePhysicalSimSlotActiveAndInserted()
             } ?: false
         Log.i(TAG, "anyRemovablePhysicalSimEnabled: $result")
         return result
     }
 
-    private fun UiccSlotInfo?.isRemovablePhysicalSimEnabled(): Boolean {
+    private fun UiccSlotInfo?.isRemovablePhysicalSimSlotActiveAndInserted(): Boolean {
         return this != null &&
             isRemovable &&
             !isEuicc &&
diff --git a/src/com/android/settings/network/tether/TetherSettings.java b/src/com/android/settings/network/tether/TetherSettings.java
index 77ef4b6..7458514 100644
--- a/src/com/android/settings/network/tether/TetherSettings.java
+++ b/src/com/android/settings/network/tether/TetherSettings.java
@@ -54,8 +54,8 @@
 import androidx.preference.TwoStatePreference;
 
 import com.android.settings.R;
-import com.android.settings.RestrictedSettingsFragment;
 import com.android.settings.Utils;
+import com.android.settings.dashboard.RestrictedDashboardFragment;
 import com.android.settings.datausage.DataSaverBackend;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.wifi.tether.WifiTetherPreferenceController;
@@ -75,7 +75,7 @@
  * Displays preferences for Tethering.
  */
 @SearchIndexable
-public class TetherSettings extends RestrictedSettingsFragment
+public class TetherSettings extends RestrictedDashboardFragment
         implements DataSaverBackend.Listener {
 
     @VisibleForTesting
@@ -144,10 +144,18 @@
     }
 
     @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.tether_prefs;
+    }
+
+    @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        // Even when the UI is restricted, addPreferencesFromResource cannot be omitted.
-        addPreferencesFromResource(R.xml.tether_prefs);
         setIfOnlyAvailableForAdmins(true);
         if (isUiRestricted()) {
             return;
diff --git a/src/com/android/settings/notification/app/BundleListPreferenceController.java b/src/com/android/settings/notification/app/BundleListPreferenceController.java
index 82e910c..9ada049 100644
--- a/src/com/android/settings/notification/app/BundleListPreferenceController.java
+++ b/src/com/android/settings/notification/app/BundleListPreferenceController.java
@@ -91,14 +91,27 @@
     public void updateState(Preference preference) {
         PreferenceCategory category = (PreferenceCategory) preference;
 
-        createOrUpdatePrefForChannel(category,
-                mBackend.getChannel(mAppRow.pkg, mAppRow.uid, PROMOTIONS_ID));
-        createOrUpdatePrefForChannel(category,
-                mBackend.getChannel(mAppRow.pkg, mAppRow.uid, RECS_ID));
-        createOrUpdatePrefForChannel(category,
-                mBackend.getChannel(mAppRow.pkg, mAppRow.uid, SOCIAL_MEDIA_ID));
-        createOrUpdatePrefForChannel(category,
-                mBackend.getChannel(mAppRow.pkg, mAppRow.uid, NEWS_ID));
+        NotificationChannel promos = mBackend.getChannel(mAppRow.pkg, mAppRow.uid, PROMOTIONS_ID);
+        if (promos != null) {
+            createOrUpdatePrefForChannel(category, promos);
+        }
+        NotificationChannel recs = mBackend.getChannel(mAppRow.pkg, mAppRow.uid, RECS_ID);
+        if (recs != null) {
+            createOrUpdatePrefForChannel(category, recs);
+        }
+        NotificationChannel social = mBackend.getChannel(mAppRow.pkg, mAppRow.uid, SOCIAL_MEDIA_ID);
+        if (social != null) {
+            createOrUpdatePrefForChannel(category, social);
+        }
+        NotificationChannel news = mBackend.getChannel(mAppRow.pkg, mAppRow.uid, NEWS_ID);
+        if (news != null) {
+            createOrUpdatePrefForChannel(category, news);
+        }
+
+        int preferenceCount = ((PreferenceGroup) preference).getPreferenceCount();
+        if (preferenceCount == 0) {
+            preference.setVisible(false);
+        }
     }
 
     @NonNull
@@ -167,5 +180,4 @@
         icon.setTintList(Utils.getColorAccent(mContext));
         return icon;
     }
-
 }
diff --git a/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java b/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java
index 014a190..13d5c6e 100644
--- a/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java
@@ -40,6 +40,7 @@
 import androidx.preference.Preference;
 
 import com.android.settings.R;
+import com.android.settings.Utils;
 import com.android.settingslib.PrimarySwitchPreference;
 import com.android.settingslib.notification.modes.ZenMode;
 import com.android.settingslib.notification.modes.ZenModesBackend;
@@ -108,7 +109,9 @@
                     tryParseScheduleConditionId(mode.getRule().getConditionId());
             if (schedule != null) {
                 preference.setTitle(SystemZenRules.getTimeSummary(mContext, schedule));
-                preference.setSummary(SystemZenRules.getShortDaysSummary(mContext, schedule));
+                preference.setSummary(Utils.createAccessibleSequence(
+                        SystemZenRules.getDaysOfWeekShort(mContext, schedule),
+                        SystemZenRules.getDaysOfWeekFull(mContext, schedule)));
             } else {
                 // Fallback, but shouldn't happen.
                 Log.wtf(TAG, "SCHEDULE_TIME mode without schedule: " + mode);
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
index 9febba3..5ea9b3c 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
@@ -58,6 +58,9 @@
     private final WifiManager mWifiManager;
 
     @VisibleForTesting
+    boolean mIsSwitchBusy;
+
+    @VisibleForTesting
     DataSaverBackend mDataSaverBackend;
     @VisibleForTesting
     final ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback =
@@ -102,8 +105,8 @@
 
     @Override
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-        // Filter out unnecessary callbacks when switch is disabled.
-        if (!buttonView.isEnabled()) return;
+        // Filter out inappropriate callbacks when switch is busy.
+        if (mIsSwitchBusy) return;
 
         if (isChecked) {
             startTether();
@@ -115,14 +118,14 @@
     void stopTether() {
         if (!isWifiApActivated()) return;
 
-        mSwitchBar.setEnabled(false);
+        mIsSwitchBusy = true;
         mConnectivityManager.stopTethering(TETHERING_WIFI);
     }
 
     void startTether() {
         if (isWifiApActivated()) return;
 
-        mSwitchBar.setEnabled(false);
+        mIsSwitchBusy = true;
         mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
                 mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
     }
@@ -159,6 +162,7 @@
 
     private void updateWifiSwitch() {
         mSwitchBar.setEnabled(!mDataSaverBackend.isDataSaverEnabled());
+        mIsSwitchBusy = false;
     }
 
     @Override
diff --git a/tests/robotests/src/com/android/settings/applications/contacts/ContactsStoragePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/contacts/ContactsStoragePreferenceControllerTest.java
index f55cbb4..f954b22 100644
--- a/tests/robotests/src/com/android/settings/applications/contacts/ContactsStoragePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/contacts/ContactsStoragePreferenceControllerTest.java
@@ -43,9 +43,9 @@
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.RawContacts.DefaultAccount.DefaultAccountAndState;
+import android.provider.Flags;
 
 import com.android.settings.R;
-import com.android.settings.flags.Flags;
 import com.android.settings.testutils.shadow.ShadowAuthenticationHelper;
 
 import org.junit.Before;
@@ -108,20 +108,20 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_ENABLE_CONTACTS_DEFAULT_ACCOUNT_IN_SETTINGS)
+    @EnableFlags(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED)
     public void getAvailabilityStatus_flagIsOn_shouldReturnAvailable() {
         assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
 
     @Test
-    @RequiresFlagsDisabled(Flags.FLAG_ENABLE_CONTACTS_DEFAULT_ACCOUNT_IN_SETTINGS)
+    @RequiresFlagsDisabled(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED)
     public void getAvailabilityStatus_flagIsOff_shouldReturnConditionallyUnavailable() {
         assertThat(mPreferenceController.getAvailabilityStatus()).isEqualTo(
                 CONDITIONALLY_UNAVAILABLE);
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_ENABLE_CONTACTS_DEFAULT_ACCOUNT_IN_SETTINGS)
+    @EnableFlags(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED)
     public void getAvailabilityStatus_illegalStateExceptionThrown_shouldReturnConditionallyUnavailable()
             throws Exception {
         when(mContentProviderClient.call(eq(QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD), any(),
@@ -135,7 +135,7 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_ENABLE_CONTACTS_DEFAULT_ACCOUNT_IN_SETTINGS)
+    @EnableFlags(Flags.FLAG_NEW_DEFAULT_ACCOUNT_API_ENABLED)
     public void getAvailabilityStatus_runtimeExceptionThrown_shouldReturnConditionallyUnavailable()
             throws Exception {
         when(mContentProviderClient.call(eq(QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD), any(),
@@ -179,6 +179,24 @@
     }
 
     @Test
+    public void getSummary_simAccountIsSetAsDefault_shouldReturnSimAccountSummary()
+            throws Exception {
+        Bundle bundle = new Bundle();
+        bundle.putInt(KEY_DEFAULT_ACCOUNT_STATE,
+                DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_SIM);
+        bundle.putString(Settings.ACCOUNT_TYPE, "SIM");
+        bundle.putString(Settings.ACCOUNT_NAME, "SIM");
+        when(mContentProviderClient.call(eq(QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD), any(),
+                any())).thenReturn(bundle);
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mResources.getString(eq(R.string.sim_card_label))).thenReturn("SIM");
+        mPreferenceController = new ContactsStoragePreferenceController(mContext,
+                CONTACTS_DEFAULT_ACCOUNT_PREFERENCE_KEY);
+
+        assertThat(mPreferenceController.getSummary()).isEqualTo("SIM");
+    }
+
+    @Test
     public void getSummary_googleAccountIsSetAsDefault_shouldReturnGoogleAccountTypeAndAccountName()
             throws Exception {
         Bundle bundle = new Bundle();
diff --git a/tests/robotests/src/com/android/settings/applications/contacts/ContactsStorageSettingsTest.java b/tests/robotests/src/com/android/settings/applications/contacts/ContactsStorageSettingsTest.java
index a8c86e1..4e873fb 100644
--- a/tests/robotests/src/com/android/settings/applications/contacts/ContactsStorageSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/contacts/ContactsStorageSettingsTest.java
@@ -32,7 +32,6 @@
 import static org.mockito.Mockito.when;
 
 import android.accounts.Account;
-import android.accounts.AccountManager;
 import android.app.settings.SettingsEnums;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
@@ -83,6 +82,8 @@
 
     private static final Account TEST_ACCOUNT3 = new Account("test@outlook.com", "type3");
 
+    private static final Account SIM_ACCOUNT = new Account("SIM", "SIM");
+
     @Rule
     public final MockitoRule mockito = MockitoJUnit.rule();
     @Spy
@@ -216,7 +217,9 @@
             throws Exception {
         Bundle currentDefaultAccount = new Bundle();
         currentDefaultAccount.putInt(KEY_DEFAULT_ACCOUNT_STATE,
-                DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_LOCAL);
+                DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_CLOUD);
+        currentDefaultAccount.putString(ContactsContract.Settings.ACCOUNT_NAME, TEST_ACCOUNT2.name);
+        currentDefaultAccount.putString(ContactsContract.Settings.ACCOUNT_TYPE, TEST_ACCOUNT2.type);
         when(mContentProviderClient.call(eq(QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD), any(),
                 any())).thenReturn(currentDefaultAccount);
         Bundle eligibleAccountBundle = new Bundle();
@@ -253,6 +256,14 @@
                 "test@samsung.com");
         assertThat(setAccountBundle.getString(ContactsContract.Settings.ACCOUNT_TYPE)).isEqualTo(
                 "type2");
+
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).startActivity(intentCaptor.capture());
+        Intent moveContactsIntent = intentCaptor.getValue();
+        assertThat(moveContactsIntent.getAction()).isEqualTo(
+                ContactsContract.RawContacts.DefaultAccount.ACTION_MOVE_CONTACTS_TO_DEFAULT_ACCOUNT);
+        assertThat(moveContactsIntent.getPackage()).isEqualTo(
+                "com.android.providers.contacts");
     }
 
     @Test
@@ -299,6 +310,32 @@
     }
 
     @Test
+    public void verifyAccountPreference_defaultAccountIsSimAccount_createSimAccountPreference()
+            throws Exception {
+        Bundle currentDefaultAccount = new Bundle();
+        currentDefaultAccount.putInt(KEY_DEFAULT_ACCOUNT_STATE,
+                DefaultAccountAndState.DEFAULT_ACCOUNT_STATE_SIM);
+        currentDefaultAccount.putString(ContactsContract.Settings.ACCOUNT_NAME, SIM_ACCOUNT.name);
+        currentDefaultAccount.putString(ContactsContract.Settings.ACCOUNT_TYPE, SIM_ACCOUNT.type);
+        when(mContentProviderClient.call(eq(QUERY_DEFAULT_ACCOUNT_FOR_NEW_CONTACTS_METHOD), any(),
+                any())).thenReturn(currentDefaultAccount);
+        Bundle eligibleAccountBundle = new Bundle();
+        eligibleAccountBundle.putParcelableArrayList(KEY_ELIGIBLE_DEFAULT_ACCOUNTS,
+                new ArrayList<>());
+        when(mContentProviderClient.call(eq(QUERY_ELIGIBLE_DEFAULT_ACCOUNTS_METHOD), any(),
+                any())).thenReturn(eligibleAccountBundle);
+
+        mContactsStorageSettings.refreshUI();
+
+        SelectorWithWidgetPreference simPreference = mScreen.findPreference(
+                String.valueOf(SIM_ACCOUNT.hashCode()));
+        assertThat(simPreference.getTitle()).isEqualTo("SIM");
+        assertThat(simPreference.getSummary()).isEqualTo("SIM");
+        assertThat(simPreference.getIcon()).isNotNull();
+        assertThat(simPreference.isChecked()).isTrue();
+    }
+
+    @Test
     public void searchIndexProvider_shouldIndexResource() {
         final List<SearchIndexableResource> indexRes =
                 ContactsStorageSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
diff --git a/tests/robotests/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModelTest.kt b/tests/robotests/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModelTest.kt
index c3f938c..6813d94 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModelTest.kt
+++ b/tests/robotests/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModelTest.kt
@@ -19,6 +19,7 @@
 import android.app.Application
 import android.bluetooth.BluetoothAdapter
 import android.graphics.Bitmap
+import android.media.AudioManager
 import androidx.test.core.app.ApplicationProvider
 import com.android.settings.bluetooth.domain.interactor.SpatialAudioInteractor
 import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout
@@ -46,7 +47,9 @@
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
 import org.mockito.Mock
+import org.mockito.Mockito.any
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
@@ -76,11 +79,21 @@
         val application = ApplicationProvider.getApplicationContext<Application>()
         featureFactory = FakeFeatureFactory.setupForTest()
 
+        `when`(
+            featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository(
+                eq(application), eq(bluetoothAdapter), any()
+            ))
+            .thenReturn(repository)
+        `when`(
+            featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor(
+                eq(application), any(AudioManager::class.java), any()
+            ))
+            .thenReturn(spatialAudioInteractor)
+
         underTest =
             BluetoothDeviceDetailsViewModel(
                 application,
-                repository,
-                spatialAudioInteractor,
+                bluetoothAdapter,
                 cachedDevice,
                 testScope.testScheduler)
     }
diff --git a/tests/robotests/src/com/android/settings/datausage/DataSaverScreenTest.kt b/tests/robotests/src/com/android/settings/datausage/DataSaverScreenTest.kt
new file mode 100644
index 0000000..08af4c0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datausage/DataSaverScreenTest.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.datausage
+
+import com.android.settings.flags.Flags
+import com.android.settingslib.preference.CatalystScreenTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class DataSaverScreenTest : CatalystScreenTestCase() {
+    override val preferenceScreenCreator = DataSaverScreen()
+    override val flagName
+        get() = Flags.FLAG_CATALYST_RESTRICT_BACKGROUND_PARENT_ENTRY
+
+    override fun migration() {}
+
+    @Test
+    fun key() {
+        assertThat(preferenceScreenCreator.key).isEqualTo(DataSaverScreen.KEY)
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/tether/TetherSettingsTest.java b/tests/robotests/src/com/android/settings/network/tether/TetherSettingsTest.java
index 4e0fb03..8c537e0 100644
--- a/tests/robotests/src/com/android/settings/network/tether/TetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/tether/TetherSettingsTest.java
@@ -54,7 +54,7 @@
 import androidx.preference.SwitchPreference;
 
 import com.android.settings.R;
-import com.android.settings.RestrictedSettingsFragment;
+import com.android.settings.dashboard.RestrictedDashboardFragment;
 import com.android.settings.wifi.tether.WifiTetherPreferenceController;
 import com.android.settingslib.RestrictedSwitchPreference;
 
@@ -130,14 +130,12 @@
     }
 
     @Test
-    @Config(shadows = ShadowRestrictedSettingsFragment.class)
+    @Config(shadows = ShadowRestrictedDashboardFragment.class)
     public void onCreate_isUiRestricted_doNotSetupViewModel() {
-        doNothing().when(mTetherSettings).addPreferencesFromResource(anyInt());
         when(mTetherSettings.isUiRestricted()).thenReturn(true);
 
         mTetherSettings.onCreate(null);
 
-        verify(mTetherSettings).addPreferencesFromResource(anyInt());
         verify(mTetherSettings, never()).setupViewModel();
     }
 
@@ -454,8 +452,8 @@
         }
     }
 
-    @Implements(RestrictedSettingsFragment.class)
-    public static final class ShadowRestrictedSettingsFragment {
+    @Implements(RestrictedDashboardFragment.class)
+    public static final class ShadowRestrictedDashboardFragment {
         @Implementation
         public void onCreate(Bundle icicle) {
             // do nothing
diff --git a/tests/robotests/src/com/android/settings/notification/app/BundleListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/BundleListPreferenceControllerTest.java
index 8b8c77e..a8de8ef 100644
--- a/tests/robotests/src/com/android/settings/notification/app/BundleListPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/BundleListPreferenceControllerTest.java
@@ -89,15 +89,6 @@
         mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
         mGroupList = new PreferenceCategory(mContext);
         mPreferenceScreen.addPreference(mGroupList);
-
-        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, PROMOTIONS_ID)).thenReturn(
-                new NotificationChannel(PROMOTIONS_ID, PROMOTIONS_ID, 2));
-        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, NEWS_ID)).thenReturn(
-                new NotificationChannel(NEWS_ID, NEWS_ID, 2));
-        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, SOCIAL_MEDIA_ID)).thenReturn(
-                new NotificationChannel(SOCIAL_MEDIA_ID, SOCIAL_MEDIA_ID, 2));
-        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, RECS_ID)).thenReturn(
-                new NotificationChannel(RECS_ID, RECS_ID, 2));
     }
 
     @Test
@@ -132,6 +123,14 @@
 
     @Test
     public void updateState() {
+        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, PROMOTIONS_ID)).thenReturn(
+                new NotificationChannel(PROMOTIONS_ID, PROMOTIONS_ID, 2));
+        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, NEWS_ID)).thenReturn(
+                new NotificationChannel(NEWS_ID, NEWS_ID, 2));
+        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, SOCIAL_MEDIA_ID)).thenReturn(
+                new NotificationChannel(SOCIAL_MEDIA_ID, SOCIAL_MEDIA_ID, 2));
+        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, RECS_ID)).thenReturn(
+                new NotificationChannel(RECS_ID, RECS_ID, 2));
         mController.updateState(mGroupList);
         assertThat(mGroupList.getPreferenceCount()).isEqualTo(4);
         assertThat(mGroupList.findPreference(PROMOTIONS_ID).getTitle()).isEqualTo(PROMOTIONS_ID);
@@ -142,19 +141,38 @@
     }
 
     @Test
-    public void updateState_updateChildren() {
+    public void updateState_noBundles() {
         mController.updateState(mGroupList);
-        assertThat(mGroupList.getPreferenceCount()).isEqualTo(4);
+        assertThat(mGroupList.getPreferenceCount()).isEqualTo(0);
+        assertThat(mGroupList.isVisible()).isFalse();
+    }
 
+    @Test
+    public void updateState_onlySomeBundlesUsed() {
         when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, PROMOTIONS_ID)).thenReturn(
                 new NotificationChannel(PROMOTIONS_ID, PROMOTIONS_ID, 2));
+        mController.updateState(mGroupList);
+        assertThat(mGroupList.getPreferenceCount()).isEqualTo(1);
+        assertThat(mGroupList.findPreference(PROMOTIONS_ID).getTitle()).isEqualTo(PROMOTIONS_ID);
+    }
+
+    @Test
+    public void updateState_noDuplicateChannelsOnReload() {
+        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, PROMOTIONS_ID)).thenReturn(
+                new NotificationChannel(PROMOTIONS_ID, PROMOTIONS_ID, 2));
+        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, NEWS_ID)).thenReturn(
+                new NotificationChannel(NEWS_ID, NEWS_ID, 2));
+        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, SOCIAL_MEDIA_ID)).thenReturn(
+                new NotificationChannel(SOCIAL_MEDIA_ID, SOCIAL_MEDIA_ID, 2));
+        when(mBackend.getChannel(mAppRow.pkg, mAppRow.uid, RECS_ID)).thenReturn(
+                new NotificationChannel(RECS_ID, RECS_ID, 2));
 
         mController.updateState(mGroupList);
         assertThat(mGroupList.getPreferenceCount()).isEqualTo(4);
+        mController.updateState(mGroupList);
+        assertThat(mGroupList.getPreferenceCount()).isEqualTo(4);
 
         assertThat(((PrimarySwitchPreference) mGroupList.findPreference(NEWS_ID)).isChecked())
                 .isEqualTo(false);
-        assertThat(((PrimarySwitchPreference) mGroupList.findPreference(NEWS_ID)).isChecked())
-                .isEqualTo(false);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceControllerTest.java
index b7af71b..d916dcf 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceControllerTest.java
@@ -44,6 +44,8 @@
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.service.notification.SystemZenRules;
 import android.service.notification.ZenModeConfig;
+import android.text.Spanned;
+import android.text.style.TtsSpan;
 import android.widget.TextView;
 
 import androidx.preference.PreferenceManager;
@@ -293,7 +295,14 @@
 
         assertThat(mPreference.isVisible()).isTrue();
         assertThat(mPreference.getTitle()).isEqualTo("1:00 AM - 3:00 PM");
-        assertThat(mPreference.getSummary()).isEqualTo("Mon - Tue, Thu");
+        Spanned summary = (Spanned) mPreference.getSummary();
+        assertThat(summary.toString()).isEqualTo("Mon - Tue, Thu");
+        TtsSpan[] ttsSpans = summary.getSpans(0, summary.length(), TtsSpan.class);
+        assertThat(ttsSpans).hasLength(1);
+        assertThat(ttsSpans[0].getType()).isEqualTo(TtsSpan.TYPE_TEXT);
+        assertThat(ttsSpans[0].getArgs().getString(TtsSpan.ARG_TEXT)).isEqualTo(
+                "Monday to Tuesday, Thursday");
+
         // Destination as written into the intent by SubSettingLauncher
         assertThat(
                 mPreference.getIntent().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
index 0982f26..32e3a61 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
@@ -147,8 +147,8 @@
     }
 
     @Test
-    public void onSwitchChanged_switchNotEnabled_doNothingForTethering() {
-        when(mSwitch.isEnabled()).thenReturn(false);
+    public void onSwitchChanged_switchIsBusy_doNothingForTethering() {
+        mController.mIsSwitchBusy = true;
 
         mController.onCheckedChanged(mSwitch, true);
 
diff --git a/tests/spa_unit/src/com/android/settings/network/SimOnboardingServiceTest.kt b/tests/spa_unit/src/com/android/settings/network/SimOnboardingServiceTest.kt
index 6f9029e..676ac48 100644
--- a/tests/spa_unit/src/com/android/settings/network/SimOnboardingServiceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/SimOnboardingServiceTest.kt
@@ -16,21 +16,55 @@
 
 package com.android.settings.network
 
+import android.content.Context
 import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import android.telephony.TelephonyManager
+import android.telephony.UiccCardInfo
+import android.telephony.UiccPortInfo
+import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.google.common.truth.Truth.assertThat
-import org.junit.Rule
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+
 
 @RunWith(AndroidJUnit4::class)
 class SimOnboardingServiceTest {
+    val simOnboardingService = SimOnboardingService()
+
+    private val mockTelephonyManager = mock<TelephonyManager> {
+        on { activeModemCount } doReturn 2
+        on { isMultiSimSupported } doReturn TelephonyManager.MULTISIM_ALLOWED
+        on { uiccCardsInfo } doReturn mepUiccCardInfoList
+    }
+
+    private val mockSubscriptionManager = mock<SubscriptionManager> {
+            on { activeSubscriptionInfoList } doReturn listOf(
+                SUB_INFO_1,
+                SUB_INFO_2
+            )
+            on { availableSubscriptionInfoList } doReturn listOf(
+                SUB_INFO_1,
+                SUB_INFO_2,
+                SUB_INFO_3,
+            )
+        }
+
+    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+        on { getSystemService(SubscriptionManager::class.java) } doReturn mockSubscriptionManager
+        on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+    }
 
     @Test
     fun addItemForRenaming_addItemWithNewName_findItem() {
-        val simOnboardingService = SimOnboardingService()
         val newName = "NewName"
-
         simOnboardingService.addItemForRenaming(SUB_INFO_1, newName)
 
         assertThat(simOnboardingService.renameMutableMap)
@@ -39,8 +73,6 @@
 
     @Test
     fun addItemForRenaming_sameNameAndItemNotInList_removeItem() {
-        val simOnboardingService = SimOnboardingService()
-
         simOnboardingService.addItemForRenaming(SUB_INFO_1, DISPLAY_NAME_1)
 
         assertThat(simOnboardingService.renameMutableMap)
@@ -49,7 +81,6 @@
 
     @Test
     fun addItemForRenaming_sameNameAndItemInList_removeItem() {
-        val simOnboardingService = SimOnboardingService()
         simOnboardingService.renameMutableMap[SUB_INFO_1.subscriptionId] = "NewName"
 
         simOnboardingService.addItemForRenaming(SUB_INFO_1, DISPLAY_NAME_1)
@@ -58,13 +89,205 @@
             .doesNotContainKey(SUB_INFO_1.subscriptionId)
     }
 
+    @Test
+    fun isDsdsConditionSatisfied_isMultiSimEnabled_returnFalse(){
+        simOnboardingService.initData(SUB_ID_3, context, {})
+
+        assertThat(simOnboardingService.isDsdsConditionSatisfied()).isFalse()
+    }
+
+    @Test
+    fun isDsdsConditionSatisfied_isNotMultiSimSupported_returnFalse() {
+        mockTelephonyManager.stub {
+            on { activeModemCount } doReturn 1
+            on {
+                isMultiSimSupported
+            } doReturn TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE
+        }
+        simOnboardingService.initData(SUB_ID_3, context, {})
+
+        assertThat(simOnboardingService.isDsdsConditionSatisfied()).isFalse()
+    }
+
+    @Test
+    fun isDsdsConditionSatisfied_mepAndOneActiveSim_returnTrue() = runBlocking {
+        mockTelephonyManager.stub {
+            on { activeModemCount } doReturn 1
+        }
+        simOnboardingService.initData(SUB_ID_3, context, {})
+        delay(100)
+
+        assertThat(simOnboardingService.isDsdsConditionSatisfied()).isTrue()
+    }
+
+    @Test
+    fun isDsdsConditionSatisfied_mepAndNoActiveSim_returnFalse() = runBlocking {
+        mockTelephonyManager.stub {
+            on { activeModemCount } doReturn 1
+        }
+        mockSubscriptionManager.stub {
+            on { activeSubscriptionInfoList } doReturn listOf()
+        }
+        simOnboardingService.initData(SUB_ID_3, context, {})
+        delay(100)
+
+        assertThat(simOnboardingService.isDsdsConditionSatisfied()).isFalse()
+    }
+
+    @Test
+    fun isDsdsConditionSatisfied_insertEsimAndOneActivePsimNoMep_returnTrue() = runBlocking {
+        mockTelephonyManager.stub {
+            on { getActiveModemCount() } doReturn 1
+            on { uiccCardsInfo } doReturn noMepUiccCardInfoList
+        }
+        simOnboardingService.initData(SUB_ID_3, context, {})
+        delay(100)
+
+        assertThat(simOnboardingService.isDsdsConditionSatisfied()).isTrue()
+    }
+
+    @Test
+    fun isDsdsConditionSatisfied_insertEsimAndNoPsimNoMep_returnFalse() = runBlocking {
+        mockTelephonyManager.stub {
+            on { getActiveModemCount() } doReturn 1
+            on { uiccCardsInfo } doReturn noMepUiccCardInfoList
+        }
+        mockSubscriptionManager.stub {
+            on { activeSubscriptionInfoList } doReturn listOf()
+        }
+        simOnboardingService.initData(SUB_ID_3, context, {})
+        delay(100)
+
+        assertThat(simOnboardingService.isDsdsConditionSatisfied()).isFalse()
+    }
+
+    @Test
+    fun isDsdsConditionSatisfied_insertPsimAndOneActiveEsimNoMep_returnTrue() = runBlocking {
+        mockTelephonyManager.stub {
+            on { getActiveModemCount() } doReturn 1
+            on { uiccCardsInfo } doReturn noMepUiccCardInfoList
+        }
+        mockSubscriptionManager.stub {
+            on { activeSubscriptionInfoList } doReturn listOf(
+                SUB_INFO_2
+            )
+        }
+        simOnboardingService.initData(SUB_ID_1, context, {})
+        delay(100)
+
+        assertThat(simOnboardingService.isDsdsConditionSatisfied()).isTrue()
+    }
+
+    @Test
+    fun isDsdsConditionSatisfied_insertPsimAndNoEsimNoMep_returnFalse() = runBlocking {
+        mockTelephonyManager.stub {
+            on { getActiveModemCount() } doReturn 1
+            on { uiccCardsInfo } doReturn noMepUiccCardInfoList
+        }
+        mockSubscriptionManager.stub {
+            on { activeSubscriptionInfoList } doReturn listOf()
+        }
+        simOnboardingService.initData(SUB_ID_1, context, {})
+        delay(100)
+
+        assertThat(simOnboardingService.isDsdsConditionSatisfied()).isFalse()
+    }
+
     private companion object {
         const val SUB_ID_1 = 1
+        const val SUB_ID_2 = 2
+        const val SUB_ID_3 = 3
+        const val SUB_ID_4 = 4
         const val DISPLAY_NAME_1 = "Sub 1"
 
         val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
             setId(SUB_ID_1)
             setDisplayName(DISPLAY_NAME_1)
         }.build()
+
+        val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(SUB_ID_2)
+            setEmbedded(true)
+        }.build()
+
+        val SUB_INFO_3: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(SUB_ID_3)
+            setEmbedded(true)
+        }.build()
+
+        val SUB_INFO_4: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(SUB_ID_4)
+        }.build()
+
+        private const val REMOVABLE_CARD_ID_1: Int = 25
+        private const val REMOVABLE_CARD_ID_2: Int = 26
+        private const val EUICC_CARD_ID_3: Int = 27
+        private const val EUICC_CARD_ID_4: Int = 28
+
+        val noMepUiccCardInfoList: List<UiccCardInfo> = listOf(
+            createUiccCardInfo(
+                isEuicc = true,
+                cardId = EUICC_CARD_ID_3,
+                physicalSlotIndex = 0,
+                isRemovable = false,
+                isMultipleEnabledProfileSupported = false,
+                logicalSlotIndex = -1,
+                portIndex = -1
+            ),
+            createUiccCardInfo(
+                isEuicc = false,
+                cardId = REMOVABLE_CARD_ID_1,
+                physicalSlotIndex = 1,
+                isRemovable = true,
+                isMultipleEnabledProfileSupported = false,
+                logicalSlotIndex = -1,
+                portIndex = -1
+            )
+        )
+        val mepUiccCardInfoList: List<UiccCardInfo> = listOf(
+            createUiccCardInfo(
+                isEuicc = true,
+                cardId = EUICC_CARD_ID_3,
+                physicalSlotIndex = 0,
+                isRemovable = false,
+                logicalSlotIndex = -1,
+                portIndex = -1
+            ),
+            createUiccCardInfo(
+                isEuicc = false,
+                cardId = REMOVABLE_CARD_ID_1,
+                physicalSlotIndex = 1,
+                isRemovable = true,
+                logicalSlotIndex = -1,
+                portIndex = -1
+            )
+        )
+
+        private fun createUiccCardInfo(
+            isEuicc: Boolean,
+            cardId: Int,
+            physicalSlotIndex: Int,
+            isRemovable: Boolean,
+            logicalSlotIndex: Int,
+            portIndex: Int,
+            isMultipleEnabledProfileSupported:Boolean = true,
+        ): UiccCardInfo {
+            return UiccCardInfo(
+                isEuicc,  /* isEuicc */
+                cardId,  /* cardId */
+                null,  /* eid */
+                physicalSlotIndex,  /* physicalSlotIndex */
+                isRemovable,  /* isRemovable */
+                isMultipleEnabledProfileSupported,  /* isMultipleEnabledProfileSupported */
+                listOf(
+                    UiccPortInfo(
+                        "123451234567890",  /* iccId */
+                        portIndex,  /* portIdx */
+                        logicalSlotIndex,  /* logicalSlotIdx */
+                        true /* isActive */
+                    )
+                )
+            )
+        }
     }
 }
\ No newline at end of file
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/UiccSlotRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/UiccSlotRepositoryTest.kt
index 96aa151..911e1d1 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/UiccSlotRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/UiccSlotRepositoryTest.kt
@@ -44,7 +44,7 @@
                 )
         }
 
-        val result = repository.anyRemovablePhysicalSimEnabled()
+        val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
 
         assertThat(result).isFalse()
     }
@@ -61,7 +61,7 @@
                 )
         }
 
-        val result = repository.anyRemovablePhysicalSimEnabled()
+        val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
 
         assertThat(result).isFalse()
     }
@@ -78,7 +78,7 @@
                 )
         }
 
-        val result = repository.anyRemovablePhysicalSimEnabled()
+        val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
 
         assertThat(result).isTrue()
     }
@@ -95,7 +95,7 @@
                 )
         }
 
-        val result = repository.anyRemovablePhysicalSimEnabled()
+        val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
 
         assertThat(result).isTrue()
     }
@@ -116,7 +116,7 @@
                 )
         }
 
-        val result = repository.anyRemovablePhysicalSimEnabled()
+        val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
 
         assertThat(result).isFalse()
     }
@@ -137,13 +137,13 @@
                 )
         }
 
-        val result = repository.anyRemovablePhysicalSimEnabled()
+        val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
 
         assertThat(result).isTrue()
     }
 
     @Test
-    fun anyRemovablePhysicalSimEnabled_activePsim_returnsTrue() {
+    fun anyRemovablePhysicalSimSlotActiveAndInserted_activePsim_returnsTrue() {
         mockTelephonyManager.stub {
             on { uiccSlotsInfo } doReturn
                 arrayOf(
@@ -152,13 +152,13 @@
                 )
         }
 
-        val result = repository.anyRemovablePhysicalSimEnabled()
+        val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
 
         assertThat(result).isTrue()
     }
 
     @Test
-    fun anyRemovablePhysicalSimEnabled_inactivePsim_returnsFalse() {
+    fun anyRemovablePhysicalSimSlotActiveAndInserted_inactivePsim_returnsFalse() {
         mockTelephonyManager.stub {
             on { uiccSlotsInfo } doReturn
                 arrayOf(
@@ -167,13 +167,13 @@
                 )
         }
 
-        val result = repository.anyRemovablePhysicalSimEnabled()
+        val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
 
         assertThat(result).isFalse()
     }
 
     @Test
-    fun anyRemovablePhysicalSimEnabled_activeEsimAndActivePsim_returnsTrue() {
+    fun anyRemovablePhysicalSimSlotActiveAndInserted_activeEsimAndActivePsim_returnsTrue() {
         mockTelephonyManager.stub {
             on { uiccSlotsInfo } doReturn
                 arrayOf(
@@ -184,13 +184,13 @@
                 )
         }
 
-        val result = repository.anyRemovablePhysicalSimEnabled()
+        val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
 
         assertThat(result).isTrue()
     }
 
     @Test
-    fun anyRemovablePhysicalSimEnabled_activeEsimAndInactivePsim_returnsFalse() {
+    fun anyRemovablePhysicalSimSlotActiveAndInserted_activeEsimAndInactivePsim_returnsFalse() {
         mockTelephonyManager.stub {
             on { uiccSlotsInfo } doReturn
                 arrayOf(
@@ -201,16 +201,16 @@
                 )
         }
 
-        val result = repository.anyRemovablePhysicalSimEnabled()
+        val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
 
         assertThat(result).isFalse()
     }
 
     @Test
-    fun anyRemovablePhysicalSimEnabled_uiccSlotInfoIsNull_returnsFalse() {
+    fun anyRemovablePhysicalSimSlotActiveAndInserted_uiccSlotInfoIsNull_returnsFalse() {
         mockTelephonyManager.stub { on { uiccSlotsInfo } doReturn arrayOf(null) }
 
-        val result = repository.anyRemovablePhysicalSimEnabled()
+        val result = repository.anyRemovablePhysicalSimSlotActiveAndInserted()
 
         assertThat(result).isFalse()
     }
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index be43f8e..07df3c8 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -26,11 +26,14 @@
         "androidx.test.ext.junit",
         "androidx.test.rules",
         "flag-junit",
+        "kotlin-test",
+        "mockito-kotlin2",
         "mockito-target-minus-junit4",
         "platform-test-annotations",
         "platform-test-rules",
         "truth",
         "kotlinx_coroutines_test",
+        "SettingsLibPreference-testutils",
         "Settings-testutils2",
         "servicestests-utils",
         // Don't add SettingsLib libraries here - you can use them directly as they are in the
diff --git a/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java b/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java
index 342212a..4c07555 100644
--- a/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java
+++ b/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java
@@ -331,9 +331,7 @@
                 .isEqualTo(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName));
     }
 
-    @Test
-    public void testGetUserMinAspectRatioEntry_enabledFullscreenOverride_returnsFullscreen() {
-        setIsOverrideToFullscreenEnabled(true);
+    private void assertUnsetIsFullscreen() {
         // Fullscreen option is pre-selected
         assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName))
                 .isEqualTo(ResourcesUtils.getResourcesString(
@@ -347,9 +345,7 @@
                         "user_aspect_ratio_app_default"));
     }
 
-    @Test
-    public void testGetUserMinAspectRatioEntry_disabledFullscreenOverride_returnsUnchanged() {
-        setIsOverrideToFullscreenEnabled(false);
+    private void assertUnsetIsAppDefault() {
         // Fullscreen option is not pre-selected
         assertThat(getUserMinAspectRatioEntry(USER_MIN_ASPECT_RATIO_UNSET, mPackageName))
                 .isEqualTo(ResourcesUtils.getResourcesString(
@@ -358,9 +354,43 @@
     }
 
     @Test
-    public void testIsOverrideToFullscreenEnabled_returnsTrue()
+    public void testGetUserMinAspectRatioEntry_enabledFullscreenCompatChange_returnsFullscreen() {
+        setIsOverrideToFullscreenEnabledBecauseCompatChange(true);
+        assertUnsetIsFullscreen();
+    }
+
+    @Test
+    public void testGetUserMinAspectRatioEntry_enabledFullscreenOverrideUniRes_returnsFullscreen() {
+        setIsOverrideToFullscreenEnabledBecauseUniversalResizeable(true);
+        assertUnsetIsFullscreen();
+    }
+
+    @Test
+    public void testGetUserMinAspectRatioEntry_noFullscreenCompatChange_returnsUnchanged() {
+        setIsOverrideToFullscreenEnabledBecauseCompatChange(false);
+        assertUnsetIsAppDefault();
+    }
+
+    @Test
+    public void testGetUserMinAspectRatioEntry_noFullscreenUnivRes_returnsUnchanged() {
+        setIsOverrideToFullscreenEnabledBecauseUniversalResizeable(false);
+        assertUnsetIsAppDefault();
+    }
+
+    @Test
+    public void testIsOverrideToFullscreenEnabledCompatChange_returnsTrue()
             throws PackageManager.NameNotFoundException {
-        setIsOverrideToFullscreenEnabled(true);
+        setIsOverrideToFullscreenEnabledBecauseCompatChange(true);
+        assertTrue(mUtils.isOverrideToFullscreenEnabled(mPackageName, mContext.getUserId()));
+
+        mockProperty(PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE, true);
+        assertTrue(mUtils.isOverrideToFullscreenEnabled(mPackageName, mContext.getUserId()));
+    }
+
+    @Test
+    public void testIsOverrideToFullscreenEnabledUnivRes_returnsTrue()
+            throws PackageManager.NameNotFoundException {
+        setIsOverrideToFullscreenEnabledBecauseUniversalResizeable(true);
         assertTrue(mUtils.isOverrideToFullscreenEnabled(mPackageName, mContext.getUserId()));
 
         mockProperty(PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE, true);
@@ -370,7 +400,7 @@
     @Test
     public void testIsOverrideToFullscreenEnabled_optOut_returnsFalse()
             throws PackageManager.NameNotFoundException {
-        setIsOverrideToFullscreenEnabled(true);
+        setIsOverrideToFullscreenEnabledBecauseCompatChange(true);
         mockProperty(PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE, false);
         assertFalse(mUtils.isOverrideToFullscreenEnabled(mPackageName, mContext.getUserId()));
     }
@@ -382,6 +412,12 @@
     }
 
     @Test
+    public void testIsOverrideToFullscreenEnabledUnivRes_flagDisabled_returnsFalse() {
+        mUtils.setFullscreenCompatChange(true);
+        assertFalse(mUtils.isOverrideToFullscreenEnabled(mPackageName, mContext.getUserId()));
+    }
+
+    @Test
     public void testIsOverrideToFullscreenEnabled_optionDisabled_returnsFalse() {
         mUtils.setFullscreenCompatChange(true);
         when(mUtils.hasAspectRatioOption(USER_MIN_ASPECT_RATIO_FULLSCREEN, mPackageName))
@@ -389,7 +425,7 @@
         assertFalse(mUtils.isOverrideToFullscreenEnabled(mPackageName, mContext.getUserId()));
     }
 
-    private void setIsOverrideToFullscreenEnabled(boolean enabled) {
+    private void setIsOverrideToFullscreenEnabledBecauseCompatChange(boolean enabled) {
         if (enabled) {
             mSetFlagsRule.enableFlags(FLAG_USER_MIN_ASPECT_RATIO_APP_DEFAULT);
             mUtils = new FakeUserAspectRatioManager(mContext, mIPm);
@@ -399,6 +435,16 @@
                 .thenReturn(enabled);
     }
 
+    private void setIsOverrideToFullscreenEnabledBecauseUniversalResizeable(boolean enabled) {
+        if (enabled) {
+            mSetFlagsRule.enableFlags(FLAG_USER_MIN_ASPECT_RATIO_APP_DEFAULT);
+            mUtils = new FakeUserAspectRatioManager(mContext, mIPm);
+        }
+        mUtils.setUniversalResizeable(enabled);
+        when(mUtils.hasAspectRatioOption(USER_MIN_ASPECT_RATIO_FULLSCREEN, mPackageName))
+                .thenReturn(enabled);
+    }
+
     private void enableAllDefaultAspectRatioOptions() {
         final int[] aspectRatioOptions = new int[] {
                 USER_MIN_ASPECT_RATIO_UNSET,
@@ -457,6 +503,7 @@
 
     private static class FakeUserAspectRatioManager extends UserAspectRatioManager {
         private boolean mFullscreenCompatChange = false;
+        private boolean mIsUniversalResizeable = false;
 
         private FakeUserAspectRatioManager(@NonNull Context context, IPackageManager pm) {
             super(context, pm);
@@ -467,8 +514,17 @@
             return mFullscreenCompatChange;
         }
 
+        @Override
+        boolean isUniversalResizeable(String pkgName, int userId) {
+            return mIsUniversalResizeable;
+        }
+
         void setFullscreenCompatChange(boolean enabled) {
             mFullscreenCompatChange = enabled;
         }
+
+        void setUniversalResizeable(boolean enabled) {
+            mIsUniversalResizeable = enabled;
+        }
     }
 }
diff --git a/tests/unit/src/com/android/settings/language/LanguageSettingScreenTest.kt b/tests/unit/src/com/android/settings/language/LanguageSettingScreenTest.kt
new file mode 100644
index 0000000..7b519a2
--- /dev/null
+++ b/tests/unit/src/com/android/settings/language/LanguageSettingScreenTest.kt
@@ -0,0 +1,46 @@
+/*
+ * 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.language
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.ContextWrapper
+import android.content.pm.PackageManager
+import android.content.res.Resources
+import com.android.settings.Settings.LanguageSettingsActivity
+import com.android.settings.flags.Flags
+import com.android.settingslib.preference.CatalystScreenTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert
+import org.junit.Test
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.stub
+
+class LanguageSettingScreenTest: CatalystScreenTestCase() {
+    override val preferenceScreenCreator = LanguageSettingScreen()
+
+    override val flagName: String
+        get() = Flags.FLAG_CATALYST_LANGUAGE_SETTING
+
+    @Test
+    fun key() {
+        assertThat(preferenceScreenCreator.key).isEqualTo(LanguageSettingScreen.KEY)
+    }
+
+    override fun migration() {}
+}