Snap for 11420186 from ca4565083f89c2bf5b0757a726bbb6f04093ecce to 24Q2-release

Change-Id: I8313be7be164bd6b6f9de9e4290a5765681d1f54
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 96b798a..e4ed275 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -802,6 +802,11 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".network.SimOnboardingActivity"
+            android:exported="false"
+            android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
+            android:theme="@style/Theme.SpaLib.BottomSheetDialog"/>
+
         <activity android:name=".network.telephony.ToggleSubscriptionDialogActivity"
                   android:exported="false"
                   android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
@@ -4404,9 +4409,12 @@
         <activity android:name=".applications.credentials.CredentialsPickerActivity"
                 android:excludeFromRecents="true"
                 android:launchMode="singleInstance"
-                android:exported="false">
-            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
-                       android:value="com.android.settings.applications.credentials.DefaultCombinedPicker" />
+                android:exported="true">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.REQUEST_SET_AUTOFILL_SERVICE" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="package" />
+            </intent-filter>
         </activity>
 
         <activity
@@ -4551,19 +4559,6 @@
                 android:exported="false">
         </activity>
 
-        <activity android:name=".applications.autofill.AutofillPickerTrampolineActivity"
-                android:theme="@android:style/Theme.NoDisplay"
-                android:excludeFromRecents="true"
-                android:launchMode="singleInstance"
-                android:exported="true"
-                android:label="@string/autofill_app">
-            <intent-filter android:priority="1">
-                <action android:name="android.settings.REQUEST_SET_AUTOFILL_SERVICE" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="package" />
-            </intent-filter>
-        </activity>
-
         <activity android:name="Settings$AdvancedConnectedDeviceActivity"
                   android:exported="true"
                   android:label="@string/connected_device_connections_title">
diff --git a/res/values/config.xml b/res/values/config.xml
index 433620d..9d71671 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -709,7 +709,7 @@
     <bool name="default_allow_sensitive_lockscreen_content">true</bool>
 
     <!-- Whether to enable the app battery usage list page feature. -->
-    <bool name="config_app_battery_usage_list_enabled">true</bool>
+    <bool name="config_app_battery_usage_list_enabled">false</bool>
 
     <!-- Whether sim related information is visible to the end user. -->
     <bool name="config_show_sim_info">true</bool>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 965daf6..7291fad 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1269,7 +1269,7 @@
     <!-- Header in hide Private Space settings page to access Private Space when hidden. [CHAR LIMIT=60] -->
     <string name="privatespace_access_header">Access private space when hidden</string>
     <!-- Text in hide Private Space settings page on how to search Private Space when hidden. [CHAR LIMIT=60] -->
-    <string name="privatespace_search_description">From your apps list, enter \'private space\' in the search bar</string>
+    <string name="privatespace_search_description">From your apps list, enter \"private space\" in the search bar</string>
     <!-- Text in hide Private Space settings page to tap on Private Space tile. [CHAR LIMIT=60] -->
     <string name="privatespace_tap_tile_description">Tap the private space tile</string>
     <!-- Text in hide Private Space settings page to Unlock Private Space. [CHAR LIMIT=60] -->
@@ -1373,18 +1373,6 @@
     <!-- Header for private space choose your pattern screen [CHAR LIMIT=40] -->
     <string name="private_space_choose_your_pattern_header">Set a pattern for your private space</string>
 
-    <!-- TODO(b/309950257): Remove below strings once QSTIle fulfillment is complete. -->
-    <!-- Header in hide Private Space settings page to unhide Private Space. [CHAR LIMIT=90] -->
-    <string name="privatespace_unhide_header">To show private space (Not final UX)</string>
-    <!-- Text in hide Private Space settings page on how to open Private Space setting. [CHAR LIMIT=NONE] -->
-    <string name="privatespace_open_settings">Open the Settings App</string>
-    <!-- Text in hide Private Space settings page on how to open Private Space setting. [CHAR LIMIT=NONE] -->
-    <string name="privatespace_tap_settings">Tap on Security &amp; privacy > private space > Hide private space when locked</string>
-    <!-- Text in hide Private Space settings page to off hide toggle. [CHAR LIMIT=90] -->
-    <string name="privatespace_turnoff_hide">Turn off \‘Hide private space when locked\’ toggle</string>
-    <!-- Note in hide Private Space settings page to inform that this is a development feature. [CHAR LIMIT=NONE] -->
-    <string name="privatespace_development_note">Note to Googlers: The development of this feature is still in progress</string>
-
     <!-- Text shown when "Add fingerprint" button is disabled -->
     <string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string>
     <!-- Text shown when users has enrolled a maximum number of fingerprints [CHAR LIMIT=NONE] -->
@@ -7318,7 +7306,7 @@
     <!-- Title for setting tile leading to saved autofill passwords, autofill, and account settings [CHAR LIMIT=40]-->
     <string name="account_dashboard_title">Passwords &amp; accounts</string>
     <!-- Summary for setting tile leading to saved autofill passwords, autofill, and account settings [CHAR LIMIT=NONE]-->
-    <string name="account_dashboard_default_summary">Saved passwords, autofill, synced accounts</string>
+    <string name="account_dashboard_default_summary">Suggestions for sign-in &amp; autofill</string>
     <!-- Title for setting tile leading to setting UI which allows user set default app to
     handle actions such as open web page, making phone calls, default SMS apps [CHAR  LIMIT=40]-->
     <string name="app_default_dashboard_title">Default apps</string>
@@ -10785,8 +10773,8 @@
     <string name="autofill_passwords">Passwords</string>
     <!-- Preference category for showing autofill and credman services with saved credentials. [CHAR LIMIT=60] -->
     <string name="credman_chosen_app_title">Preferred service</string>
-    <!-- Preference category for showing additional credential providers. [CHAR LIMIT=60] -->
-    <string name="credman_credentials">Additional providers</string>
+    <!-- Preference category for showing additional credential services. [CHAR LIMIT=60] -->
+    <string name="credman_credentials">Additional services</string>
     <!-- Summary for passwords settings that shows how many passwords are saved for each autofill
          service. [CHAR LIMIT=NONE] -->
     <string name="autofill_passwords_count">{count, plural,
@@ -10831,7 +10819,7 @@
     </string>
 
     <!-- Title of the screen where the user picks a provider. [CHAR_LIMIT=NONE] -->
-    <string name="credman_picker_title">Passwords, passkeys, and data services</string>
+    <string name="credman_picker_title">Preferred service for passwords, passkeys &amp; autofill</string>
 
     <!-- Title of the warning dialog for disabling the credential provider. [CHAR_LIMIT=NONE] -->
     <string name="credman_confirmation_message_title">Turn off %1$s\?</string>
@@ -10848,6 +10836,9 @@
         ]]>
     </string>
 
+    <!-- Title for setting tile leading to saved autofill passwords, passkeys, autofill, and account settings [CHAR LIMIT=40]-->
+    <string name="account_dashboard_title_with_passkeys">Passwords, passkeys &amp; autofill</string>
+
     <!-- Message of the warning dialog for disabling the credential provider (new strings for 24Q3). [CHAR_LIMIT=NONE] -->
     <string name="credman_confirmation_message_new_ui">
         <![CDATA[
@@ -12891,4 +12882,4 @@
 
     <!-- Authority of the content provider that support methods restartPhoneProcess and restartRild. Will be overlaid by OEM.-->
     <string name="reset_telephony_stack_content_provider_authority" translatable="false"></string>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/res/xml/accounts_dashboard_settings_credman.xml b/res/xml/accounts_dashboard_settings_credman.xml
index 7266bda..08377c9 100644
--- a/res/xml/accounts_dashboard_settings_credman.xml
+++ b/res/xml/accounts_dashboard_settings_credman.xml
@@ -18,7 +18,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="user_and_account_settings_screen"
-    android:title="@string/account_dashboard_title"
+    android:title="@string/account_dashboard_title_with_passkeys"
     settings:keywords="@string/keywords_accounts">
 
     <PreferenceCategory
diff --git a/res/xml/accounts_personal_dashboard_settings_credman.xml b/res/xml/accounts_personal_dashboard_settings_credman.xml
index 9473e17..16ab31b 100644
--- a/res/xml/accounts_personal_dashboard_settings_credman.xml
+++ b/res/xml/accounts_personal_dashboard_settings_credman.xml
@@ -19,7 +19,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="user_and_account_settings_screen"
-    android:title="@string/account_dashboard_title"
+    android:title="@string/account_dashboard_title_with_passkeys"
     settings:keywords="@string/keywords_accounts">
 
     <PreferenceCategory
diff --git a/res/xml/accounts_private_dashboard_settings_credman.xml b/res/xml/accounts_private_dashboard_settings_credman.xml
index 54db839..c0b12b5 100644
--- a/res/xml/accounts_private_dashboard_settings_credman.xml
+++ b/res/xml/accounts_private_dashboard_settings_credman.xml
@@ -19,7 +19,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="user_and_account_settings_screen"
-    android:title="@string/account_dashboard_title"
+    android:title="@string/account_dashboard_title_with_passkeys"
     settings:keywords="@string/keywords_accounts">
 
     <PreferenceCategory
diff --git a/res/xml/accounts_work_dashboard_settings_credman.xml b/res/xml/accounts_work_dashboard_settings_credman.xml
index d649940..44bdb52 100644
--- a/res/xml/accounts_work_dashboard_settings_credman.xml
+++ b/res/xml/accounts_work_dashboard_settings_credman.xml
@@ -19,7 +19,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="user_and_account_settings_screen"
-    android:title="@string/account_dashboard_title"
+    android:title="@string/account_dashboard_title_with_passkeys"
     settings:keywords="@string/keywords_accounts">
 
     <PreferenceCategory
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index e62f5c0..1af8a8c 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
+<!-- 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.
@@ -51,6 +51,13 @@
         settings:keywords="@string/keywords_battery_saver"
         settings:controller="com.android.settings.fuelgauge.BatterySaverController" />
 
+    <Preference
+        android:fragment="com.android.settings.fuelgauge.SmartBatterySettings"
+        android:key="smart_battery_manager"
+        android:title="@string/smart_battery_manager_title"
+        settings:controller="com.android.settings.fuelgauge.batterytip.BatteryManagerPreferenceController"
+        settings:keywords="@string/keywords_battery_adaptive_preferences" />
+
     <SwitchPreferenceCompat
         android:key="battery_percentage"
         android:title="@string/battery_percentage"
diff --git a/res/xml/privatespace_hide_locked.xml b/res/xml/privatespace_hide_locked.xml
index f26d207..f453d75 100644
--- a/res/xml/privatespace_hide_locked.xml
+++ b/res/xml/privatespace_hide_locked.xml
@@ -34,33 +34,27 @@
         android:selectable="false"
         settings:searchable="false" />
 
-        <Preference
-        android:key="private_space_note"
-        android:summary="@string/privatespace_development_note"
-        android:selectable="false"
-        settings:searchable="false" />
-
     <PreferenceCategory
-        android:title="@string/privatespace_unhide_header">
+        android:title="@string/privatespace_access_header">
 
         <Preference
         android:key="search_when_locked_footer"
         android:icon="@drawable/counter_1_24dp"
-        android:title="@string/privatespace_open_settings"
+        android:title="@string/privatespace_search_description"
         android:selectable="false"
         settings:searchable="false" />
 
         <Preference
             android:key="tap_tile_footer"
             android:icon="@drawable/counter_2_24dp"
-            android:title="@string/privatespace_tap_settings"
+            android:title="@string/privatespace_tap_tile_description"
             android:selectable="false"
             settings:searchable="false" />
 
         <Preference
-            android:key="turn_off_footer"
+            android:key="unlock_profile_footer"
             android:icon="@drawable/counter_3_24dp"
-            android:title="@string/privatespace_turnoff_hide"
+            android:title="@string/privatespace_unlock_description"
             android:selectable="false"
             settings:searchable="false" />
 
diff --git a/res/xml/top_level_settings.xml b/res/xml/top_level_settings.xml
index d050a1f..31c6af3 100644
--- a/res/xml/top_level_settings.xml
+++ b/res/xml/top_level_settings.xml
@@ -180,7 +180,7 @@
         android:icon="@drawable/ic_settings_accounts"
         android:key="top_level_accounts"
         android:order="-10"
-        android:title="@string/account_dashboard_title"
+        android:title="@string/account_dashboard_title_with_passkeys"
         android:summary="@string/summary_placeholder"
         settings:highlightableMenuKey="@string/menu_key_accounts"
         settings:controller="com.android.settings.accounts.TopLevelAccountEntryPreferenceController"/>
diff --git a/src/com/android/settings/accessibility/HearingDevicePairingFragment.java b/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
index 78f5b4c..0b762f3 100644
--- a/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
+++ b/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
@@ -17,6 +17,7 @@
 package com.android.settings.accessibility;
 
 import static android.app.Activity.RESULT_OK;
+import static android.bluetooth.BluetoothGatt.GATT_SUCCESS;
 import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
 
 import android.app.settings.SettingsEnums;
@@ -191,7 +192,7 @@
     public void onDeviceBondStateChanged(@NonNull CachedBluetoothDevice cachedDevice,
             int bondState) {
         if (DEBUG) {
-            Log.d(TAG, "onDeviceBondStateChanged: " + cachedDevice.getName() + ", state = "
+            Log.d(TAG, "onDeviceBondStateChanged: " + cachedDevice.getDevice() + ", state = "
                     + bondState);
         }
         if (bondState == BluetoothDevice.BOND_BONDED) {
@@ -275,13 +276,13 @@
         }
         mDevicePreferenceMap.put(cachedDevice, preference);
         if (DEBUG) {
-            Log.d(TAG, "Add device. device: " + cachedDevice);
+            Log.d(TAG, "Add device. device: " + cachedDevice.getDevice());
         }
     }
 
     void removeDevice(CachedBluetoothDevice cachedDevice) {
         if (DEBUG) {
-            Log.d(TAG, "removeDevice: " + cachedDevice);
+            Log.d(TAG, "removeDevice: " + cachedDevice.getDevice());
         }
         BluetoothDevicePreference preference = mDevicePreferenceMap.remove(cachedDevice);
         if (mAvailableHearingDeviceGroup != null && preference != null) {
@@ -328,10 +329,15 @@
         CachedBluetoothDevice cachedDevice = mCachedDeviceManager.findDevice(device);
         if (cachedDevice == null) {
             cachedDevice = mCachedDeviceManager.addDevice(device);
+        } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
+            if (DEBUG) {
+                Log.d(TAG, "Skip this device, already bonded: " + cachedDevice.getDevice());
+            }
+            return;
         }
         if (cachedDevice.getHearingAidInfo() == null) {
             if (DEBUG) {
-                Log.d(TAG, "Set hearing aid info on device: " + cachedDevice);
+                Log.d(TAG, "Set hearing aid info on device: " + cachedDevice.getDevice());
             }
             cachedDevice.setHearingAidInfo(new HearingAidInfo.Builder().build());
         }
@@ -449,7 +455,7 @@
 
     void discoverServices(CachedBluetoothDevice cachedDevice) {
         if (DEBUG) {
-            Log.d(TAG, "connectGattToCheckCompatibility, device: " + cachedDevice);
+            Log.d(TAG, "connectGattToCheckCompatibility, device: " + cachedDevice.getDevice());
         }
         BluetoothGatt gatt = cachedDevice.getDevice().connectGatt(getContext(), false,
                 new BluetoothGattCallback() {
@@ -459,26 +465,36 @@
                         super.onConnectionStateChange(gatt, status, newState);
                         if (DEBUG) {
                             Log.d(TAG, "onConnectionStateChange, status: " + status + ", newState: "
-                                    + newState + ", device: " + cachedDevice);
+                                    + newState + ", device: " + cachedDevice.getDevice());
                         }
-                        if (newState == BluetoothProfile.STATE_CONNECTED) {
+                        if (status == GATT_SUCCESS
+                                && newState == BluetoothProfile.STATE_CONNECTED) {
                             gatt.discoverServices();
+                        } else {
+                            gatt.disconnect();
+                            mConnectingGattList.remove(gatt);
                         }
                     }
 
                     @Override
                     public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                         super.onServicesDiscovered(gatt, status);
-                        boolean isCompatible = gatt.getService(BluetoothUuid.HEARING_AID.getUuid())
-                                != null
-                                || gatt.getService(BluetoothUuid.HAS.getUuid()) != null;
                         if (DEBUG) {
-                            Log.d(TAG,
-                                    "onServicesDiscovered, compatible with Android: " + isCompatible
-                                            + ", device: " + cachedDevice);
+                            Log.d(TAG, "onServicesDiscovered, status: " + status + ", device: "
+                                    + cachedDevice.getDevice());
                         }
-                        if (isCompatible) {
-                            addDevice(cachedDevice);
+                        if (status == GATT_SUCCESS) {
+                            if (gatt.getService(BluetoothUuid.HEARING_AID.getUuid()) != null
+                                    || gatt.getService(BluetoothUuid.HAS.getUuid()) != null) {
+                                if (DEBUG) {
+                                    Log.d(TAG, "compatible with Android, device: "
+                                            + cachedDevice.getDevice());
+                                }
+                                addDevice(cachedDevice);
+                            }
+                        } else {
+                            gatt.disconnect();
+                            mConnectingGattList.remove(gatt);
                         }
                     }
                 });
diff --git a/src/com/android/settings/applications/credentials/CombinedProviderInfo.java b/src/com/android/settings/applications/credentials/CombinedProviderInfo.java
index f8a3b0f..4f27870 100644
--- a/src/com/android/settings/applications/credentials/CombinedProviderInfo.java
+++ b/src/com/android/settings/applications/credentials/CombinedProviderInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.applications.credentials;
 
+import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -24,7 +25,6 @@
 import android.credentials.CredentialProviderInfo;
 import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.service.autofill.AutofillServiceInfo;
 import android.text.TextUtils;
 import android.util.IconDrawableFactory;
@@ -49,7 +49,7 @@
     private static final String TAG = "CombinedProviderInfo";
     private static final String SETTINGS_ACTIVITY_INTENT_ACTION = "android.intent.action.MAIN";
     private static final String SETTINGS_ACTIVITY_INTENT_CATEGORY =
-            "android.intent.category.LAUNCHER";
+            "android.intent.category.DEFAULT";
 
     private final List<CredentialProviderInfo> mCredentialProviderInfos;
     private final @Nullable AutofillServiceInfo mAutofillServiceInfo;
@@ -327,10 +327,8 @@
     }
 
     public static @Nullable Intent createSettingsActivityIntent(
-            @NonNull Context context,
             @Nullable CharSequence packageName,
-            @Nullable CharSequence settingsActivity,
-            int currentUserId) {
+            @Nullable CharSequence settingsActivity) {
         if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(settingsActivity)) {
             return null;
         }
@@ -350,19 +348,25 @@
         Intent intent = new Intent(SETTINGS_ACTIVITY_INTENT_ACTION);
         intent.addCategory(SETTINGS_ACTIVITY_INTENT_CATEGORY);
         intent.setComponent(cn);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return intent;
+    }
 
-        int contextUserId = context.getUser().getIdentifier();
-        if (currentUserId != contextUserId && UserManager.isHeadlessSystemUserMode()) {
-            Log.w(
-                    TAG,
-                    "onLeftSideClicked(): using context for current user ("
-                            + currentUserId
-                            + ") instead of user "
-                            + contextUserId
-                            + " on headless system user mode");
-            context = context.createContextAsUser(UserHandle.of(currentUserId), /* flags= */ 0);
+    /** Launches the settings activity intent. */
+    public static void launchSettingsActivityIntent(
+            @NonNull Context context,
+            @Nullable CharSequence packageName,
+            @Nullable CharSequence settingsActivity,
+            int userId) {
+        Intent settingsIntent = createSettingsActivityIntent(packageName, settingsActivity);
+        if (settingsIntent == null) {
+            return;
         }
 
-        return intent;
+        try {
+            context.startActivityAsUser(settingsIntent, UserHandle.of(userId));
+        } catch (ActivityNotFoundException e) {
+            Log.e(TAG, "Failed to open settings activity", e);
+        }
     }
 }
diff --git a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
index 4fc0e16..d98bc51 100644
--- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
+++ b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
@@ -20,7 +20,6 @@
 
 import android.app.Activity;
 import android.app.Dialog;
-import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -677,16 +676,8 @@
 
                     @Override
                     public void onLeftSideClicked() {
-                        Intent settingsIntent =
-                                CombinedProviderInfo.createSettingsActivityIntent(
-                                        mContext, packageName, settingsActivity, getUser());
-                        if (settingsIntent != null) {
-                            try {
-                                mContext.startActivity(settingsIntent);
-                            } catch (ActivityNotFoundException e) {
-                                Log.e(TAG, "Failed to open settings activity", e);
-                            }
-                        }
+                        CombinedProviderInfo.launchSettingsActivityIntent(
+                                mContext, packageName, settingsActivity, getUser());
                     }
                 });
 
diff --git a/src/com/android/settings/applications/credentials/CredentialsPickerActivity.java b/src/com/android/settings/applications/credentials/CredentialsPickerActivity.java
index 495c104..479a184 100644
--- a/src/com/android/settings/applications/credentials/CredentialsPickerActivity.java
+++ b/src/com/android/settings/applications/credentials/CredentialsPickerActivity.java
@@ -16,15 +16,53 @@
 
 package com.android.settings.applications.credentials;
 
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.SettingsActivity;
 
-/** Standalone activity used to launch a {@link DefaultCombinedPicker} fragment. */
+/**
+ * Standalone activity used to launch a {@link DefaultCombinedPicker} fragment if the user is a
+ * normal user, a {@link DefaultCombinedPickerWork} fragment if the user is a work profile or {@link
+ * DefaultCombinedPickerPrivate} fragment if the user is a private profile.
+ */
 public class CredentialsPickerActivity extends SettingsActivity {
+    private static final String TAG = "CredentialsPickerActivity";
+
+    /** Injects the fragment name into the intent so the correct fragment is opened. */
+    @VisibleForTesting
+    public static void injectFragmentIntoIntent(Context context, Intent intent) {
+        final int userId = UserHandle.myUserId();
+        final UserManager userManager = UserManager.get(context);
+
+        if (DefaultCombinedPickerWork.isUserHandledByFragment(userManager, userId)) {
+            Slog.d(TAG, "Creating picker fragment using work profile");
+            intent.putExtra(EXTRA_SHOW_FRAGMENT, DefaultCombinedPickerWork.class.getName());
+        } else if (DefaultCombinedPickerPrivate.isUserHandledByFragment(userManager)) {
+            Slog.d(TAG, "Creating picker fragment using private profile");
+            intent.putExtra(EXTRA_SHOW_FRAGMENT, DefaultCombinedPickerPrivate.class.getName());
+        } else {
+            Slog.d(TAG, "Creating picker fragment using normal profile");
+            intent.putExtra(EXTRA_SHOW_FRAGMENT, DefaultCombinedPicker.class.getName());
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        injectFragmentIntoIntent(this, getIntent());
+        super.onCreate(savedInstanceState);
+    }
 
     @Override
     protected boolean isValidFragment(String fragmentName) {
         return super.isValidFragment(fragmentName)
-                || DefaultCombinedPicker.class.getName().equals(fragmentName);
+                || DefaultCombinedPicker.class.getName().equals(fragmentName)
+                || DefaultCombinedPickerWork.class.getName().equals(fragmentName)
+                || DefaultCombinedPickerPrivate.class.getName().equals(fragmentName);
     }
 }
diff --git a/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java b/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java
index 722cb1a..8d8af0e 100644
--- a/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java
+++ b/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java
@@ -17,14 +17,29 @@
 package com.android.settings.applications.credentials;
 
 import android.os.UserManager;
+import android.util.Slog;
 
 import com.android.settings.Utils;
 import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
 
 public class DefaultCombinedPickerPrivate extends DefaultCombinedPicker {
+    private static final String TAG = "DefaultCombinedPickerPrivate";
+
     @Override
     protected int getUser() {
         UserManager userManager = getContext().getSystemService(UserManager.class);
         return Utils.getCurrentUserIdOfType(userManager, ProfileType.PRIVATE);
     }
+
+    /** Returns whether the user is handled by this fragment. */
+    public static boolean isUserHandledByFragment(UserManager userManager) {
+        try {
+            // If there is no private profile then this will throw an exception.
+            Utils.getCurrentUserIdOfType(userManager, ProfileType.PRIVATE);
+            return true;
+        } catch (IllegalStateException e) {
+            Slog.e(TAG, "Failed to get private profile user id", e);
+            return false;
+        }
+    }
 }
diff --git a/src/com/android/settings/applications/credentials/DefaultCombinedPickerWork.java b/src/com/android/settings/applications/credentials/DefaultCombinedPickerWork.java
index 9808502..945d6b8 100644
--- a/src/com/android/settings/applications/credentials/DefaultCombinedPickerWork.java
+++ b/src/com/android/settings/applications/credentials/DefaultCombinedPickerWork.java
@@ -19,13 +19,16 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 
-import com.android.settings.Utils;
-
 public class DefaultCombinedPickerWork extends DefaultCombinedPicker {
+    private static final String TAG = "DefaultCombinedPickerWork";
 
     @Override
     protected int getUser() {
-        UserHandle workProfile = Utils.getManagedProfile(UserManager.get(getContext()));
-        return workProfile.getIdentifier();
+        return UserHandle.myUserId();
+    }
+
+    /** Returns whether the user is handled by this fragment. */
+    public static boolean isUserHandledByFragment(UserManager userManager, int userId) {
+        return userManager.isManagedProfile(userId);
     }
 }
diff --git a/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceController.java b/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceController.java
index 0fb1769..49dd7cd 100644
--- a/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceController.java
+++ b/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceController.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.applications.credentials;
 
-import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.credentials.CredentialManager;
@@ -26,11 +25,11 @@
 import android.provider.Settings;
 import android.service.autofill.AutofillService;
 import android.service.autofill.AutofillServiceInfo;
+import android.text.TextUtils;
 import android.view.autofill.AutofillManager;
-import android.util.Slog;
 
-import androidx.annotation.Nullable;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.preference.Preference;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -83,7 +82,7 @@
         // hand side presses to align the UX.
         if (PrimaryProviderPreference.shouldUseNewSettingsUi()) {
             // We need to return an empty intent here since the class we inherit
-            // from will throw an NPE if we return null and we don't want it to 
+            // from will throw an NPE if we return null and we don't want it to
             // open anything since we added the buttons.
             return new Intent();
         }
@@ -99,10 +98,10 @@
                     topProvider.getAppName(mContext),
                     topProvider.getSettingsSubtitle(),
                     topProvider.getAppIcon(mContext, getUser()),
-                    createSettingsActivityIntent(
-                            topProvider.getPackageName(), topProvider.getSettingsActivity()));
+                    topProvider.getPackageName(),
+                    topProvider.getSettingsActivity());
         } else {
-            updatePreferenceForProvider(preference, null, null, null, null);
+            updatePreferenceForProvider(preference, null, null, null, null, null);
         }
     }
 
@@ -112,7 +111,8 @@
             @Nullable CharSequence appName,
             @Nullable String appSubtitle,
             @Nullable Drawable appIcon,
-            @Nullable Intent settingsActivityIntent) {
+            @Nullable CharSequence packageName,
+            @Nullable CharSequence settingsActivity) {
         if (appName == null) {
             preference.setTitle(R.string.app_list_preference_none);
         } else {
@@ -133,13 +133,8 @@
             primaryPref.setDelegate(
                     new PrimaryProviderPreference.Delegate() {
                         public void onOpenButtonClicked() {
-                            if (settingsActivityIntent != null) {
-                                try {
-                                    startActivity(settingsActivityIntent);
-                                } catch (ActivityNotFoundException e) {
-                                    Slog.e(TAG, "Failed to open settings activity", e);
-                                }
-                            }
+                            CombinedProviderInfo.launchSettingsActivityIntent(
+                                    mContext, packageName, settingsActivity, getUser());
                         }
 
                         public void onChangeButtonClicked() {
@@ -148,7 +143,7 @@
                     });
 
             // Hide the open button if there is no defined settings activity.
-            primaryPref.setOpenButtonVisible(settingsActivityIntent != null);
+            primaryPref.setOpenButtonVisible(!TextUtils.isEmpty(settingsActivity));
             primaryPref.setButtonsVisible(appName != null);
         }
     }
@@ -198,13 +193,8 @@
 
     /** Creates an intent to open the credential picker. */
     private Intent createIntentToOpenPicker() {
-        return new Intent(mContext, CredentialsPickerActivity.class);
-    }
-
-    /** Creates an intent to open the settings activity of the primary provider (if available). */
-    public @Nullable Intent createSettingsActivityIntent(
-            @Nullable String packageName, @Nullable String settingsActivity) {
-        return CombinedProviderInfo.createSettingsActivityIntent(
-                mContext, packageName, settingsActivity, getUser());
+        final Context context =
+                mContext.createContextAsUser(UserHandle.of(getUser()), /* flags= */ 0);
+        return new Intent(context, CredentialsPickerActivity.class);
     }
 }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index 0bc6176..a04d8f8 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -98,6 +98,12 @@
     /** Checks whether we should show usage information by slots or not */
     boolean isChartGraphSlotsEnabled(Context context);
 
+    /** Checks whether adaptive charging feature is supported in this device */
+    boolean isAdaptiveChargingSupported();
+
+    /** Checks whether battery manager feature is supported in this device */
+    boolean isBatteryManagerSupported();
+
     /** Returns {@code true} if current defender mode is extra defend */
     boolean isExtraDefend();
 
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index a8a2f75..75ebabb 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -149,6 +149,16 @@
     }
 
     @Override
+    public boolean isAdaptiveChargingSupported() {
+        return false;
+    }
+
+    @Override
+    public boolean isBatteryManagerSupported() {
+        return true;
+    }
+
+    @Override
     public Intent getResumeChargeIntent(boolean isDockDefender) {
         return null;
     }
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceController.java
new file mode 100644
index 0000000..7448003
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceController.java
@@ -0,0 +1,85 @@
+/*
+ * 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.fuelgauge.batterytip;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.UserManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.utils.StringUtil;
+
+/** Preference controller to control the battery manager */
+public class BatteryManagerPreferenceController extends BasePreferenceController {
+    private static final String KEY_BATTERY_MANAGER = "smart_battery_manager";
+
+    private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+    private AppOpsManager mAppOpsManager;
+    private UserManager mUserManager;
+    private boolean mEnableAppBatteryUsagePage;
+
+    public BatteryManagerPreferenceController(Context context) {
+        super(context, KEY_BATTERY_MANAGER);
+        mPowerUsageFeatureProvider = FeatureFactory.getFeatureFactory()
+                .getPowerUsageFeatureProvider();
+        mAppOpsManager = context.getSystemService(AppOpsManager.class);
+        mUserManager = context.getSystemService(UserManager.class);
+        mEnableAppBatteryUsagePage =
+                mContext.getResources().getBoolean(R.bool.config_app_battery_usage_list_enabled);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        if (!mPowerUsageFeatureProvider.isBatteryManagerSupported()) {
+            return UNSUPPORTED_ON_DEVICE;
+        }
+        if (!mContext.getResources().getBoolean(R.bool.config_battery_manager_consider_ac)) {
+            return AVAILABLE_UNSEARCHABLE;
+        }
+        return mPowerUsageFeatureProvider.isAdaptiveChargingSupported()
+                ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        if (!mEnableAppBatteryUsagePage) {
+            final int num = BatteryTipUtils.getRestrictedAppsList(mAppOpsManager,
+                    mUserManager).size();
+            updateSummary(preference, num);
+        }
+    }
+
+    @VisibleForTesting
+    void updateSummary(Preference preference, int num) {
+        if (num > 0) {
+            preference.setSummary(StringUtil.getIcuPluralsString(mContext, num,
+                    R.string.battery_manager_app_restricted));
+        } else {
+            preference.setSummary(
+                    mPowerUsageFeatureProvider.isAdaptiveChargingSupported()
+                            ? R.string.battery_manager_summary
+                            : R.string.battery_manager_summary_unsupported);
+        }
+    }
+}
diff --git a/src/com/android/settings/localepicker/TermsOfAddressFeminineController.java b/src/com/android/settings/localepicker/TermsOfAddressFeminineController.java
index 9a46872..fdc4589 100644
--- a/src/com/android/settings/localepicker/TermsOfAddressFeminineController.java
+++ b/src/com/android/settings/localepicker/TermsOfAddressFeminineController.java
@@ -35,7 +35,7 @@
 
     @Override
     protected int getMetricsActionKey() {
-        return SettingsEnums.ACTION_TERMS_OF_ADDRESS_FEMININE;
+        return 0;
     }
 
     @Override
diff --git a/src/com/android/settings/localepicker/TermsOfAddressMasculineController.java b/src/com/android/settings/localepicker/TermsOfAddressMasculineController.java
index cb39df0..8601113 100644
--- a/src/com/android/settings/localepicker/TermsOfAddressMasculineController.java
+++ b/src/com/android/settings/localepicker/TermsOfAddressMasculineController.java
@@ -35,7 +35,7 @@
 
     @Override
     protected int getMetricsActionKey() {
-        return SettingsEnums.ACTION_TERMS_OF_ADDRESS_MASCULINE;
+        return 0;
     }
 
     @Override
diff --git a/src/com/android/settings/localepicker/TermsOfAddressNeutralController.java b/src/com/android/settings/localepicker/TermsOfAddressNeutralController.java
index e0693b5..e67bd4d 100644
--- a/src/com/android/settings/localepicker/TermsOfAddressNeutralController.java
+++ b/src/com/android/settings/localepicker/TermsOfAddressNeutralController.java
@@ -35,7 +35,7 @@
 
     @Override
     protected int getMetricsActionKey() {
-        return SettingsEnums.ACTION_TERMS_OF_ADDRESS_NEUTRAL;
+        return 0;
     }
 
     @Override
diff --git a/src/com/android/settings/network/SimOnboardingActivity.kt b/src/com/android/settings/network/SimOnboardingActivity.kt
new file mode 100644
index 0000000..f5dc886
--- /dev/null
+++ b/src/com/android/settings/network/SimOnboardingActivity.kt
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network
+
+import android.app.ProgressDialog
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.telephony.SubscriptionManager
+import android.util.Log
+import android.view.MotionEvent
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.SignalCellularAlt
+import androidx.compose.material3.Button
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.ModalBottomSheet
+import androidx.compose.material3.SheetState
+import androidx.compose.material3.Text
+import androidx.compose.material3.rememberModalBottomSheetState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import com.android.settings.R
+import com.android.settings.SidecarFragment
+import com.android.settings.network.telephony.SubscriptionActionDialogActivity
+import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
+import com.android.settings.spa.network.SimOnboardingPageProvider.getRoute
+import com.android.settingslib.spa.SpaBaseDialogActivity
+import com.android.settingslib.spa.framework.theme.SettingsDimension
+import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
+import com.android.settingslib.spa.widget.ui.SettingsTitle
+import com.android.settingslib.spaprivileged.framework.common.userManager
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.launch
+
+class SimOnboardingActivity : SpaBaseDialogActivity() {
+    lateinit var scope: CoroutineScope
+    lateinit var showBottomSheet: MutableState<Boolean>
+    lateinit var showError: MutableState<Boolean>
+    lateinit var showDialog: MutableState<Boolean>
+
+    private var switchToEuiccSubscriptionSidecar: SwitchToEuiccSubscriptionSidecar? = null
+    private var switchToRemovableSlotSidecar: SwitchToRemovableSlotSidecar? = null
+    private var enableMultiSimSidecar: EnableMultiSimSidecar? = null
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        if (!this.userManager.isAdminUser) {
+            Log.e(TAG, "It is not the admin user. Unable to toggle subscription.")
+            finish()
+            return
+        }
+
+        var targetSubId = intent.getIntExtra(SUB_ID,SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+        initServiceData(this, targetSubId, callbackListener)
+        if (!onboardingService.isUsableTargetSubscriptionId) {
+            Log.e(TAG, "The subscription id is not usable.")
+            finish()
+            return
+        }
+
+        switchToEuiccSubscriptionSidecar = SwitchToEuiccSubscriptionSidecar.get(fragmentManager)
+        switchToRemovableSlotSidecar = SwitchToRemovableSlotSidecar.get(fragmentManager)
+        enableMultiSimSidecar = EnableMultiSimSidecar.get(fragmentManager)
+
+        setContent {
+            Content()
+        }
+    }
+
+    override fun finish() {
+        setProgressDialog(false)
+        onboardingService.clear()
+        super.finish()
+    }
+
+    var callbackListener: (Int) -> Unit = {
+        Log.d(TAG, "Receive the CALLBACK: $it")
+        when (it) {
+            CALLBACK_ERROR -> {
+                setProgressDialog(false)
+                showError.value = true
+            }
+
+            CALLBACK_ONBOARDING_COMPLETE -> {
+                showBottomSheet.value = false
+                setProgressDialog(true)
+                scope.launch {
+                    // TODO: refactor the Sidecar
+                    // start to activate the sim
+                    startSimSwitching()
+                }
+            }
+
+            CALLBACK_SETUP_NAME -> {
+                scope.launch {
+                    onboardingService.startSetupName()
+                }
+            }
+
+            CALLBACK_SETUP_PRIMARY_SIM -> {
+                scope.launch {
+                    onboardingService.startSetupPrimarySim(this@SimOnboardingActivity)
+                }
+            }
+
+            CALLBACK_FINISH -> {
+                finish()
+            }
+        }
+    }
+
+    fun setProgressDialog(enable: Boolean) {
+        showDialog.value = enable
+        val progressState = if (enable) {
+            SubscriptionActionDialogActivity.PROGRESS_IS_SHOWING
+        } else {
+            SubscriptionActionDialogActivity.PROGRESS_IS_NOT_SHOWING
+        }
+        setProgressState(progressState)
+    }
+
+    @OptIn(ExperimentalMaterial3Api::class)
+    @Composable
+    override fun Content() {
+        showBottomSheet = remember { mutableStateOf(true) }
+        showError = remember { mutableStateOf(false) }
+        showDialog = remember { mutableStateOf(false) }
+        scope = rememberCoroutineScope()
+
+        registerSidecarReceiverFlow()
+
+        if(showError.value){
+            // show error
+            return
+        }
+
+        if (showBottomSheet.value) {
+            var sheetState = rememberModalBottomSheetState()
+            BottomSheetImpl(
+                sheetState = sheetState,
+                nextAction = {
+                    // TODO: if the phone is SS mode and the isDsdsConditionSatisfied is true, then
+                    //  enable the DSDS mode.
+                    //  case#1: the device need the reboot after enabling DSDS. Showing the confirm
+                    //          dialog to user whether reboot device or not.
+                    //  case#2: The device don't need the reboot. Enabling DSDS and then showing
+                    //          the SIM onboarding UI.
+
+                    // case#2
+                    val route = getRoute(onboardingService.targetSubId)
+                    startSpaActivity(route)
+                },
+                cancelAction = { finish() },
+            )
+        } else {
+            ProgressDialogImpl()
+        }
+    }
+
+    @Composable
+    fun ProgressDialogImpl() {
+        // TODO: 1. Create the SPA's ProgressDialog and using SPA's widget
+        val dialog: ProgressDialog = object : ProgressDialog(this) {
+            override fun onTouchEvent(event: MotionEvent): Boolean {
+                return true
+            }
+        }
+        dialog.setMessage(
+            stringResource(
+                R.string.sim_onboarding_progressbar_turning_sim_on,
+                onboardingService.targetSubInfo?.displayName ?: ""
+            )
+        )
+        dialog.setCancelable(false)
+
+        if(showDialog.value) {
+            dialog.show()
+        }
+    }
+    @Composable
+    fun registerSidecarReceiverFlow(){
+        switchToEuiccSubscriptionSidecar?.sidecarReceiverFlow()
+            ?.collectLatestWithLifecycle(LocalLifecycleOwner.current) {
+                onStateChange(it)
+            }
+        switchToRemovableSlotSidecar?.sidecarReceiverFlow()
+            ?.collectLatestWithLifecycle(LocalLifecycleOwner.current) {
+                onStateChange(it)
+            }
+        enableMultiSimSidecar?.sidecarReceiverFlow()
+            ?.collectLatestWithLifecycle(LocalLifecycleOwner.current) {
+                onStateChange(it)
+            }
+    }
+
+    fun SidecarFragment.sidecarReceiverFlow(): Flow<SidecarFragment> = callbackFlow {
+        val broadcastReceiver = SidecarFragment.Listener {
+            Log.d(TAG, "onReceive: $it")
+            trySend(it)
+        }
+        addListener(broadcastReceiver)
+
+        awaitClose { removeListener(broadcastReceiver) }
+    }.catch { e ->
+        Log.e(TAG, "Error while sidecarReceiverFlow", e)
+    }.conflate()
+
+    fun startSimSwitching(){
+        Log.d(TAG, "startSimSwitching:")
+
+        var targetSubInfo = onboardingService.targetSubInfo
+        targetSubInfo?.let {
+            var removedSubInfo = onboardingService.getRemovedSim()
+            if (targetSubInfo.isEmbedded) {
+                switchToEuiccSubscriptionSidecar!!.run(
+                    targetSubInfo.subscriptionId,
+                    UiccSlotUtil.INVALID_PORT_ID,
+                    removedSubInfo
+                )
+                return@let
+            }
+            switchToRemovableSlotSidecar!!.run(
+                UiccSlotUtil.INVALID_PHYSICAL_SLOT_ID,
+                removedSubInfo
+            )
+        } ?: run {
+            Log.e(TAG, "no target subInfo in onboardingService")
+            finish()
+        }
+    }
+
+    fun onStateChange(fragment: SidecarFragment?) {
+        if (fragment === switchToEuiccSubscriptionSidecar) {
+            handleSwitchToEuiccSubscriptionSidecarStateChange()
+        } else if (fragment === switchToRemovableSlotSidecar) {
+            handleSwitchToRemovableSlotSidecarStateChange()
+        } else if (fragment === enableMultiSimSidecar) {
+            handleEnableMultiSimSidecarStateChange()
+        }
+    }
+
+    fun handleSwitchToEuiccSubscriptionSidecarStateChange() {
+        when (switchToEuiccSubscriptionSidecar!!.state) {
+            SidecarFragment.State.SUCCESS -> {
+                Log.i(TAG, "Successfully enable the eSIM profile.")
+                switchToEuiccSubscriptionSidecar!!.reset()
+                callbackListener(CALLBACK_SETUP_NAME)
+            }
+
+            SidecarFragment.State.ERROR -> {
+                Log.i(TAG, "Failed to enable the eSIM profile.")
+                switchToEuiccSubscriptionSidecar!!.reset()
+                callbackListener(CALLBACK_ERROR)
+                // TODO: showErrorDialog and using privileged_action_disable_fail_title and
+                //       privileged_action_disable_fail_text
+            }
+        }
+    }
+
+    fun handleSwitchToRemovableSlotSidecarStateChange() {
+        when (switchToRemovableSlotSidecar!!.state) {
+            SidecarFragment.State.SUCCESS -> {
+                Log.i(TAG, "Successfully switched to removable slot.")
+                switchToRemovableSlotSidecar!!.reset()
+                onboardingService.handleTogglePsimAction()
+                callbackListener(CALLBACK_SETUP_NAME)
+            }
+
+            SidecarFragment.State.ERROR -> {
+                Log.e(TAG, "Failed switching to removable slot.")
+                switchToRemovableSlotSidecar!!.reset()
+                callbackListener(CALLBACK_ERROR)
+                // TODO: showErrorDialog and using sim_action_enable_sim_fail_title and
+                //       sim_action_enable_sim_fail_text
+            }
+        }
+    }
+
+    fun handleEnableMultiSimSidecarStateChange() {
+        when (enableMultiSimSidecar!!.state) {
+            SidecarFragment.State.SUCCESS -> {
+                enableMultiSimSidecar!!.reset()
+                Log.i(TAG, "Successfully switched to DSDS without reboot.")
+                handleEnableSubscriptionAfterEnablingDsds()
+            }
+
+            SidecarFragment.State.ERROR -> {
+                enableMultiSimSidecar!!.reset()
+                Log.i(TAG, "Failed to switch to DSDS without rebooting.")
+                callbackListener(CALLBACK_ERROR)
+                // TODO: showErrorDialog and using dsds_activation_failure_title and
+                //       dsds_activation_failure_body_msg2
+            }
+        }
+    }
+
+    fun handleEnableSubscriptionAfterEnablingDsds() {
+        var targetSubInfo = onboardingService.targetSubInfo
+        if (targetSubInfo?.isEmbedded == true) {
+            Log.i(TAG,
+                    "DSDS enabled, start to enable profile: " + targetSubInfo.getSubscriptionId()
+            )
+            // For eSIM operations, we simply switch to the selected eSIM profile.
+            switchToEuiccSubscriptionSidecar!!.run(
+                targetSubInfo.subscriptionId,
+                UiccSlotUtil.INVALID_PORT_ID,
+                null
+            )
+            return
+        }
+        Log.i(TAG, "DSDS enabled, start to enable pSIM profile.")
+        onboardingService.handleTogglePsimAction()
+        callbackListener(CALLBACK_FINISH)
+    }
+
+    @Composable
+    fun BottomSheetBody(nextAction: () -> Unit) {
+        Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(bottom = SettingsDimension.itemPaddingVertical)) {
+            Icon(
+                imageVector = Icons.Outlined.SignalCellularAlt,
+                contentDescription = null,
+                modifier = Modifier
+                    .size(SettingsDimension.iconLarge),
+                tint = MaterialTheme.colorScheme.primary,
+            )
+            SettingsTitle(stringResource(R.string.sim_onboarding_bottomsheets_title))
+            Column(Modifier.padding(SettingsDimension.itemPadding)) {
+                Text(
+                    text = stringResource(R.string.sim_onboarding_bottomsheets_msg),
+                    color = MaterialTheme.colorScheme.onSurfaceVariant,
+                    style = MaterialTheme.typography.bodyMedium,
+                    overflow = TextOverflow.Ellipsis,
+                    textAlign = TextAlign.Center
+                )
+            }
+            Button(onClick = nextAction) {
+                Text(stringResource(R.string.sim_onboarding_setup))
+            }
+        }
+    }
+
+    @OptIn(ExperimentalMaterial3Api::class)
+    @Composable
+    fun BottomSheetImpl(
+        sheetState: SheetState,
+        nextAction: () -> Unit,
+        cancelAction: () -> Unit,
+    ) {
+        ModalBottomSheet(
+            onDismissRequest = cancelAction,
+            sheetState = sheetState,
+        ) {
+            BottomSheetBody(nextAction = nextAction)
+        }
+        LaunchedEffect(Unit) {
+            sheetState.show()
+        }
+    }
+
+    fun setProgressState(state: Int) {
+        val prefs = getSharedPreferences(
+            SubscriptionActionDialogActivity.SIM_ACTION_DIALOG_PREFS,
+            MODE_PRIVATE
+        )
+        prefs.edit().putInt(SubscriptionActionDialogActivity.KEY_PROGRESS_STATE, state).apply()
+        Log.i(TAG, "setProgressState:$state")
+    }
+
+    fun initServiceData(context: Context,targetSubId: Int, callback:(Int)->Unit) {
+        onboardingService.initData(targetSubId, context,callback)
+    }
+
+    companion object {
+        @JvmStatic
+        fun startSimOnboardingActivity(
+            context: Context,
+            subId: Int,
+        ) {
+            val intent = Intent(context, SimOnboardingActivity::class.java).apply {
+                putExtra(SUB_ID, subId)
+            }
+            context.startActivity(intent)
+        }
+
+        var onboardingService:SimOnboardingService = SimOnboardingService()
+        const val TAG = "SimOnboardingActivity"
+        const val SUB_ID = "sub_id"
+        const val CALLBACK_ERROR = -1
+        const val CALLBACK_ONBOARDING_COMPLETE = 1
+        const val CALLBACK_SETUP_NAME = 2
+        const val CALLBACK_SETUP_PRIMARY_SIM = 3
+        const val CALLBACK_FINISH = 4
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/network/SimOnboardingService.kt b/src/com/android/settings/network/SimOnboardingService.kt
index 1b3994e..8679385 100644
--- a/src/com/android/settings/network/SimOnboardingService.kt
+++ b/src/com/android/settings/network/SimOnboardingService.kt
@@ -23,11 +23,17 @@
 import android.telephony.UiccCardInfo
 import android.telephony.UiccSlotInfo
 import android.util.Log
+import com.android.settings.spa.network.setAutomaticData
+import com.android.settings.spa.network.setDefaultData
+import com.android.settings.spa.network.setDefaultSms
+import com.android.settings.spa.network.setDefaultVoice
 import com.android.settingslib.utils.ThreadUtils
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
 
 
 private const val TAG = "SimOnboardingService"
-private const val INVALID = -1
+private const val INVALID = SubscriptionManager.INVALID_SUBSCRIPTION_ID
 
 class SimOnboardingService {
     var subscriptionManager:SubscriptionManager? = null
@@ -40,19 +46,72 @@
     var slotInfoList: List<UiccSlotInfo> = listOf()
     var uiccCardInfoList: List<UiccCardInfo> = listOf()
     var selectedSubInfoList: MutableList<SubscriptionInfo> = mutableListOf()
-    var targetPrimarySimCalls: Int = -1
-    var targetPrimarySimTexts: Int = -1
-    var targetPrimarySimMobileData: Int = -1
+    var targetPrimarySimCalls: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+    var targetPrimarySimTexts: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+    var targetPrimarySimMobileData: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+    var targetPrimarySimAutoDataSwitch: Boolean = false
+    var targetNonDds: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+        get() {
+            if(targetPrimarySimMobileData == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                Log.w(TAG, "No DDS")
+                return SubscriptionManager.INVALID_SUBSCRIPTION_ID
+            }
+            return selectedSubInfoList
+                .filter { info ->
+                    (info.simSlotIndex != -1) && (info.subscriptionId != targetPrimarySimMobileData)
+                }
+                .map { it.subscriptionId }
+                .firstOrNull() ?: SubscriptionManager.INVALID_SUBSCRIPTION_ID
+        }
+    var callback: (Int) -> Unit = {}
+
     var isMultipleEnabledProfilesSupported: Boolean = false
         get() {
             if (uiccCardInfoList.isEmpty()) {
                 Log.w(TAG, "UICC cards info list is empty.")
                 return false
             }
-            return uiccCardInfoList.stream()
-                .anyMatch { cardInfo: UiccCardInfo -> cardInfo.isMultipleEnabledProfilesSupported }
+            return  uiccCardInfoList.any { it.isMultipleEnabledProfilesSupported }
         }
+    var isRemovableSimEnabled: Boolean = false
+        get() {
+            if(slotInfoList.isEmpty()) {
+                Log.w(TAG, "UICC Slot info list is empty.")
+                return false
+            }
+            return UiccSlotUtil.isRemovableSimEnabled(slotInfoList)
+        }
+
+    var doesTargetSimHaveEsimOperation = false
+        get() {
+            return targetSubInfo?.isEmbedded ?: false
+        }
+
+    var isUsableTargetSubscriptionId = false
+        get() {
+            return SubscriptionManager.isUsableSubscriptionId(targetSubId)
+        }
+    var getActiveModemCount = 0
+        get() {
+            return telephonyManager?.getActiveModemCount() ?: 0
+        }
+
     var renameMutableMap : MutableMap<Int, String> = mutableMapOf()
+    var userSelectedSubInfoList : MutableList<SubscriptionInfo> = mutableListOf()
+
+    var isSimSelectionFinished = false
+        get() {
+            return getActiveModemCount != 0 && userSelectedSubInfoList.size == getActiveModemCount
+        }
+
+    var isAllOfSlotAssigned = false
+        get() {
+            if(getActiveModemCount == 0){
+                Log.e(TAG, "isAllOfSlotAssigned: getActiveModemCount is 0")
+                return true
+            }
+            return getActiveModemCount != 0 && activeSubInfoList.size == getActiveModemCount
+        }
 
     fun isValid(): Boolean {
         return targetSubId != INVALID
@@ -73,18 +132,27 @@
         targetPrimarySimCalls = -1
         targetPrimarySimTexts = -1
         targetPrimarySimMobileData = -1
-        renameMutableMap.clear()
+        clearUserRecord()
     }
 
-    fun initData(inputTargetSubId:Int,context: Context) {
+    fun clearUserRecord(){
+        renameMutableMap.clear()
+        userSelectedSubInfoList.clear()
+    }
+
+    fun initData(inputTargetSubId:Int,context: Context, callback: (Int) -> Unit) {
+        this.callback = callback
         targetSubId = inputTargetSubId
         subscriptionManager = context.getSystemService(SubscriptionManager::class.java)
         telephonyManager = context.getSystemService(TelephonyManager::class.java)
-
+        Log.d(
+            TAG, "startInit: targetSubId:$targetSubId"
+        )
         ThreadUtils.postOnBackgroundThread {
             activeSubInfoList = SubscriptionUtil.getActiveSubscriptions(subscriptionManager)
             availableSubInfoList = SubscriptionUtil.getAvailableSubscriptions(context)
             targetSubInfo = availableSubInfoList.find { subInfo -> subInfo.subscriptionId == targetSubId }
+            targetSubInfo?.let { userSelectedSubInfoList.add(it) }
             Log.d(
                 TAG, "targetSubId: $targetSubId" + ", targetSubInfo: $targetSubInfo" +
                     ". activeSubInfoList: $activeSubInfoList"
@@ -94,11 +162,24 @@
             uiccCardInfoList = telephonyManager?.uiccCardsInfo!!
             Log.d(TAG, "uiccCardInfoList: $uiccCardInfoList")
 
-            Log.d(TAG, "isMultipleEnabledProfilesSupported: $isMultipleEnabledProfilesSupported")
+            targetPrimarySimCalls = SubscriptionManager.getDefaultVoiceSubscriptionId()
+            targetPrimarySimTexts = SubscriptionManager.getDefaultSmsSubscriptionId()
+            targetPrimarySimMobileData = SubscriptionManager.getDefaultDataSubscriptionId()
+            Log.d(
+                TAG,"doesTargetSimHaveEsimOperation: $doesTargetSimHaveEsimOperation" +
+                    ", isRemovableSimEnabled: $isRemovableSimEnabled" +
+                    ", isMultipleEnabledProfilesSupported: $isMultipleEnabledProfilesSupported" +
+                    ", targetPrimarySimCalls: $targetPrimarySimCalls" +
+                    ", targetPrimarySimTexts: $targetPrimarySimTexts" +
+                    ", targetPrimarySimMobileData: $targetPrimarySimMobileData")
         }
     }
 
-    fun getSelectableSubscriptionInfo(): List<SubscriptionInfo> {
+    /**
+     * Return the subscriptionInfo list which has
+     * the target subscriptionInfo + active subscriptionInfo.
+     */
+    fun getSelectableSubscriptionInfoList(): List<SubscriptionInfo> {
         var list: MutableList<SubscriptionInfo> = mutableListOf()
         list.addAll(activeSubInfoList)
         if (!list.contains(targetSubInfo)) {
@@ -109,18 +190,102 @@
         return list.toList()
     }
 
+    /**
+     * Return the user selected SubscriptionInfo list.
+     */
+    fun getSelectedSubscriptionInfoList(): List<SubscriptionInfo> {
+        if (userSelectedSubInfoList.isEmpty()){
+            Log.d(TAG, "userSelectedSubInfoList is empty")
+            return activeSubInfoList
+        }
+        return userSelectedSubInfoList.toList()
+    }
+
     fun addItemForRenaming(subInfo: SubscriptionInfo, newName: String) {
         if (subInfo.displayName == newName) {
             return
         }
         renameMutableMap[subInfo.subscriptionId] = newName
+        Log.d(TAG, "renameMutableMap add ${subInfo.subscriptionId} & $newName into: $renameMutableMap")
     }
 
     fun getSubscriptionInfoDisplayName(subInfo: SubscriptionInfo): String {
         return renameMutableMap[subInfo.subscriptionId] ?: subInfo.displayName.toString()
     }
 
-    fun startActivatingSim(callback:() -> Unit){
+    fun addCurrentItemForSelectedSim(){
+        userSelectedSubInfoList.addAll(activeSubInfoList)
+    }
+
+    fun addItemForSelectedSim(selectedSubInfo: SubscriptionInfo) {
+        userSelectedSubInfoList.add(selectedSubInfo)
+    }
+
+    fun removeItemForSelectedSim(selectedSubInfo: SubscriptionInfo) {
+        if (userSelectedSubInfoList.contains(selectedSubInfo)) {
+            userSelectedSubInfoList.remove(selectedSubInfo)
+        }
+    }
+
+    /**
+     * Return the subscriptionInfo which will be removed in the slot during the sim onboarding.
+     * If return Null, then no subscriptionInfo will be removed in the slot.
+     */
+    fun getRemovedSim():SubscriptionInfo?{
+        return activeSubInfoList.find { !userSelectedSubInfoList.contains(it) }
+    }
+
+    fun handleTogglePsimAction() {
+        val canDisablePhysicalSubscription =
+            subscriptionManager?.canDisablePhysicalSubscription() == true
+        if (targetSubInfo != null && canDisablePhysicalSubscription) {
+            // TODO: to support disable case.
+            subscriptionManager?.setUiccApplicationsEnabled(
+                    targetSubInfo!!.subscriptionId, /*enabled=*/true)
+        } else {
+            Log.i(TAG, "The device does not support toggling pSIM. It is enough to just "
+                    + "enable the removable slot."
+            )
+        }
+    }
+
+    fun startActivatingSim(){
         // TODO: start to activate sim
+        callback(SimOnboardingActivity.CALLBACK_FINISH)
+    }
+
+    suspend fun startSetupName() {
+        withContext(Dispatchers.Default) {
+            renameMutableMap.forEach {
+                subscriptionManager?.setDisplayName(
+                    it.value, it.key,
+                    SubscriptionManager.NAME_SOURCE_USER_INPUT
+                )
+            }
+            // next action is SETUP_PRIMARY_SIM
+            callback(SimOnboardingActivity.CALLBACK_SETUP_PRIMARY_SIM)
+        }
+    }
+
+    suspend fun startSetupPrimarySim(context: Context) {
+        withContext(Dispatchers.Default) {
+            setDefaultVoice(subscriptionManager,targetPrimarySimCalls)
+            setDefaultSms(subscriptionManager,targetPrimarySimTexts)
+            setDefaultData(
+                context,
+                subscriptionManager,
+                null,
+                targetPrimarySimMobileData
+            )
+
+
+            val telephonyManagerForNonDds: TelephonyManager? =
+                context.getSystemService(TelephonyManager::class.java)
+                    ?.createForSubscriptionId(targetNonDds)
+            setAutomaticData(telephonyManagerForNonDds, targetPrimarySimAutoDataSwitch)
+
+            // no next action, send finish
+            callback(SimOnboardingActivity.CALLBACK_FINISH)
+        }
     }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index b6b433b..84e4e75 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -48,8 +48,6 @@
 import com.android.settings.network.helper.SubscriptionAnnotation;
 import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
 import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
-import com.android.settings.spa.SpaActivity;
-import com.android.settings.spa.network.SimOnboardingPageProvider;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -546,8 +544,7 @@
             return;
         }
         if (enable && Flags.isDualSimOnboardingEnabled()) {
-            String route = SimOnboardingPageProvider.INSTANCE.getRoute(subId);
-            SpaActivity.startSpaActivity(context, route);
+            SimOnboardingActivity.startSimOnboardingActivity(context, subId);
             return;
         }
         context.startActivity(ToggleSubscriptionDialogActivity.getIntent(context, subId, enable));
diff --git a/src/com/android/settings/network/UiccSlotUtil.java b/src/com/android/settings/network/UiccSlotUtil.java
index 5175c23..df23f12 100644
--- a/src/com/android/settings/network/UiccSlotUtil.java
+++ b/src/com/android/settings/network/UiccSlotUtil.java
@@ -463,17 +463,27 @@
         if (telMgr == null) {
             return false;
         }
-        ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(telMgr);
+        List<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(telMgr);
+        return isRemovableSimEnabled(slotInfos);
+    }
+
+    /**
+     * Return whether the removable psim is enabled.
+     *
+     * @param slotInfos is a List of UiccSlotInfo.
+     * @return whether the removable psim is enabled.
+     */
+    public static boolean isRemovableSimEnabled(List<UiccSlotInfo> slotInfos) {
         boolean isRemovableSimEnabled =
                 slotInfos.stream()
                         .anyMatch(
                                 slot -> slot != null
                                         && slot.isRemovable()
                                         && !slot.getIsEuicc()
-                                        && slot.getPorts().stream().anyMatch(
-                                                port -> port.isActive())
+                                        && slot.getPorts().stream()
+                                                .anyMatch(port -> port.isActive())
                                         && slot.getCardStateInfo()
-                                                == UiccSlotInfo.CARD_STATE_INFO_PRESENT);
+                                        == UiccSlotInfo.CARD_STATE_INFO_PRESENT);
         Log.i(TAG, "isRemovableSimEnabled: " + isRemovableSimEnabled);
         return isRemovableSimEnabled;
     }
diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java
index d65b2d1..4544e73 100644
--- a/src/com/android/settings/sim/SimDialogActivity.java
+++ b/src/com/android/settings/sim/SimDialogActivity.java
@@ -41,6 +41,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
+import com.android.settings.flags.Flags;
 import com.android.settings.network.CarrierConfigCache;
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settings.network.ims.WifiCallingQueryImsState;
@@ -134,6 +135,17 @@
             return;
         }
 
+        if (Flags.isDualSimOnboardingEnabled()
+                && getProgressState() == SubscriptionActionDialogActivity.PROGRESS_IS_SHOWING
+                && (dialogType == PREFERRED_PICK
+                || dialogType == DATA_PICK
+                || dialogType == CALLS_PICK
+                || dialogType == SMS_PICK)) {
+            Log.d(TAG, "Finish the sim dialog since the sim onboarding is shown");
+            finish();
+            return;
+        }
+
         final String tag = Integer.toString(dialogType);
         final FragmentManager fragmentManager = getSupportFragmentManager();
         SimDialogFragment fragment = (SimDialogFragment) fragmentManager.findFragmentByTag(tag);
diff --git a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
index e746d4a..b6d83f2 100644
--- a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
+++ b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
@@ -67,6 +67,7 @@
 
 import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
 import com.android.settingslib.spaprivileged.template.preference.RestrictedPreference
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
@@ -171,6 +172,8 @@
                     .map { it.subscriptionId }
                     .firstOrNull() ?: SubscriptionManager.INVALID_SUBSCRIPTION_ID
         }
+
+        Log.d(name, "defaultDataSubId: $defaultDataSubId, nonDds: $nonDds")
     }
 }
 
@@ -195,7 +198,6 @@
                 selectableSubscriptionInfoList
         )
         PrimarySimSectionImpl(
-                subscriptionManager,
                 activeSubscriptionInfoList,
                 defaultVoiceSubId,
                 defaultSmsSubId,
@@ -257,12 +259,49 @@
 
 @Composable
 fun PrimarySimSectionImpl(
-        subscriptionManager: SubscriptionManager?,
-        activeSubscriptionInfoList: List<SubscriptionInfo>,
-        callsSelectedId: MutableIntState,
-        textsSelectedId: MutableIntState,
-        mobileDataSelectedId: MutableIntState,
-        nonDds: MutableIntState
+    subscriptionInfoList: List<SubscriptionInfo>,
+    callsSelectedId: MutableIntState,
+    textsSelectedId: MutableIntState,
+    mobileDataSelectedId: MutableIntState,
+    nonDds: MutableIntState,
+    subscriptionManager: SubscriptionManager? =
+        LocalContext.current.getSystemService(SubscriptionManager::class.java),
+    coroutineScope: CoroutineScope = rememberCoroutineScope(),
+    context: Context = LocalContext.current,
+    actionSetCalls: (Int) -> Unit = {
+        callsSelectedId.intValue = it
+        coroutineScope.launch {
+            setDefaultVoice(subscriptionManager, it)
+        }
+    },
+    actionSetTexts: (Int) -> Unit = {
+        textsSelectedId.intValue = it
+        coroutineScope.launch {
+            setDefaultSms(subscriptionManager, it)
+        }
+    },
+    actionSetMobileData: (Int) -> Unit = {
+        mobileDataSelectedId.intValue = it
+        coroutineScope.launch {
+            // TODO: to fix the WifiPickerTracker crash when create
+            //       the wifiPickerTrackerHelper
+            setDefaultData(
+                context,
+                subscriptionManager,
+                null/*wifiPickerTrackerHelper*/,
+                it
+            )
+        }
+    },
+    actionSetAutoDataSwitch: (Boolean) -> Unit = { newState ->
+        coroutineScope.launch {
+            val telephonyManagerForNonDds: TelephonyManager? =
+                context.getSystemService(TelephonyManager::class.java)
+                    ?.createForSubscriptionId(nonDds.intValue)
+            Log.d(NetworkCellularGroupProvider.name, "NonDds:${nonDds.intValue} setAutomaticData")
+            setAutomaticData(telephonyManagerForNonDds, newState)
+        }
+    },
 ) {
     var state = rememberSaveable { mutableStateOf(false) }
     var callsAndSmsList = remember {
@@ -272,11 +311,11 @@
         mutableListOf(ListPreferenceOption(id = -1, text = "Loading"))
     }
 
-    if (activeSubscriptionInfoList.size >= 2) {
+    if (subscriptionInfoList.size >= 2) {
         state.value = true
         callsAndSmsList.clear()
         dataList.clear()
-        for (info in activeSubscriptionInfoList) {
+        for (info in subscriptionInfoList) {
             var item = ListPreferenceOption(
                     id = info.subscriptionId,
                     text = "${info.displayName}"
@@ -291,12 +330,10 @@
     } else {
         // hide the primary sim
         state.value = false
-        Log.d("NetworkCellularGroupProvider", "Hide primary sim")
+        Log.d(NetworkCellularGroupProvider.name, "Hide primary sim")
     }
 
     if (state.value) {
-        val coroutineScope = rememberCoroutineScope()
-        var context = LocalContext.current
         val telephonyManagerForNonDds: TelephonyManager? =
                 context.getSystemService(TelephonyManager::class.java)
                         ?.createForSubscriptionId(nonDds.intValue)
@@ -305,44 +342,27 @@
         }
 
         Category(title = stringResource(id = R.string.primary_sim_title)) {
-            createPrimarySimListPreference(
+            CreatePrimarySimListPreference(
                     stringResource(id = R.string.primary_sim_calls_title),
                     callsAndSmsList,
                     callsSelectedId,
                     ImageVector.vectorResource(R.drawable.ic_phone),
-            ) {
-                callsSelectedId.intValue = it
-                coroutineScope.launch {
-                    setDefaultVoice(subscriptionManager, it)
-                }
-            }
-            createPrimarySimListPreference(
+                    actionSetCalls
+            )
+            CreatePrimarySimListPreference(
                     stringResource(id = R.string.primary_sim_texts_title),
                     callsAndSmsList,
                     textsSelectedId,
                     Icons.AutoMirrored.Outlined.Message,
-            ) {
-                textsSelectedId.intValue = it
-                coroutineScope.launch {
-                    setDefaultSms(subscriptionManager, it)
-                }
-            }
-            createPrimarySimListPreference(
+                    actionSetTexts
+            )
+            CreatePrimarySimListPreference(
                     stringResource(id = R.string.mobile_data_settings_title),
                     dataList,
                     mobileDataSelectedId,
                     Icons.Outlined.DataUsage,
-            ) {
-                mobileDataSelectedId.intValue = it
-                coroutineScope.launch {
-                    // TODO: to fix the WifiPickerTracker crash when create
-                    //       the wifiPickerTrackerHelper
-                    setDefaultData(context,
-                            subscriptionManager,
-                            null/*wifiPickerTrackerHelper*/,
-                            it)
-                }
-            }
+                    actionSetMobileData
+            )
         }
 
         val autoDataTitle = stringResource(id = R.string.primary_sim_automatic_data_title)
@@ -351,25 +371,18 @@
             object : SwitchPreferenceModel {
                 override val title = autoDataTitle
                 override val summary = { autoDataSummary }
-                override val changeable: () -> Boolean = {
-                    nonDds.intValue != SubscriptionManager.INVALID_SUBSCRIPTION_ID
-                }
                 override val checked = {
-                    coroutineScope.launch {
-                        withContext(Dispatchers.Default) {
-                            automaticDataChecked.value = telephonyManagerForNonDds != null
-                                    && telephonyManagerForNonDds.isMobileDataPolicyEnabled(
-                                    TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)
+                    if (nonDds.intValue != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                        coroutineScope.launch {
+                            automaticDataChecked.value = getAutomaticData(telephonyManagerForNonDds)
                         }
                     }
                     automaticDataChecked.value
                 }
-                override val onCheckedChange: ((Boolean) -> Unit)? =
-                        { newChecked: Boolean ->
-                            coroutineScope.launch {
-                                setAutomaticData(telephonyManagerForNonDds, newChecked)
-                            }
-                        }
+                override val onCheckedChange: ((Boolean) -> Unit)? = {
+                    automaticDataChecked.value = it
+                    actionSetAutoDataSwitch(it)
+                }
             }
         })
     }
@@ -428,19 +441,19 @@
     return MobileNetworkUtils.showEuiccSettings(context)
 }
 
-private suspend fun setDefaultVoice(
+suspend fun setDefaultVoice(
         subscriptionManager: SubscriptionManager?,
         subId: Int): Unit = withContext(Dispatchers.Default) {
     subscriptionManager?.setDefaultVoiceSubscriptionId(subId)
 }
 
-private suspend fun setDefaultSms(
+suspend fun setDefaultSms(
         subscriptionManager: SubscriptionManager?,
         subId: Int): Unit = withContext(Dispatchers.Default) {
     subscriptionManager?.setDefaultSmsSubId(subId)
 }
 
-private suspend fun setDefaultData(context: Context,
+suspend fun setDefaultData(context: Context,
                                    subscriptionManager: SubscriptionManager?,
                                    wifiPickerTrackerHelper: WifiPickerTrackerHelper?,
                                    subId: Int): Unit = withContext(Dispatchers.Default) {
@@ -455,11 +468,22 @@
         wifiPickerTrackerHelper.setCarrierNetworkEnabled(true)
     }
 }
+suspend fun getAutomaticData(telephonyManagerForNonDds: TelephonyManager?): Boolean =
+    withContext(Dispatchers.Default) {
+        telephonyManagerForNonDds != null
+            && telephonyManagerForNonDds.isMobileDataPolicyEnabled(
+            TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)
+    }
 
-private suspend fun setAutomaticData(telephonyManager: TelephonyManager?, newState: Boolean): Unit =
-        withContext(Dispatchers.Default) {
-            telephonyManager?.setMobileDataPolicyEnabled(
-                    TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
-                    newState)
-            //TODO: setup backup calling
-        }
\ No newline at end of file
+suspend fun setAutomaticData(telephonyManager: TelephonyManager?, newState: Boolean): Unit =
+    withContext(Dispatchers.Default) {
+        Log.d(
+            "NetworkCellularGroupProvider",
+            "setAutomaticData: MOBILE_DATA_POLICY_AUTO_DATA_SWITCH as $newState"
+        )
+        telephonyManager?.setMobileDataPolicyEnabled(
+            TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
+            newState
+        )
+        //TODO: setup backup calling
+    }
\ No newline at end of file
diff --git a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
index 4cb04b6..e88c5c7 100644
--- a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
@@ -27,11 +27,9 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
 import com.android.settings.R
 import com.android.settings.network.SimOnboardingService
-import com.android.settings.network.SubscriptionUtil
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.widget.dialog.AlertDialogButton
 import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
@@ -74,7 +72,7 @@
         SettingsBody(stringResource(R.string.sim_onboarding_label_sim_msg))
     }
 
-    for (subInfo in onboardingService.getSelectableSubscriptionInfo()) {
+    for (subInfo in onboardingService.getSelectableSubscriptionInfoList()) {
         var titleSimName by remember {
             mutableStateOf(
                 onboardingService.getSubscriptionInfoDisplayName(subInfo)
diff --git a/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt b/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt
index e46dc2e..c60ac88 100644
--- a/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt
@@ -21,6 +21,7 @@
 import android.content.Context
 import android.content.ContextWrapper
 import android.os.Bundle
+import android.util.Log
 import androidx.annotation.VisibleForTesting
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.platform.LocalContext
@@ -31,12 +32,12 @@
 import androidx.navigation.compose.rememberNavController
 import androidx.navigation.navArgument
 import com.android.settings.R
+import com.android.settings.network.SimOnboardingActivity
 import com.android.settings.network.SimOnboardingService
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
-
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
 
@@ -59,7 +60,7 @@
 
     private val owner = createSettingsPage()
     @VisibleForTesting
-    var onboardingService: SimOnboardingService = SimOnboardingService()
+    var onboardingService: SimOnboardingService = SimOnboardingActivity.onboardingService
 
     fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = owner)
         .setUiLayoutFn {
@@ -72,18 +73,12 @@
 
     @Composable
     override fun Page(arguments: Bundle?) {
-        initServiceData(arguments!!.getInt(SUB_ID))
         PageImpl(onboardingService,rememberNavController())
     }
 
     fun getRoute(
         subId: Int
     ): String = "${name}/$subId"
-
-    @Composable
-    fun initServiceData(targetSubId: Int) {
-        onboardingService.initData(targetSubId, LocalContext.current)
-    }
 }
 
 private fun Context.getActivity(): Activity? = when (this) {
@@ -95,7 +90,10 @@
 @Composable
 fun PageImpl(onboardingService:SimOnboardingService,navHostController: NavHostController) {
     val context = LocalContext.current
-    var previousPageOfOnboarding: () -> Unit = { context.getActivity()?.finish() }
+    var finishOnboarding: () -> Unit = {
+        context.getActivity()?.finish()
+        onboardingService.callback(SimOnboardingActivity.CALLBACK_FINISH)
+    }
 
     NavHost(
         navController = navHostController,
@@ -103,31 +101,32 @@
     ) {
         composable(route = SimOnboardingScreen.LabelSim.name) {
             val nextPage =
-                // Adding more conditions
-                if (onboardingService.isMultipleEnabledProfilesSupported) {
+                if (onboardingService.isMultipleEnabledProfilesSupported && onboardingService.isAllOfSlotAssigned) {
                     SimOnboardingScreen.SelectSim.name
                 } else {
+                    onboardingService.addCurrentItemForSelectedSim()
                     SimOnboardingScreen.PrimarySim.name
                 }
             SimOnboardingLabelSimImpl(
                 nextAction = { navHostController.navigate(nextPage) },
-                cancelAction = previousPageOfOnboarding,
+                cancelAction = finishOnboarding,
                 onboardingService = onboardingService
             )
         }
         composable(route = SimOnboardingScreen.PrimarySim.name) {
             SimOnboardingPrimarySimImpl(
                 nextAction = {
-                    //go back and activate sim
+                    onboardingService.callback(SimOnboardingActivity.CALLBACK_ONBOARDING_COMPLETE)
+                    context.getActivity()?.finish()
                 },
-                cancelAction = previousPageOfOnboarding,
+                cancelAction = finishOnboarding,
                 onboardingService = onboardingService
             )
         }
         composable(route = SimOnboardingScreen.SelectSim.name) {
             SimOnboardingSelectSimImpl(
                 nextAction = { navHostController.navigate(SimOnboardingScreen.PrimarySim.name) },
-                cancelAction = previousPageOfOnboarding,
+                cancelAction = finishOnboarding,
                 onboardingService = onboardingService
             )
         }
diff --git a/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt b/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
index 5752a4f..999abb4 100644
--- a/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
@@ -16,32 +16,25 @@
 
 package com.android.settings.spa.network
 
+import android.telephony.SubscriptionManager
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.automirrored.outlined.Message
-import androidx.compose.material.icons.outlined.DataUsage
 import androidx.compose.material.icons.outlined.SignalCellularAlt
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.MutableIntState
-import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableIntStateOf
-import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.res.vectorResource
 import com.android.settings.R
 import com.android.settings.network.SimOnboardingService
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.widget.preference.ListPreference
 import com.android.settingslib.spa.widget.preference.ListPreferenceModel
 import com.android.settingslib.spa.widget.preference.ListPreferenceOption
-import com.android.settingslib.spa.widget.preference.SwitchPreference
-import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import com.android.settingslib.spa.widget.scaffold.BottomAppBarButton
 import com.android.settingslib.spa.widget.scaffold.SuwScaffold
 import com.android.settingslib.spa.widget.ui.SettingsBody
@@ -68,84 +61,54 @@
             cancelAction
         ),
     ) {
-        primarySimBody(onboardingService)
-    }
-}
-
-@Composable
-private fun primarySimBody(onboardingService: SimOnboardingService) {
-    //TODO: Load the status from the frameworks
-    var callsSelectedId = rememberSaveable { mutableIntStateOf(1) }
-    var textsSelectedId = rememberSaveable { mutableIntStateOf(1) }
-    var mobileDataSelectedId = rememberSaveable { mutableIntStateOf(1) }
-    var automaticDataChecked by rememberSaveable { mutableStateOf(true) }
-
-    Column(Modifier.padding(SettingsDimension.itemPadding)) {
-        SettingsBody(stringResource(id = R.string.sim_onboarding_primary_sim_msg))
-    }
-    var selectableSubscriptionInfo = onboardingService.getSelectableSubscriptionInfo()
-    var list = listOf(ListPreferenceOption(id = -1, text = "Loading"))
-    if (selectableSubscriptionInfo.size >= 2) {
-        list = listOf(
-            ListPreferenceOption(
-                id = selectableSubscriptionInfo[0].subscriptionId,
-                text = "${selectableSubscriptionInfo[0].displayName}"
-            ),
-            ListPreferenceOption(
-                id = selectableSubscriptionInfo[1].subscriptionId,
-                text = "${selectableSubscriptionInfo[1].displayName}"
-            ),
-            ListPreferenceOption(
-                id = -1,
-                text = stringResource(id = R.string.sim_calls_ask_first_prefs_title)
-            ),
-        )
-    } else {
-        // set all of primary sim items' enable as false and showing that sim.
-    }
-    createPrimarySimListPreference(
-        stringResource(id = R.string.primary_sim_calls_title),
-        list,
-        callsSelectedId,
-        ImageVector.vectorResource(R.drawable.ic_phone),
-        onIdSelected = { callsSelectedId.intValue = it }
-    )
-    createPrimarySimListPreference(
-        stringResource(id = R.string.primary_sim_texts_title),
-        list,
-        textsSelectedId,
-        Icons.AutoMirrored.Outlined.Message,
-        onIdSelected = { textsSelectedId.intValue = it }
-    )
-
-    createPrimarySimListPreference(
-            stringResource(id = R.string.mobile_data_settings_title),
-            list,
-            mobileDataSelectedId,
-        Icons.Outlined.DataUsage,
-            onIdSelected = { mobileDataSelectedId.intValue = it }
-    )
-
-    val autoDataTitle = stringResource(id = R.string.primary_sim_automatic_data_title)
-    val autoDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg)
-    SwitchPreference(remember {
-        object : SwitchPreferenceModel {
-            override val title = autoDataTitle
-            override val summary = { autoDataSummary }
-            override val checked = { automaticDataChecked }
-            override val onCheckedChange =
-                { newChecked: Boolean -> automaticDataChecked = newChecked }
+        val callsSelectedId = rememberSaveable {
+            mutableIntStateOf(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
         }
-    })
+        val textsSelectedId = rememberSaveable {
+            mutableIntStateOf(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+        }
+        val mobileDataSelectedId = rememberSaveable {
+            mutableIntStateOf(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+        }
+        val nonDdsRemember = rememberSaveable {
+            mutableIntStateOf(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+        }
+
+        Column(Modifier.padding(SettingsDimension.itemPadding)) {
+            SettingsBody(stringResource(id = R.string.sim_onboarding_primary_sim_msg))
+        }
+
+        var selectedSubscriptionInfoList = onboardingService.getSelectedSubscriptionInfoList()
+        callsSelectedId.intValue = onboardingService.targetPrimarySimCalls
+        textsSelectedId.intValue = onboardingService.targetPrimarySimTexts
+        mobileDataSelectedId.intValue = onboardingService.targetPrimarySimMobileData
+        PrimarySimSectionImpl(
+            subscriptionInfoList = selectedSubscriptionInfoList,
+            callsSelectedId = callsSelectedId,
+            textsSelectedId = textsSelectedId,
+            mobileDataSelectedId = mobileDataSelectedId,
+            nonDds = nonDdsRemember,
+            actionSetCalls = {
+                callsSelectedId.intValue = it
+                onboardingService.targetPrimarySimCalls = it},
+            actionSetTexts = {
+                textsSelectedId.intValue = it
+                onboardingService.targetPrimarySimTexts = it},
+            actionSetMobileData = {
+                mobileDataSelectedId.intValue = it
+                onboardingService.targetPrimarySimMobileData = it},
+            actionSetAutoDataSwitch = {
+                onboardingService.targetPrimarySimAutoDataSwitch = it},
+        )
+    }
 }
 
 @Composable
-fun createPrimarySimListPreference(
+fun CreatePrimarySimListPreference(
         title: String,
         list: List<ListPreferenceOption>,
         selectedId: MutableIntState,
         icon: ImageVector,
-        enable: Boolean = true,
         onIdSelected: (id: Int) -> Unit
 ) = ListPreference(remember {
     object : ListPreferenceModel {
@@ -156,7 +119,5 @@
         override val icon = @Composable {
             SettingsIcon(icon)
         }
-        override val enabled: () -> Boolean
-            get() = { enable }
     }
 })
\ No newline at end of file
diff --git a/src/com/android/settings/spa/network/SimOnboardingSelectSim.kt b/src/com/android/settings/spa/network/SimOnboardingSelectSim.kt
index 1955d13..5e71b12 100644
--- a/src/com/android/settings/spa/network/SimOnboardingSelectSim.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingSelectSim.kt
@@ -16,24 +16,23 @@
 
 package com.android.settings.spa.network
 
+import android.util.Log
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.padding
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.SignalCellularAlt
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
 import com.android.settings.R
 import com.android.settings.network.SimOnboardingService
+import com.android.settings.sim.SimDialogActivity
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.widget.preference.CheckboxPreference
 import com.android.settingslib.spa.widget.preference.CheckboxPreferenceModel
-
 import com.android.settingslib.spa.widget.scaffold.BottomAppBarButton
 import com.android.settingslib.spa.widget.scaffold.SuwScaffold
 import com.android.settingslib.spa.widget.ui.SettingsBody
@@ -68,22 +67,38 @@
     Column(Modifier.padding(SettingsDimension.itemPadding)) {
         SettingsBody(stringResource(id = R.string.sim_onboarding_select_sim_msg))
     }
-    for (subInfo in onboardingService.getSelectableSubscriptionInfo()) {
+    var isFinished = rememberSaveable { mutableStateOf(false) }
+    isFinished.value = onboardingService.isSimSelectionFinished
+    for (subInfo in onboardingService.getSelectableSubscriptionInfoList()) {
         var title = onboardingService.getSubscriptionInfoDisplayName(subInfo)
         var summaryNumber =
             subInfo.number // TODO using the SubscriptionUtil.getFormattedPhoneNumber
-        var changeable = subInfo.isActive
-        var checked by rememberSaveable { mutableStateOf(!subInfo.isActive) }
+        var checked = rememberSaveable {
+            mutableStateOf(
+                onboardingService.getSelectedSubscriptionInfoList().contains(subInfo)
+            )
+        }
 
         CheckboxPreference(remember {
             object : CheckboxPreferenceModel {
                 override val title = title
                 override val summary: () -> String
                     get() = { summaryNumber }
-                override val checked = { checked }
-                override val changeable = { changeable }
-                override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
+                override val checked = { checked.value }
+                override val onCheckedChange = { newChecked: Boolean ->
+                    checked.value = newChecked
+                    if (newChecked) {
+                        onboardingService.addItemForSelectedSim(subInfo)
+                    } else {
+                        onboardingService.removeItemForSelectedSim(subInfo)
+                    }
+                    isFinished.value = onboardingService.isSimSelectionFinished
+                }
+                override val changeable = {
+                    subInfo.isActive
+                        && (!isFinished.value || (isFinished.value && checked.value))
+                }
             }
         })
     }
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
index 0131330..db4c359 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
@@ -134,6 +134,11 @@
     }
 
     @Test
+    public void testIsAdaptiveChargingSupported_returnFalse() {
+        assertThat(mPowerFeatureProvider.isAdaptiveChargingSupported()).isFalse();
+    }
+
+    @Test
     public void testGetResumeChargeIntentWithoutDockDefender_returnNull() {
         assertThat(mPowerFeatureProvider.getResumeChargeIntent(false)).isNull();
     }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceControllerTest.java
new file mode 100644
index 0000000..f7469c7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceControllerTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.fuelgauge.batterytip;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = SettingsShadowResources.class)
+public class BatteryManagerPreferenceControllerTest {
+    private static final int ON = 1;
+    private static final int OFF = 0;
+
+    @Mock
+    private AppOpsManager mAppOpsManager;
+
+    private Context mContext;
+    private Preference mPreference;
+    private FakeFeatureFactory mFeatureFactory;
+    private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+    private BatteryManagerPreferenceController mController;
+
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        mPreference = new Preference(mContext);
+        mController = new BatteryManagerPreferenceController(mContext);
+        mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
+    }
+
+    @Test
+    public void updateState_smartBatteryWithRestrictApps_showSummary() {
+        mController.updateSummary(mPreference, 2);
+
+        assertThat(mPreference.getSummary()).isEqualTo("2 apps restricted");
+    }
+
+    @Test
+    public void updateState_smartBatteryWithoutRestriction_showSummary() {
+        when(mPowerUsageFeatureProvider.isSmartBatterySupported()).thenReturn(true);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, ON);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.getSummary()).isEqualTo("Detecting when apps drain battery");
+    }
+
+    @Test
+    public void getAvailabilityStatus_supportBatteryManager_showPrefPage() {
+        SettingsShadowResources.overrideResource(
+                R.bool.config_battery_manager_consider_ac, true);
+        when(mPowerUsageFeatureProvider.isBatteryManagerSupported()).thenReturn(true);
+        when(mPowerUsageFeatureProvider.isAdaptiveChargingSupported()).thenReturn(true);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BatteryManagerPreferenceController.AVAILABLE_UNSEARCHABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_notSupportBatteryManager_notShowPrefPage() {
+        when(mPowerUsageFeatureProvider.isBatteryManagerSupported()).thenReturn(false);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BatteryManagerPreferenceController.UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_supportBatteryManagerWithoutAC_notShowPrefPage() {
+        SettingsShadowResources.overrideResource(
+                R.bool.config_battery_manager_consider_ac, true);
+        when(mPowerUsageFeatureProvider.isBatteryManagerSupported()).thenReturn(true);
+        when(mPowerUsageFeatureProvider.isAdaptiveChargingSupported()).thenReturn(false);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BatteryManagerPreferenceController.UNSUPPORTED_ON_DEVICE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_ignoreBatteryManagerWithoutAC_showPrefPage() {
+        SettingsShadowResources.overrideResource(
+                R.bool.config_battery_manager_consider_ac, false);
+        when(mPowerUsageFeatureProvider.isBatteryManagerSupported()).thenReturn(true);
+        when(mPowerUsageFeatureProvider.isAdaptiveChargingSupported()).thenReturn(false);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BatteryManagerPreferenceController.AVAILABLE_UNSEARCHABLE);
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
index dace5e9..8e12b20 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
@@ -108,7 +108,7 @@
             on { targetSubInfo }.doReturn(SUB_INFO_1)
             on { availableSubInfoList }.doReturn(listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_3))
             on { activeSubInfoList }.doReturn(listOf(SUB_INFO_2, SUB_INFO_3))
-            on { getSelectableSubscriptionInfo() }.doReturn(
+            on { getSelectableSubscriptionInfoList() }.doReturn(
                 listOf(
                     SUB_INFO_1,
                     SUB_INFO_2,
@@ -139,7 +139,7 @@
             on { targetSubInfo }.doReturn(SUB_INFO_1)
             on { availableSubInfoList }.doReturn(listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_3))
             on { activeSubInfoList }.doReturn(listOf(SUB_INFO_2, SUB_INFO_3))
-            on { getSelectableSubscriptionInfo() }.doReturn(
+            on { getSelectableSubscriptionInfoList() }.doReturn(
                 listOf(
                     SUB_INFO_1,
                     SUB_INFO_2,
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt
index 35f1968..82dba76 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt
@@ -91,6 +91,7 @@
     fun simOnboardingPage_nextAction_fromLabelSimToSelectSim() {
         mockSimOnboardingService.stub {
             on { isMultipleEnabledProfilesSupported }.thenReturn(true)
+            on { isAllOfSlotAssigned }.thenReturn(true)
         }
 
         composeTestRule.setContent {
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
index 5d7465f..45667ef 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
@@ -108,7 +108,7 @@
             on { targetSubInfo }.doReturn(SUB_INFO_1)
             on { availableSubInfoList }.doReturn(listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_3))
             on { activeSubInfoList }.doReturn(listOf(SUB_INFO_2, SUB_INFO_3))
-            on { getSelectableSubscriptionInfo() }.doReturn(
+            on { getSelectableSubscriptionInfoList() }.doReturn(
                 listOf(
                     SUB_INFO_1,
                     SUB_INFO_2,
diff --git a/tests/unit/src/com/android/settings/applications/credentials/CredentialsPickerActivityTest.java b/tests/unit/src/com/android/settings/applications/credentials/CredentialsPickerActivityTest.java
new file mode 100644
index 0000000..044c23d
--- /dev/null
+++ b/tests/unit/src/com/android/settings/applications/credentials/CredentialsPickerActivityTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.applications.credentials;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.google.common.collect.Lists;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class CredentialsPickerActivityTest {
+
+    @Mock private UserManager mUserManager;
+
+    private Context mMockContext;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mMockContext = spy(ApplicationProvider.getApplicationContext());
+        when(mMockContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
+    }
+
+    @Test
+    public void testInjectFragmentIntoIntent_normalProfile() {
+        Intent intent = new Intent();
+        CredentialsPickerActivity.injectFragmentIntoIntent(mMockContext, intent);
+        assertThat(intent.getStringExtra(CredentialsPickerActivity.EXTRA_SHOW_FRAGMENT))
+                .isEqualTo(DefaultCombinedPicker.class.getName());
+    }
+
+    @Test
+    public void testInjectFragmentIntoIntent_workProfile() {
+        Intent intent = new Intent();
+
+        // Simulate managed / work profile.
+        when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
+        assertThat(DefaultCombinedPickerWork.isUserHandledByFragment(mUserManager, 10)).isTrue();
+
+        CredentialsPickerActivity.injectFragmentIntoIntent(mMockContext, intent);
+        assertThat(intent.getStringExtra(CredentialsPickerActivity.EXTRA_SHOW_FRAGMENT))
+                .isEqualTo(DefaultCombinedPickerWork.class.getName());
+    }
+
+    @Test
+    public void testInjectFragmentIntoIntent_privateProfile() {
+        Intent intent = new Intent();
+
+        // Simulate private profile.
+        UserHandle privateUser = new UserHandle(100);
+        when(mUserManager.getUserInfo(100))
+                .thenReturn(new UserInfo(100, "", "", 0, UserManager.USER_TYPE_PROFILE_PRIVATE));
+        when(mUserManager.getUserProfiles()).thenReturn(Lists.newArrayList(privateUser));
+        assertThat(DefaultCombinedPickerPrivate.isUserHandledByFragment(mUserManager)).isTrue();
+
+        CredentialsPickerActivity.injectFragmentIntoIntent(mMockContext, intent);
+        assertThat(intent.getStringExtra(CredentialsPickerActivity.EXTRA_SHOW_FRAGMENT))
+                .isEqualTo(DefaultCombinedPickerPrivate.class.getName());
+    }
+}
diff --git a/tests/unit/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceControllerTest.java
index 301fcfa..d02240e 100644
--- a/tests/unit/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceControllerTest.java
@@ -87,16 +87,14 @@
 
     @Test
     public void ensureSettingsActivityIntentCreatedSuccessfully() {
-        DefaultCombinedPreferenceController dcpc =
-                new DefaultCombinedPreferenceController(mContext);
-
         // Ensure that the settings activity is only created if we haved the right combination
         // of package and class name.
-        assertThat(dcpc.createSettingsActivityIntent(null, null)).isNull();
-        assertThat(dcpc.createSettingsActivityIntent("", null)).isNull();
-        assertThat(dcpc.createSettingsActivityIntent("", "")).isNull();
-        assertThat(dcpc.createSettingsActivityIntent("com.test", "")).isNull();
-        assertThat(dcpc.createSettingsActivityIntent("com.test", "ClassName")).isNotNull();
+        assertThat(CombinedProviderInfo.createSettingsActivityIntent(null, null)).isNull();
+        assertThat(CombinedProviderInfo.createSettingsActivityIntent("", null)).isNull();
+        assertThat(CombinedProviderInfo.createSettingsActivityIntent("", "")).isNull();
+        assertThat(CombinedProviderInfo.createSettingsActivityIntent("com.test", "")).isNull();
+        assertThat(CombinedProviderInfo.createSettingsActivityIntent("com.test", "ClassName"))
+                .isNotNull();
     }
 
     @Test
@@ -112,13 +110,13 @@
 
         // Update the preference to use the provider and make sure the view
         // was updated.
-        dcpc.updatePreferenceForProvider(ppp, "App Name", "Subtitle", appIcon, null);
+        dcpc.updatePreferenceForProvider(ppp, "App Name", "Subtitle", appIcon, null, null);
         assertThat(ppp.getTitle().toString()).isEqualTo("App Name");
         assertThat(ppp.getSummary().toString()).isEqualTo("Subtitle");
         assertThat(ppp.getIcon()).isEqualTo(appIcon);
 
         // Set the preference back to none and make sure the view was updated.
-        dcpc.updatePreferenceForProvider(ppp, null, null, null, null);
+        dcpc.updatePreferenceForProvider(ppp, null, null, null, null, null);
         assertThat(ppp.getTitle().toString()).isEqualTo("None");
         assertThat(ppp.getSummary()).isNull();
         assertThat(ppp.getIcon()).isNull();
diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImplTest.kt b/tests/unit/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImplTest.kt
new file mode 100644
index 0000000..794cfec
--- /dev/null
+++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImplTest.kt
@@ -0,0 +1,201 @@
+/*
+ * 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.biometrics.fingerprint.feature
+
+import android.animation.Animator
+import android.content.Context
+import android.hardware.fingerprint.FingerprintManager
+import android.view.View
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_CENTER
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_FINGERTIP
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_LEFT_EDGE
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_NO_ANIMATION
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_RIGHT_EDGE
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.STAGE_UNKNOWN
+import com.google.common.truth.Truth.assertThat
+import kotlin.math.roundToInt
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Spy
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.Mockito.`when` as whenever
+
+@RunWith(AndroidJUnit4::class)
+class SfpsEnrollmentFeatureImplTest {
+    @get:Rule
+    val mockito: MockitoRule = MockitoJUnit.rule()
+
+    @Spy
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    private val settingsPackageName = "com.android.settings"
+
+    private lateinit var settingsContext: Context
+
+    @Mock
+    private lateinit var mockFingerprintManager: FingerprintManager
+
+    private val mSfpsEnrollmentFeatureImpl: SfpsEnrollmentFeatureImpl = SfpsEnrollmentFeatureImpl()
+
+    @Before
+    fun setUp() {
+        assertThat(mSfpsEnrollmentFeatureImpl).isInstanceOf(SfpsEnrollmentFeatureImpl::class.java)
+        whenever(context.getSystemService(FingerprintManager::class.java))
+            .thenReturn(mockFingerprintManager)
+        doReturn(0f).`when`(mockFingerprintManager).getEnrollStageThreshold(0)
+        doReturn(0.36f).`when`(mockFingerprintManager).getEnrollStageThreshold(1)
+        doReturn(0.52f).`when`(mockFingerprintManager).getEnrollStageThreshold(2)
+        doReturn(0.76f).`when`(mockFingerprintManager).getEnrollStageThreshold(3)
+        doReturn(1f).`when`(mockFingerprintManager).getEnrollStageThreshold(4)
+        settingsContext = context.createPackageContext(settingsPackageName, 0)
+    }
+
+    @Test
+    fun testGetEnrollStageThreshold() {
+        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 0)).isEqualTo(0f)
+        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 1)).isEqualTo(0.36f)
+        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 2)).isEqualTo(0.52f)
+        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 3)).isEqualTo(0.76f)
+        assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 4)).isEqualTo(1f)
+    }
+
+    @Test
+    fun testGetHelpAnimator() {
+        val mockView: View = mock(View::class.java)
+        val animator: Animator = mSfpsEnrollmentFeatureImpl.getHelpAnimator(mockView)
+        assertThat(animator.duration).isEqualTo(550)
+    }
+
+    @Test
+    fun testGetCurrentSfpsEnrollStage() {
+        assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(0, null))
+            .isEqualTo(STAGE_UNKNOWN)
+        val mapper = { i: Int ->
+            (25 * mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, i)).roundToInt()
+        }
+        assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(-1, mapper))
+            .isEqualTo(SFPS_STAGE_NO_ANIMATION)
+        assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(0, mapper))
+            .isEqualTo(SFPS_STAGE_CENTER)
+        assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(9, mapper))
+            .isEqualTo(SFPS_STAGE_FINGERTIP)
+        assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(13, mapper))
+            .isEqualTo(SFPS_STAGE_LEFT_EDGE)
+        assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(19, mapper))
+            .isEqualTo(SFPS_STAGE_RIGHT_EDGE)
+        assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(25, mapper))
+            .isEqualTo(SFPS_STAGE_RIGHT_EDGE)
+    }
+
+    @Test
+    fun testGetFeaturedStageHeaderResource() {
+        val type = "string"
+        assertThat(
+            mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_NO_ANIMATION)
+        ).isEqualTo(
+            settingsContext.resources.getIdentifier(
+                "security_settings_fingerprint_enroll_repeat_title",
+                type,
+                settingsPackageName)
+        )
+        assertThat(
+            mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_CENTER)
+        ).isEqualTo(
+            settingsContext.resources.getIdentifier(
+                "security_settings_sfps_enroll_finger_center_title",
+                type,
+                settingsPackageName)
+        )
+        assertThat(
+            mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_FINGERTIP)
+        ).isEqualTo(
+            settingsContext.resources.getIdentifier(
+                "security_settings_sfps_enroll_fingertip_title",
+                type,
+                settingsPackageName)
+        )
+        assertThat(
+            mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_LEFT_EDGE)
+        ).isEqualTo(
+            settingsContext.resources.getIdentifier(
+                "security_settings_sfps_enroll_left_edge_title",
+                type,
+                settingsPackageName)
+        )
+        assertThat(
+            mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_RIGHT_EDGE)
+        ).isEqualTo(
+            settingsContext.resources.getIdentifier(
+                "security_settings_sfps_enroll_right_edge_title",
+                type,
+                settingsPackageName)
+        )
+    }
+
+    @Test
+    fun testGetSfpsEnrollLottiePerStage() {
+        val type = "raw"
+        assertThat(
+            mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_NO_ANIMATION)
+        ).isEqualTo(
+            settingsContext.resources.getIdentifier(
+                "sfps_lottie_no_animation",
+                type,
+                settingsPackageName)
+        )
+        assertThat(
+            mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_CENTER)
+        ).isEqualTo(
+            settingsContext.resources.getIdentifier(
+                "sfps_lottie_pad_center",
+                type,
+                settingsPackageName)
+        )
+        assertThat(
+            mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_FINGERTIP)
+        ).isEqualTo(
+            settingsContext.resources.getIdentifier(
+                "sfps_lottie_tip",
+                type,
+                settingsPackageName)
+        )
+        assertThat(
+            mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_LEFT_EDGE)
+        ).isEqualTo(
+            settingsContext.resources.getIdentifier(
+                "sfps_lottie_left_edge",
+                type,
+                settingsPackageName)
+        )
+        assertThat(
+            mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_RIGHT_EDGE)
+        ).isEqualTo(
+            settingsContext.resources.getIdentifier(
+                "sfps_lottie_right_edge",
+                type,
+                settingsPackageName)
+        )
+    }
+}
\ No newline at end of file
diff --git a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressFeminineControllerTest.java b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressFeminineControllerTest.java
index c04e5f9..d1e3078 100644
--- a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressFeminineControllerTest.java
+++ b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressFeminineControllerTest.java
@@ -97,7 +97,6 @@
 
         selectedPreference.performClick();
 
-        assertThat(selectedPreference.getKey()).isEqualTo(KEY_FEMININE);
         assertThat(selectedPreference.isSelected()).isTrue();
         assertThat(pref.isSelected()).isFalse();
     }
diff --git a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressMasculineControllerTest.java b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressMasculineControllerTest.java
index c2298be..5bf3073 100644
--- a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressMasculineControllerTest.java
+++ b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressMasculineControllerTest.java
@@ -97,7 +97,6 @@
 
         selectedPreference.performClick();
 
-        assertThat(selectedPreference.getKey()).isEqualTo(KEY_MASCULINE);
         assertThat(selectedPreference.isSelected()).isTrue();
         assertThat(pref.isSelected()).isFalse();
     }
diff --git a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNeutralControllerTest.java b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNeutralControllerTest.java
index fb207fc..e83f3cd 100644
--- a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNeutralControllerTest.java
+++ b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNeutralControllerTest.java
@@ -97,7 +97,6 @@
 
         selectedPreference.performClick();
 
-        assertThat(selectedPreference.getKey()).isEqualTo(KEY_NEUTRAL);
         assertThat(selectedPreference.isSelected()).isTrue();
         assertThat(pref.isSelected()).isFalse();
     }
diff --git a/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java b/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java
index 4aae76c..daa2afb 100644
--- a/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java
@@ -34,7 +34,7 @@
 import androidx.preference.PreferenceGroup;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
 import androidx.test.annotation.UiThreadTest;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -275,7 +275,7 @@
             PreferenceGroup group = (PreferenceGroup) mGroupList.getPreference(0);
             assertEquals("group", group.getKey());
             assertEquals(3, group.getPreferenceCount());
-            SwitchPreference groupBlockPref = (SwitchPreference) group.getPreference(0);
+            SwitchPreferenceCompat groupBlockPref = (SwitchPreferenceCompat) group.getPreference(0);
             assertNull(groupBlockPref.getKey());
             assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle().toString());
             assertTrue(groupBlockPref.isChecked());
@@ -297,7 +297,7 @@
             PreferenceGroup group = (PreferenceGroup) mGroupList.getPreference(0);
             assertEquals("group", group.getKey());
             assertEquals(1, group.getPreferenceCount());
-            SwitchPreference groupBlockPref = (SwitchPreference) group.getPreference(0);
+            SwitchPreferenceCompat groupBlockPref = (SwitchPreferenceCompat) group.getPreference(0);
             assertNull(groupBlockPref.getKey());
             assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle().toString());
             assertFalse(groupBlockPref.isChecked());
@@ -311,7 +311,7 @@
             PreferenceGroup group = (PreferenceGroup) mGroupList.getPreference(0);
             assertEquals("group", group.getKey());
             assertEquals(3, group.getPreferenceCount());
-            SwitchPreference groupBlockPref = (SwitchPreference) group.getPreference(0);
+            SwitchPreferenceCompat groupBlockPref = (SwitchPreferenceCompat) group.getPreference(0);
             assertNull(groupBlockPref.getKey());
             assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle().toString());
             assertTrue(groupBlockPref.isChecked());