Show a separate tab for the Private Space

This covers all the known Settings pages using the tabbed view model.

https://docs.google.com/document/d/1CdjUjAE84-5ZEPRIfw5KYFjLVHtEZxc_sF0w95su8DA/edit?resourcekey=0-dAACT9HRexY1IyoxMmkVlw#heading=h.58jd58rmznte

Screenshots:
all apps
https://screenshot.googleplex.com/3E5Jm7Pi2JfN64r
with work tab:
https://screenshot.googleplex.com/8egk4yHK5jSENjR

PS Apps Special media management apps
https://screenshot.googleplex.com/BHHafqW7bgUwSGg
with work tab:
https://screenshot.googleplex.com/3cocdhruEmCCh5k

PS Location Services tab view
https://screenshot.googleplex.com/3DqJcT2BFTEpvYT
with work tab:
https://screenshot.googleplex.com/6Avpx6hxSrdGJw5

PS on screen keyboard tab view
https://screenshot.googleplex.com/4FzVNnBWwbUeJNw
with work tab:
https://screenshot.googleplex.com/8E8UhpWq8PL5nxU

PS password account tab view
https://screenshot.googleplex.com/6bDR4AKtth2S3EW
with work tab:
https://screenshot.googleplex.com/9msXV2TdHdJapch

PS storage tab view
https://screenshot.googleplex.com/5Nk2FTxwdmpEv3B
with work tab:
https://screenshot.googleplex.com/79tw2EaWZKfMsnC

PS appl_languages_work
https://screenshot.googleplex.com/3qrREeg3RQdHhhH

Bug: 302278487
Test: manual
Change-Id: I8cd39170827fbe251bc4075ef306206020b3a022
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 87ba77b..464905a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6180,6 +6180,8 @@
     <string name="account_settings_menu_auto_sync_personal">Auto-sync personal data</string>
     <!--  Title for menu option to enable global auto-sync of work account data [CHAR LIMIT=30] -->
     <string name="account_settings_menu_auto_sync_work">Auto-sync work data</string>
+    <!--  Title for menu option to enable global auto-sync of private account data [CHAR LIMIT=30] -->
+    <string name="account_settings_menu_auto_sync_private">Auto-sync private data</string>
 
     <!-- Title for option to change data usage cycle day. [CHAR LIMIT=32] -->
     <string name="data_usage_change_cycle">Change cycle\u2026</string>
diff --git a/res/xml/accounts_private_dashboard_settings.xml b/res/xml/accounts_private_dashboard_settings.xml
new file mode 100644
index 0000000..79bcce9
--- /dev/null
+++ b/res/xml/accounts_private_dashboard_settings.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2023 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<PreferenceScreen
+    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"
+    settings:keywords="@string/keywords_accounts">
+
+    <PreferenceCategory
+        android:key="passwords_category"
+        android:order="10"
+        android:persistent="false"
+        android:title="@string/autofill_passwords"
+        settings:controller="com.android.settings.applications.autofill.PasswordsPreferenceController"
+        settings:keywords="@string/autofill_keywords" />
+
+    <PreferenceCategory
+        android:key="default_service_category"
+        android:order="20"
+        android:title="@string/autofill_app">
+
+        <com.android.settings.widget.GearPreference
+            android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
+            android:key="default_autofill_private"
+            android:title="@string/autofill_app"
+            settings:keywords="@string/autofill_keywords">
+            <extra
+                android:name="for_work"
+                android:value="false" />
+        </com.android.settings.widget.GearPreference>
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:key="dashboard_tile_placeholder"
+        android:order="130"/>
+
+    <SwitchPreference
+        android:key="auto_sync_account_data"
+        android:title="@string/auto_sync_account_title"
+        android:summary="@string/auto_sync_account_summary"
+        android:order="200"
+        settings:allowDividerAbove="true"/>
+
+    <SwitchPreference
+        android:key="auto_sync_private_account_data"
+        android:title="@string/account_settings_menu_auto_sync_private"
+        android:summary="@string/auto_sync_account_summary"
+        android:order="210"/>
+
+</PreferenceScreen>
diff --git a/res/xml/accounts_private_dashboard_settings_credman.xml b/res/xml/accounts_private_dashboard_settings_credman.xml
new file mode 100644
index 0000000..88b2736
--- /dev/null
+++ b/res/xml/accounts_private_dashboard_settings_credman.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<PreferenceScreen
+    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"
+    settings:keywords="@string/keywords_accounts">
+
+    <PreferenceCategory
+        android:key="default_service_category"
+        android:order="10"
+        android:title="@string/credman_chosen_app_title">
+
+        <com.android.settings.widget.GearPreference
+            android:fragment="com.android.settings.applications.credentials.DefaultCombinedPickerPrivate"
+            android:key="default_credman_autofill_private"
+            android:title="@string/credman_chosen_app_title"
+            settings:searchable="false">
+            settings:keywords="@string/credman_autofill_keywords">
+            <extra
+                android:name="for_work"
+                android:value="false" />
+        </com.android.settings.widget.GearPreference>
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:key="credman_category"
+        android:order="20"
+        android:persistent="false"
+        android:title="@string/credman_credentials"
+        settings:controller="com.android.settings.applications.credentials.CredentialManagerPreferenceController"
+        settings:keywords="@string/credman_keywords" />
+
+    <PreferenceCategory
+        android:key="dashboard_tile_placeholder"
+        android:order="130"/>
+
+    <SwitchPreference
+        android:key="auto_sync_account_data"
+        android:title="@string/auto_sync_account_title"
+        android:summary="@string/auto_sync_account_summary"
+        android:order="200"
+        settings:allowDividerAbove="true"/>
+
+    <SwitchPreference
+        android:key="auto_sync_private_account_data"
+        android:title="@string/account_settings_menu_auto_sync_private"
+        android:summary="@string/auto_sync_account_summary"
+        android:order="210"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index b41650c..29eabdb 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -18,6 +18,9 @@
 
 import static android.content.Intent.EXTRA_USER;
 import static android.content.Intent.EXTRA_USER_ID;
+import static android.os.UserManager.USER_TYPE_FULL_SYSTEM;
+import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
+import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE;
 import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
 import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
 
@@ -63,6 +66,7 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Flags;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
 import android.os.RemoteException;
@@ -111,6 +115,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.dashboard.profileselector.ProfileFragmentBridge;
 import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.settingslib.widget.ActionBarShadowController;
 import com.android.settingslib.widget.AdaptiveIcon;
@@ -118,6 +123,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.Set;
 
 public final class Utils extends com.android.settingslib.Utils {
@@ -441,6 +447,38 @@
     }
 
     /**
+     * Returns the profile of userType of the current user or {@code null} if none is found or a
+     * profile exists, but it is disabled.
+     */
+    @Nullable
+    public static UserHandle getProfileOfType(
+            @NonNull UserManager userManager, @ProfileType int userType) {
+        final List<UserHandle> userProfiles = userManager.getUserProfiles();
+        String umUserType = getUmUserType(userType);
+        for (UserHandle profile : userProfiles) {
+            if (profile.getIdentifier() == UserHandle.myUserId()) {
+                continue;
+            }
+            final UserInfo userInfo = userManager.getUserInfo(profile.getIdentifier());
+            if (Objects.equals(umUserType, userInfo.userType)) {
+                return profile;
+            }
+        }
+        return null;
+    }
+
+    private static String getUmUserType(@ProfileType int userType) throws IllegalArgumentException {
+        if (userType == ProfileType.WORK) {
+            return USER_TYPE_PROFILE_MANAGED;
+        } else if (userType == ProfileType.PRIVATE) {
+            return USER_TYPE_PROFILE_PRIVATE;
+        } else if (userType == ProfileType.PERSONAL) {
+            return USER_TYPE_FULL_SYSTEM;
+        }
+        throw new IllegalArgumentException("Cannot get user type for ALL types");
+    }
+
+    /**
      * Returns the managed profile of the current user or {@code null} if none is found. Unlike
      * {@link #getManagedProfile} this method returns enabled and disabled managed profiles.
      */
@@ -479,15 +517,20 @@
         return UserHandle.USER_NULL;
     }
 
-    /** Returns user ID of current user, throws IllegalStateException if it's not available. */
-    public static int getCurrentUserId(UserManager userManager, boolean isWorkProfile)
-            throws IllegalStateException {
-        if (isWorkProfile) {
-            final UserHandle managedUserHandle = getManagedProfile(userManager);
-            if (managedUserHandle == null) {
-                throw new IllegalStateException("Work profile user ID is not available.");
+    /**
+     * Returns user ID of the user of specified type under the current context, throws
+     * IllegalStateException if it's not available.
+     */
+    public static int getCurrentUserIdOfType(
+            @NonNull UserManager userManager,
+            @ProfileType int userType) throws IllegalStateException {
+        if (userType != ProfileType.PERSONAL) {
+            final UserHandle userHandle = getProfileOfType(userManager, userType);
+            if (userHandle == null) {
+                throw new IllegalStateException("User ID of requested profile type is not "
+                        + "available.");
             }
-            return managedUserHandle.getIdentifier();
+            return userHandle.getIdentifier();
         }
         return UserHandle.myUserId();
     }
@@ -1223,8 +1266,10 @@
         List<UserHandle> profiles = userManager.getUserProfiles();
         for (UserHandle userHandle : profiles) {
             UserProperties userProperties = userManager.getUserProperties(userHandle);
-            if (userProperties.getShowInSettings()
-                    == UserProperties.SHOW_IN_SETTINGS_SEPARATE) {
+            if (userProperties.getShowInSettings() == UserProperties.SHOW_IN_SETTINGS_SEPARATE) {
+                if (Flags.allowPrivateProfile() && userProperties.getHideInSettingsInQuietMode()) {
+                    return !userManager.isQuietModeEnabled(userHandle);
+                }
                 return true;
             }
         }
diff --git a/src/com/android/settings/accounts/AccountDashboardFragment.java b/src/com/android/settings/accounts/AccountDashboardFragment.java
index 7816fd7..81aefd9 100644
--- a/src/com/android/settings/accounts/AccountDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDashboardFragment.java
@@ -31,14 +31,17 @@
 import com.android.settings.applications.autofill.PasswordsPreferenceController;
 import com.android.settings.applications.credentials.CredentialManagerPreferenceController;
 import com.android.settings.applications.credentials.DefaultCombinedPreferenceController;
+import com.android.settings.applications.credentials.DefaultPrivateCombinedPreferenceController;
 import com.android.settings.applications.credentials.DefaultWorkCombinedPreferenceController;
 import com.android.settings.applications.defaultapps.DefaultAutofillPreferenceController;
+import com.android.settings.applications.defaultapps.DefaultPrivateAutofillPreferenceController;
 import com.android.settings.applications.defaultapps.DefaultWorkAutofillPreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.users.AutoSyncDataPreferenceController;
 import com.android.settings.users.AutoSyncPersonalDataPreferenceController;
+import com.android.settings.users.AutoSyncPrivateDataPreferenceController;
 import com.android.settings.users.AutoSyncWorkDataPreferenceController;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.search.SearchIndexable;
@@ -111,9 +114,11 @@
         if (CredentialManager.isServiceEnabled(context)) {
             controllers.add(new DefaultCombinedPreferenceController(context));
             controllers.add(new DefaultWorkCombinedPreferenceController(context));
+            controllers.add(new DefaultPrivateCombinedPreferenceController(context));
         } else {
             controllers.add(new DefaultAutofillPreferenceController(context));
             controllers.add(new DefaultWorkAutofillPreferenceController(context));
+            controllers.add(new DefaultPrivateAutofillPreferenceController(context));
         }
     }
 
@@ -132,6 +137,7 @@
         controllers.add(new AutoSyncDataPreferenceController(context, parent));
         controllers.add(new AutoSyncPersonalDataPreferenceController(context, parent));
         controllers.add(new AutoSyncWorkDataPreferenceController(context, parent));
+        controllers.add(new AutoSyncPrivateDataPreferenceController(context, parent));
     }
 
     private static int getPreferenceLayoutResId(Context context) {
diff --git a/src/com/android/settings/accounts/AccountPreferenceController.java b/src/com/android/settings/accounts/AccountPreferenceController.java
index db6a4ae..33b3888 100644
--- a/src/com/android/settings/accounts/AccountPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountPreferenceController.java
@@ -296,14 +296,15 @@
             updateProfileUi(userInfo);
         } else {
             List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
-            final int profilesCount = profiles.size();
-            for (int i = 0; i < profilesCount; i++) {
-                if (profiles.get(i).isManagedProfile()
-                        && (mType & ProfileSelectFragment.ProfileType.WORK) != 0) {
-                    updateProfileUi(profiles.get(i));
-                } else if (!profiles.get(i).isManagedProfile()
-                        && (mType & ProfileSelectFragment.ProfileType.PERSONAL) != 0) {
-                    updateProfileUi(profiles.get(i));
+            for (UserInfo profile : profiles) {
+                if ((profile.isManagedProfile()
+                            && (mType & ProfileSelectFragment.ProfileType.WORK) != 0)
+                        || (profile.isPrivateProfile()
+                            && (mType & ProfileSelectFragment.ProfileType.PRIVATE) != 0)
+                        || (!profile.isManagedProfile()
+                            && !profile.isPrivateProfile()
+                            && (mType & ProfileSelectFragment.ProfileType.PERSONAL) != 0)) {
+                    updateProfileUi(profile);
                 }
             }
         }
diff --git a/src/com/android/settings/accounts/AccountPrivateDashboardFragment.java b/src/com/android/settings/accounts/AccountPrivateDashboardFragment.java
new file mode 100644
index 0000000..9794b4a
--- /dev/null
+++ b/src/com/android/settings/accounts/AccountPrivateDashboardFragment.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accounts;
+
+import static android.provider.Settings.EXTRA_AUTHORITIES;
+
+import static com.android.settings.accounts.AccountDashboardFragment.buildAutofillPreferenceControllers;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.credentials.CredentialManager;
+
+import com.android.settings.R;
+import com.android.settings.applications.autofill.PasswordsPreferenceController;
+import com.android.settings.applications.credentials.CredentialManagerPreferenceController;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
+import com.android.settings.users.AutoSyncDataPreferenceController;
+import com.android.settings.users.AutoSyncPrivateDataPreferenceController;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AccountPrivateDashboardFragment extends DashboardFragment {
+    private static final String TAG = "AccountPrivateFrag";
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.ACCOUNT_PRIVATE;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        if (this.getContext() != null && CredentialManager.isServiceEnabled(this.getContext())) {
+            return R.xml.accounts_private_dashboard_settings_credman;
+        }
+        return R.xml.accounts_private_dashboard_settings;
+    }
+
+    @Override
+    public int getHelpResource() {
+        return R.string.help_url_user_and_account_dashboard;
+    }
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        if (CredentialManager.isServiceEnabled(context)) {
+            CredentialManagerPreferenceController cmpp =
+                    use(CredentialManagerPreferenceController.class);
+            CredentialManagerPreferenceController.Delegate delegate =
+                    new CredentialManagerPreferenceController.Delegate() {
+                        public void setActivityResult(int resultCode) {
+                            getActivity().setResult(resultCode);
+                        }
+                        public void forceDelegateRefresh() {
+                            forceUpdatePreferences();
+                        }
+                    };
+            cmpp.init(this, getFragmentManager(), getIntent(), delegate, /*isWorkProfile=*/false);
+        } else {
+            getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
+        }
+    }
+
+    @Override
+    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+        final List<AbstractPreferenceController> controllers = new ArrayList<>();
+        buildAutofillPreferenceControllers(context, controllers);
+        final String[] authorities = getIntent().getStringArrayExtra(EXTRA_AUTHORITIES);
+        buildAccountPreferenceControllers(context, authorities, controllers);
+        return controllers;
+    }
+
+    private void buildAccountPreferenceControllers(
+            Context context,
+            String[] authorities,
+            List<AbstractPreferenceController> controllers) {
+        final AccountPreferenceController accountPrefController =
+                new AccountPreferenceController(
+                        context,
+                        this,
+                        authorities,
+                        ProfileSelectFragment.ProfileType.PRIVATE);
+        controllers.add(accountPrefController);
+        controllers.add(new AutoSyncDataPreferenceController(context, this));
+        controllers.add(new AutoSyncPrivateDataPreferenceController(context, this));
+    }
+}
diff --git a/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java b/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java
index 03a551f..73fef1b 100644
--- a/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java
+++ b/src/com/android/settings/applications/autofill/PasswordsPreferenceController.java
@@ -17,6 +17,7 @@
 package com.android.settings.applications.autofill;
 
 import static android.app.admin.DevicePolicyResources.Strings.Settings.AUTO_SYNC_PERSONAL_DATA;
+import static android.app.admin.DevicePolicyResources.Strings.Settings.AUTO_SYNC_PRIVATE_DATA;
 import static android.app.admin.DevicePolicyResources.Strings.Settings.AUTO_SYNC_WORK_DATA;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.service.autofill.AutofillService.EXTRA_RESULT;
@@ -122,6 +123,8 @@
                 AUTO_SYNC_PERSONAL_DATA, R.string.account_settings_menu_auto_sync_personal);
         replaceEnterpriseStringTitle(screen, "auto_sync_work_account_data",
                 AUTO_SYNC_WORK_DATA, R.string.account_settings_menu_auto_sync_work);
+        replaceEnterpriseStringTitle(screen, "auto_sync_private_account_data",
+                AUTO_SYNC_PRIVATE_DATA, R.string.account_settings_menu_auto_sync_private);
     }
 
     private void addPasswordPreferences(
diff --git a/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java b/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java
new file mode 100644
index 0000000..722cb1a
--- /dev/null
+++ b/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.credentials;
+
+import android.os.UserManager;
+
+import com.android.settings.Utils;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
+
+public class DefaultCombinedPickerPrivate extends DefaultCombinedPicker {
+    @Override
+    protected int getUser() {
+        UserManager userManager = getContext().getSystemService(UserManager.class);
+        return Utils.getCurrentUserIdOfType(userManager, ProfileType.PRIVATE);
+    }
+}
diff --git a/src/com/android/settings/applications/credentials/DefaultPrivateCombinedPreferenceController.kt b/src/com/android/settings/applications/credentials/DefaultPrivateCombinedPreferenceController.kt
new file mode 100644
index 0000000..d606f3c
--- /dev/null
+++ b/src/com/android/settings/applications/credentials/DefaultPrivateCombinedPreferenceController.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.applications.credentials
+
+import android.content.Context
+import android.content.Intent
+import android.os.UserHandle
+import com.android.settings.Utils
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment
+import com.android.settingslib.applications.DefaultAppInfo
+
+class DefaultPrivateCombinedPreferenceController(context: Context?) : DefaultCombinedPreferenceController(context) {
+    private val userHandle: UserHandle? =
+            Utils.getProfileOfType(mUserManager, ProfileSelectFragment.ProfileType.PRIVATE)
+
+    override fun isAvailable(): Boolean {
+        return if (userHandle == null) {
+            false
+        } else super.isAvailable()
+    }
+
+    override fun getPreferenceKey(): String {
+        return "default_credman_autofill_private"
+    }
+
+    override fun getSettingIntent(info: DefaultAppInfo ?): Intent ? {
+        if (info == null) {
+            return null
+        }
+        return userHandle?.let { handle ->
+            AutofillSettingIntentProvider(mContext, handle.identifier, info.key).intent
+        } ?: null
+    }
+
+    override fun startActivity(intent: Intent) {
+        userHandle?.let { handle ->
+            mContext.startActivityAsUser(intent, handle)
+        }
+    }
+
+    override fun getUser(): Int {
+        return userHandle?.identifier ?: UserHandle.myUserId()
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/applications/defaultapps/DefaultPrivateAutofillPreferenceController.kt b/src/com/android/settings/applications/defaultapps/DefaultPrivateAutofillPreferenceController.kt
new file mode 100644
index 0000000..67211b4
--- /dev/null
+++ b/src/com/android/settings/applications/defaultapps/DefaultPrivateAutofillPreferenceController.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.applications.defaultapps
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.os.UserHandle
+import android.provider.Settings
+import android.text.TextUtils
+import com.android.settings.Utils
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment
+import com.android.settingslib.applications.DefaultAppInfo
+
+class DefaultPrivateAutofillPreferenceController(context: Context?) : DefaultAutofillPreferenceController(context) {
+    private val userHandle: UserHandle? = Utils
+            .getProfileOfType(mUserManager, ProfileSelectFragment.ProfileType.PRIVATE)
+
+    override fun isAvailable(): Boolean {
+        return if (userHandle == null) {
+            false
+        } else super.isAvailable()
+    }
+
+    override fun getPreferenceKey(): String {
+        return "default_autofill_private"
+    }
+
+    override fun getDefaultAppInfo(): DefaultAppInfo ? {
+        val flattenComponent = userHandle?.let { handle ->
+            Settings.Secure.getStringForUser(
+                    mContext.contentResolver,
+                    DefaultAutofillPicker.SETTING,
+                    handle.identifier
+            )
+        }
+        return if (!flattenComponent.isNullOrEmpty()) {
+            userHandle?.let {
+                DefaultAppInfo(
+                        mContext,
+                        mPackageManager,
+                        it.identifier,
+                        ComponentName.unflattenFromString(flattenComponent))
+            }
+        } else null
+    }
+
+    override fun startActivity(intent: Intent) {
+        if (userHandle == null) {
+            mContext.startActivityAsUser(intent, UserHandle.CURRENT)
+        } else mContext.startActivityAsUser(intent, userHandle)
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectAccountFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectAccountFragment.java
index cf91031..77dc3a7 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectAccountFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectAccountFragment.java
@@ -15,10 +15,12 @@
  */
 
 package com.android.settings.dashboard.profileselector;
+
 import androidx.fragment.app.Fragment;
 
 import com.android.settings.R;
 import com.android.settings.accounts.AccountPersonalDashboardFragment;
+import com.android.settings.accounts.AccountPrivateDashboardFragment;
 import com.android.settings.accounts.AccountWorkProfileDashboardFragment;
 
 /**
@@ -28,10 +30,12 @@
 
     @Override
     public Fragment[] getFragments() {
-        return new Fragment[] {
-                new AccountPersonalDashboardFragment(),
-                new AccountWorkProfileDashboardFragment()
-        };
+        return ProfileSelectFragment.getFragments(
+                getContext(),
+                null /* bundle */,
+                AccountPersonalDashboardFragment::new,
+                AccountWorkProfileDashboardFragment::new,
+                AccountPrivateDashboardFragment::new);
     }
 
     @Override
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
index 5c0580d..657cdbf 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
@@ -17,21 +17,28 @@
 package com.android.settings.dashboard.profileselector;
 
 import static android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_CATEGORY_HEADER;
+import static android.app.admin.DevicePolicyResources.Strings.Settings.PRIVATE_CATEGORY_HEADER;
 import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_CATEGORY_HEADER;
 import static android.content.Intent.EXTRA_USER_ID;
 
 import android.annotation.IntDef;
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.pm.UserInfo;
 import android.os.Bundle;
+import android.os.Flags;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.Fragment;
 import androidx.recyclerview.widget.RecyclerView;
@@ -42,12 +49,14 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.privatespace.PrivateSpaceMaintainer;
 
 import com.google.android.material.tabs.TabLayout;
 import com.google.android.material.tabs.TabLayoutMediator;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 
 /**
  * Base fragment class for profile settings.
@@ -77,9 +86,14 @@
         int WORK = 1 << 1;
 
         /**
-         * It is personal and work profile
+         * It is private profile
          */
-        int ALL = PERSONAL | WORK;
+        int PRIVATE = 1 << 2;
+
+        /**
+         * It is personal, work, and private profile
+         */
+        int ALL = PERSONAL | WORK | PRIVATE;
     }
 
     /**
@@ -97,6 +111,11 @@
      */
     public static final int WORK_TAB = 1;
 
+    /**
+     * Used in fragment argument with Extra key {@link SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB}
+     */
+    public static final int PRIVATE_TAB = 2;
+
     private ViewGroup mContentView;
 
     private ViewPager2 mViewPager;
@@ -215,12 +234,20 @@
             if (isWorkProfile) {
                 return WORK_TAB;
             }
+            UserInfo userInfo = UserManager.get(activity).getUserInfo(userId);
+            if (Flags.allowPrivateProfile() && userInfo != null && userInfo.isPrivateProfile()) {
+                return PRIVATE_TAB;
+            }
         }
         // Start intent from a specific user eg: adb shell --user 10
         final int intentUser = activity.getIntent().getContentUserHint();
         if (UserManager.get(activity).isManagedProfile(intentUser)) {
             return WORK_TAB;
         }
+        UserInfo userInfo = UserManager.get(activity).getUserInfo(intentUser);
+        if (Flags.allowPrivateProfile() && userInfo != null && userInfo.isPrivateProfile()) {
+            return PRIVATE_TAB;
+        }
 
         return PERSONAL_TAB;
     }
@@ -229,13 +256,114 @@
         final DevicePolicyManager devicePolicyManager =
                 getContext().getSystemService(DevicePolicyManager.class);
 
-        if (position == WORK_TAB) {
+        if (Flags.allowPrivateProfile()) {
+            int tabForPosition =
+                    ((ViewPagerAdapter) mViewPager.getAdapter()).getTabForPosition(position);
+
+            if (tabForPosition == WORK_TAB) {
+                return devicePolicyManager.getResources().getString(WORK_CATEGORY_HEADER,
+                        () -> getContext().getString(
+                                com.android.settingslib.R.string.category_work));
+            }
+
+            if (tabForPosition == PRIVATE_TAB) {
+                return devicePolicyManager.getResources().getString(PRIVATE_CATEGORY_HEADER,
+                        () -> getContext()
+                                .getString(com.android.settingslib.R.string.category_private));
+            }
+
+        } else if (position == WORK_TAB) {
             return devicePolicyManager.getResources().getString(WORK_CATEGORY_HEADER,
                     () -> getContext().getString(com.android.settingslib.R.string.category_work));
+
+        }
+        return devicePolicyManager.getResources().getString(PERSONAL_CATEGORY_HEADER,
+                () -> getContext().getString(
+                        com.android.settingslib.R.string.category_personal));
+    }
+
+    /** Creates fragments of passed types, and returns them in an array. */
+    @NonNull static Fragment[] getFragments(
+            Context context,
+            @Nullable Bundle bundle,
+            FragmentConstructor personalFragmentConstructor,
+            FragmentConstructor workFragmentConstructor,
+            FragmentConstructor privateFragmentConstructor) {
+        return getFragments(
+                context,
+                bundle,
+                personalFragmentConstructor,
+                workFragmentConstructor,
+                privateFragmentConstructor,
+                new PrivateSpaceInfoProvider() {},
+                new ManagedProfileInfoProvider() {});
+    }
+
+    /**
+     * Creates fragments of passed types, and returns them in an array. This overload exists only
+     * for helping with testing.
+     */
+    @NonNull static Fragment[] getFragments(
+            Context context,
+            @Nullable Bundle bundle,
+            FragmentConstructor personalFragmentConstructor,
+            FragmentConstructor workFragmentConstructor,
+            FragmentConstructor privateFragmentConstructor,
+            PrivateSpaceInfoProvider privateSpaceInfoProvider,
+            ManagedProfileInfoProvider managedProfileInfoProvider) {
+        Fragment[] result = new Fragment[0];
+        ArrayList<Fragment> fragments = new ArrayList<>();
+
+        try {
+            final Bundle personalOnly = bundle != null ? bundle : new Bundle();
+            personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
+            final Fragment personalFragment =
+                    personalFragmentConstructor.constructAndGetFragment();
+            personalFragment.setArguments(personalOnly);
+            fragments.add(personalFragment);
+
+            if (managedProfileInfoProvider.getManagedProfile(context) != null) {
+                final Bundle workOnly = bundle != null ? bundle : new Bundle();
+                workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
+                final Fragment workFragment =
+                        workFragmentConstructor.constructAndGetFragment();
+                workFragment.setArguments(workOnly);
+                fragments.add(workFragment);
+            }
+
+            if (Flags.allowPrivateProfile()
+                    && !privateSpaceInfoProvider.isPrivateSpaceLocked(context)) {
+                final Bundle privateOnly = bundle != null ? bundle : new Bundle();
+                privateOnly.putInt(EXTRA_PROFILE, ProfileType.PRIVATE);
+                final Fragment privateFragment =
+                        privateFragmentConstructor.constructAndGetFragment();
+                privateFragment.setArguments(privateOnly);
+                fragments.add(privateFragment);
+            }
+
+            result = new Fragment[fragments.size()];
+            fragments.toArray(result);
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to create fragment");
         }
 
-        return devicePolicyManager.getResources().getString(PERSONAL_CATEGORY_HEADER,
-                () -> getContext().getString(com.android.settingslib.R.string.category_personal));
+        return result;
+    }
+
+    interface FragmentConstructor {
+        Fragment constructAndGetFragment();
+    }
+
+    interface PrivateSpaceInfoProvider {
+        default boolean isPrivateSpaceLocked(Context context) {
+            return PrivateSpaceMaintainer.getInstance(context).isPrivateSpaceLocked();
+        }
+    }
+
+    interface ManagedProfileInfoProvider {
+        default UserHandle getManagedProfile(Context context) {
+            return Utils.getManagedProfile(context.getSystemService(UserManager.class));
+        }
     }
 
     static class ViewPagerAdapter extends FragmentStateAdapter {
@@ -256,5 +384,22 @@
         public int getItemCount() {
             return mChildFragments.length;
         }
+
+        private int getTabForPosition(int position) {
+            if (position >= mChildFragments.length) {
+                Log.e(TAG, "tab requested for out of bound position " + position);
+                return PERSONAL_TAB;
+            }
+            @ProfileType
+            int profileType = mChildFragments[position].getArguments().getInt(EXTRA_PROFILE);
+
+            if (profileType == ProfileType.WORK) {
+                return WORK_TAB;
+            }
+            if (profileType == ProfileType.PRIVATE) {
+                return PRIVATE_TAB;
+            }
+            return PERSONAL_TAB;
+        }
     }
 }
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectKeyboardFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectKeyboardFragment.java
index c4386e6..d35692c 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectKeyboardFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectKeyboardFragment.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.dashboard.profileselector;
 
-import android.os.Bundle;
-
 import androidx.fragment.app.Fragment;
 
 import com.android.settings.R;
@@ -39,19 +37,11 @@
 
     @Override
     public Fragment[] getFragments() {
-        final Bundle personalOnly = new Bundle();
-        personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
-        final Fragment personalFragment = new AvailableVirtualKeyboardFragment();
-        personalFragment.setArguments(personalOnly);
-
-        final Bundle workOnly = new Bundle();
-        workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
-        final Fragment workFragment = new AvailableVirtualKeyboardFragment();
-        workFragment.setArguments(workOnly);
-
-        return new Fragment[]{
-                personalFragment,
-                workFragment
-        };
+        return ProfileSelectFragment.getFragments(
+                getContext(),
+                null /* bundle */,
+                AvailableVirtualKeyboardFragment::new,
+                AvailableVirtualKeyboardFragment::new,
+                AvailableVirtualKeyboardFragment::new);
     }
 }
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragment.java
index 28fb97b..feaec74 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragment.java
@@ -45,20 +45,12 @@
 
     @Override
     public Fragment[] getFragments() {
-
-        final Bundle workOnly = new Bundle();
-        workOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.WORK);
-        final Fragment workFragment = new LocationWorkProfileSettings();
-        workFragment.setArguments(workOnly);
-
-        final Bundle personalOnly = new Bundle();
-        personalOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.PERSONAL);
-        final Fragment personalFragment = new LocationPersonalSettings();
-        personalFragment.setArguments(personalOnly);
-        return new Fragment[]{
-                personalFragment,
-                workFragment
-        };
+        return ProfileSelectFragment.getFragments(
+                getContext(),
+                null /* bundle */,
+                LocationPersonalSettings::new,
+                LocationWorkProfileSettings::new,
+                LocationPersonalSettings::new);
     }
 
     @Override
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationServicesFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationServicesFragment.java
index 111e4ce..8e48c7b 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationServicesFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationServicesFragment.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.dashboard.profileselector;
 
-import android.os.Bundle;
-
 import androidx.fragment.app.Fragment;
 
 import com.android.settings.R;
@@ -31,19 +29,12 @@
 
     @Override
     public Fragment[] getFragments() {
-        final Bundle workOnly = new Bundle();
-        workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
-        final Fragment workFragment = new LocationServicesForWork();
-        workFragment.setArguments(workOnly);
-
-        final Bundle personalOnly = new Bundle();
-        personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
-        final Fragment personalFragment = new LocationServices();
-        personalFragment.setArguments(personalOnly);
-        return new Fragment[]{
-                personalFragment, // 0
-                workFragment
-        };
+        return ProfileSelectFragment.getFragments(
+                getContext(),
+                null /* bundle */,
+                LocationServices::new,
+                LocationServicesForWork::new,
+                LocationServices::new);
     }
 
     @Override
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java
index 36aa9c5..4c82f6c 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java
@@ -31,19 +31,12 @@
 
     @Override
     public Fragment[] getFragments() {
-        final Bundle workOnly = getArguments() != null ? getArguments().deepCopy() : new Bundle();
-        workOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.WORK);
-        final Fragment workFragment = new ManageApplications();
-        workFragment.setArguments(workOnly);
-
-        final Bundle personalOnly = getArguments() != null ? getArguments() : new Bundle();
-        personalOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.PERSONAL);
-        final Fragment personalFragment = new ManageApplications();
-        personalFragment.setArguments(personalOnly);
-        return new Fragment[]{
-                personalFragment, //0
-                workFragment
-        };
+        return ProfileSelectFragment.getFragments(
+                getContext(),
+                getArguments(),
+                ManageApplications::new,
+                ManageApplications::new,
+                ManageApplications::new);
     }
 
     @Override
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectPhysicalKeyboardFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectPhysicalKeyboardFragment.java
index 3c1546e..239d609 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectPhysicalKeyboardFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectPhysicalKeyboardFragment.java
@@ -51,22 +51,11 @@
 
     @Override
     public Fragment[] getFragments() {
-        final Bundle personalOnly = new Bundle();
-        personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
-        final Fragment personalFragment = new NewKeyboardLayoutEnabledLocalesFragment();
-        personalOnly.putParcelable(
-                Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, mInputDeviceIdentifier);
-        personalFragment.setArguments(personalOnly);
-
-        final Bundle workOnly = new Bundle();
-        workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
-        final Fragment workFragment = new NewKeyboardLayoutEnabledLocalesFragment();
-        workOnly.putParcelable(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, mInputDeviceIdentifier);
-        workFragment.setArguments(workOnly);
-
-        return new Fragment[]{
-                personalFragment,
-                workFragment
-        };
+        return ProfileSelectFragment.getFragments(
+                getContext(),
+                null /* bundle */,
+                NewKeyboardLayoutEnabledLocalesFragment::new,
+                NewKeyboardLayoutEnabledLocalesFragment::new,
+                NewKeyboardLayoutEnabledLocalesFragment::new);
     }
 }
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
index 5babf30..b523e7e 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
@@ -193,20 +193,12 @@
             return mFragments;
         }
 
-        final Bundle workBundle = new Bundle();
-        workBundle.putInt(EXTRA_PROFILE, ProfileType.WORK);
-        final Fragment workFragment = new StorageCategoryFragment();
-        workFragment.setArguments(workBundle);
-
-        final Bundle personalBundle = new Bundle();
-        personalBundle.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
-        final Fragment personalFragment = new StorageCategoryFragment();
-        personalFragment.setArguments(personalBundle);
-
-        mFragments = new Fragment[] {
-            personalFragment,
-            workFragment
-        };
+        mFragments = ProfileSelectFragment.getFragments(
+                getContext(),
+                null /* bundle */,
+                StorageCategoryFragment::new,
+                StorageCategoryFragment::new,
+                StorageCategoryFragment::new);
         return mFragments;
     }
 
diff --git a/src/com/android/settings/deviceinfo/StorageCategoryFragment.java b/src/com/android/settings/deviceinfo/StorageCategoryFragment.java
index 52f453d..1280057 100644
--- a/src/com/android/settings/deviceinfo/StorageCategoryFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageCategoryFragment.java
@@ -37,6 +37,7 @@
 import com.android.settings.Utils;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
 import com.android.settings.deviceinfo.storage.ManageStoragePreferenceController;
 import com.android.settings.deviceinfo.storage.NonCurrentUserController;
 import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
@@ -85,7 +86,7 @@
 
     private StorageItemPreferenceController mPreferenceController;
     private List<NonCurrentUserController> mNonCurrentUsers;
-    private boolean mIsWorkProfile;
+    private @ProfileType int mProfileType;
     private int mUserId;
     private boolean mIsLoadedFromCache;
     private StorageCacheHelper mStorageCacheHelper;
@@ -163,9 +164,9 @@
         // These member variables are initialized befoer super.onAttach for
         // createPreferenceControllers to work correctly.
         mUserManager = context.getSystemService(UserManager.class);
-        mIsWorkProfile = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE)
-                == ProfileSelectFragment.ProfileType.WORK;
-        mUserId = Utils.getCurrentUserId(mUserManager, mIsWorkProfile);
+        mProfileType = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE);
+        mUserId = Utils.getCurrentUserIdOfType(mUserManager, mProfileType);
+
         mStorageCacheHelper = new StorageCacheHelper(getContext(), mUserId);
 
         super.onAttach(context);
@@ -229,8 +230,12 @@
 
     @Override
     public int getMetricsCategory() {
-        return mIsWorkProfile ? SettingsEnums.SETTINGS_STORAGE_CATEGORY_WORK :
-                SettingsEnums.SETTINGS_STORAGE_CATEGORY;
+        if (mProfileType == ProfileSelectFragment.ProfileType.WORK) {
+            return SettingsEnums.SETTINGS_STORAGE_CATEGORY_WORK;
+        } else if (mProfileType == ProfileSelectFragment.ProfileType.PRIVATE) {
+            return SettingsEnums.SETTINGS_STORAGE_CATEGORY_PRIVATE;
+        }
+        return SettingsEnums.SETTINGS_STORAGE_CATEGORY;
     }
 
     @Override
@@ -248,11 +253,12 @@
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         final StorageManager sm = context.getSystemService(StorageManager.class);
         mPreferenceController = new StorageItemPreferenceController(context, this,
-                null /* volume */, new StorageManagerVolumeProvider(sm), mIsWorkProfile);
+                null /* volume */, new StorageManagerVolumeProvider(sm), mProfileType);
         controllers.add(mPreferenceController);
 
-        mNonCurrentUsers = mIsWorkProfile ? EMPTY_LIST :
-                NonCurrentUserController.getNonCurrentUserControllers(context, mUserManager);
+        mNonCurrentUsers = mProfileType == ProfileSelectFragment.ProfileType.PERSONAL
+                ? NonCurrentUserController.getNonCurrentUserControllers(context, mUserManager)
+                : EMPTY_LIST;
         controllers.addAll(mNonCurrentUsers);
         return controllers;
     }
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index f31f2be..0da3667 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -308,7 +308,6 @@
         // These member variables are initialized befoer super.onAttach for
         // createPreferenceControllers to work correctly.
         mUserManager = context.getSystemService(UserManager.class);
-        mIsWorkProfile = false;
         mUserId = UserHandle.myUserId();
         mStorageCacheHelper = new StorageCacheHelper(getContext(), mUserId);
 
@@ -423,7 +422,7 @@
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         final StorageManager sm = context.getSystemService(StorageManager.class);
         mPreferenceController = new StorageItemPreferenceController(context, this,
-                null /* volume */, new StorageManagerVolumeProvider(sm), mIsWorkProfile);
+                null /* volume */, new StorageManagerVolumeProvider(sm));
         controllers.add(mPreferenceController);
 
         mNonCurrentUsers = NonCurrentUserController.getNonCurrentUserControllers(context,
@@ -467,8 +466,7 @@
                     final UserManager userManager = context.getSystemService(UserManager.class);
                     final List<AbstractPreferenceController> controllers = new ArrayList<>();
                     controllers.add(new StorageItemPreferenceController(context, null /* host */,
-                            null /* volume */, new StorageManagerVolumeProvider(sm),
-                            false /* isWorkProfile */));
+                            null /* volume */, new StorageManagerVolumeProvider(sm)));
                     controllers.addAll(NonCurrentUserController.getNonCurrentUserControllers(
                             context, userManager));
                     return controllers;
diff --git a/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java b/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java
index ccae7e9..1955f36 100644
--- a/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java
+++ b/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java
@@ -27,6 +27,7 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
 import com.android.settings.deviceinfo.storage.StorageCacheHelper;
 import com.android.settingslib.deviceinfo.PrivateStorageInfo;
 import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
@@ -62,8 +63,8 @@
 
     @VisibleForTesting
     protected Future refreshSummaryThread(Preference preference) {
-        int userId = Utils.getCurrentUserId(mContext.getSystemService(UserManager.class),
-                /* isWorkProfile */ false);
+        int userId = Utils.getCurrentUserIdOfType(
+                mContext.getSystemService(UserManager.class), ProfileType.PERSONAL);
         final StorageCacheHelper storageCacheHelper = new StorageCacheHelper(mContext, userId);
         long cachedUsedSize = storageCacheHelper.retrieveUsedSize();
         long cachedTotalSize = storageCacheHelper.retrieveCachedSize().totalSize;
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index a57cd5b..fd42417 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -17,11 +17,13 @@
 package com.android.settings.deviceinfo.storage;
 
 import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.PERSONAL_TAB;
+import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.PRIVATE_TAB;
 import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.WORK_TAB;
 
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -47,6 +49,7 @@
 import com.android.settings.applications.manageapplications.ManageApplications;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
 import com.android.settings.deviceinfo.StorageItemPreference;
 import com.android.settings.deviceinfo.storage.StorageUtils.SystemInfoFragment;
 import com.android.settings.overlay.FeatureFactory;
@@ -108,33 +111,33 @@
     private final Fragment mFragment;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
     private final StorageVolumeProvider mSvp;
-    private VolumeInfo mVolume;
+    @Nullable private VolumeInfo mVolume;
     private int mUserId;
     private long mUsedBytes;
     private long mTotalSize;
 
-    private List<StorageItemPreference> mPrivateStorageItemPreferences;
-    private PreferenceScreen mScreen;
+    @Nullable private List<StorageItemPreference> mPrivateStorageItemPreferences;
+    @Nullable private PreferenceScreen mScreen;
     @VisibleForTesting
-    Preference mPublicStoragePreference;
+    @Nullable Preference mPublicStoragePreference;
     @VisibleForTesting
-    StorageItemPreference mImagesPreference;
+    @Nullable StorageItemPreference mImagesPreference;
     @VisibleForTesting
-    StorageItemPreference mVideosPreference;
+    @Nullable StorageItemPreference mVideosPreference;
     @VisibleForTesting
-    StorageItemPreference mAudioPreference;
+    @Nullable StorageItemPreference mAudioPreference;
     @VisibleForTesting
-    StorageItemPreference mAppsPreference;
+    @Nullable StorageItemPreference mAppsPreference;
     @VisibleForTesting
-    StorageItemPreference mGamesPreference;
+    @Nullable StorageItemPreference mGamesPreference;
     @VisibleForTesting
-    StorageItemPreference mDocumentsAndOtherPreference;
+    @Nullable StorageItemPreference mDocumentsAndOtherPreference;
     @VisibleForTesting
-    StorageItemPreference mSystemPreference;
+    @Nullable StorageItemPreference mSystemPreference;
     @VisibleForTesting
-    StorageItemPreference mTrashPreference;
+    @Nullable StorageItemPreference mTrashPreference;
 
-    private boolean mIsWorkProfile;
+    private final int mProfileType;
 
     private StorageCacheHelper mStorageCacheHelper;
     // The mIsDocumentsPrefShown being used here is to prevent a flicker problem from displaying
@@ -142,15 +145,24 @@
     private boolean mIsDocumentsPrefShown;
     private boolean mIsPreferenceOrderedBySize;
 
-    public StorageItemPreferenceController(Context context, Fragment hostFragment,
-            VolumeInfo volume, StorageVolumeProvider svp, boolean isWorkProfile) {
+    public StorageItemPreferenceController(
+            Context context, Fragment hostFragment, VolumeInfo volume, StorageVolumeProvider svp) {
+        this(context, hostFragment, volume, svp, ProfileSelectFragment.ProfileType.PERSONAL);
+    }
+
+    public StorageItemPreferenceController(
+            Context context,
+            Fragment hostFragment,
+            @Nullable VolumeInfo volume,
+            StorageVolumeProvider svp,
+            @ProfileSelectFragment.ProfileType int profileType) {
         super(context);
         mPackageManager = context.getPackageManager();
         mUserManager = context.getSystemService(UserManager.class);
         mFragment = hostFragment;
         mVolume = volume;
         mSvp = svp;
-        mIsWorkProfile = isWorkProfile;
+        mProfileType = profileType;
         mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
         mUserId = getCurrentUserId();
         mIsDocumentsPrefShown = isDocumentsPrefShown();
@@ -168,7 +180,7 @@
 
     @VisibleForTesting
     int getCurrentUserId() {
-        return Utils.getCurrentUserId(mUserManager, mIsWorkProfile);
+        return Utils.getCurrentUserIdOfType(mUserManager, mProfileType);
     }
 
     @Override
@@ -229,7 +241,9 @@
         mVolume = volume;
 
         if (mPublicStoragePreference != null) {
-            mPublicStoragePreference.setVisible(isValidPublicVolume() && !mIsWorkProfile);
+            mPublicStoragePreference.setVisible(
+                    isValidPublicVolume()
+                            && mProfileType == ProfileSelectFragment.ProfileType.PERSONAL);
         }
 
         // If isValidPrivateVolume() is true, these preferences will become visible at
@@ -327,9 +341,16 @@
      * Sets the user id for which this preference controller is handling.
      */
     public void setUserId(UserHandle userHandle) {
-        if (mIsWorkProfile && !mUserManager.isManagedProfile(userHandle.getIdentifier())) {
+        if (mProfileType == ProfileSelectFragment.ProfileType.WORK
+                && !mUserManager.isManagedProfile(userHandle.getIdentifier())) {
             throw new IllegalArgumentException("Only accept work profile userHandle");
         }
+
+        UserInfo userInfo = mUserManager.getUserInfo(userHandle.getIdentifier());
+        if (mProfileType == ProfileSelectFragment.ProfileType.PRIVATE
+                && (userInfo == null || userInfo.isPrivateProfile())) {
+            throw new IllegalArgumentException("Only accept private profile userHandle");
+        }
         mUserId = userHandle.getIdentifier();
 
         tintPreference(mPublicStoragePreference);
@@ -498,8 +519,13 @@
 
     private Bundle getWorkAnnotatedBundle(int additionalCapacity) {
         final Bundle args = new Bundle(1 + additionalCapacity);
-        args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB,
-                mIsWorkProfile ? WORK_TAB : PERSONAL_TAB);
+        if (mProfileType == ProfileSelectFragment.ProfileType.WORK) {
+            args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, WORK_TAB);
+        } else if (mProfileType == ProfileSelectFragment.ProfileType.PRIVATE) {
+            args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PRIVATE_TAB);
+        } else {
+            args.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PERSONAL_TAB);
+        }
         return args;
     }
 
diff --git a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
index 6efbc6d..7e27529 100644
--- a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
@@ -84,6 +84,16 @@
                 newUserAwareContext = context.createContextAsUser(UserHandle.of(newUserId), 0);
                 break;
             }
+            case ProfileSelectFragment.ProfileType.PRIVATE: {
+                // If the user is a private profile user, use currentUserId directly. Or get the
+                // private profile userId instead.
+                newUserId = userManager.isPrivateProfile()
+                        ? currentUserId
+                        : Utils.getCurrentUserIdOfType(
+                                userManager, ProfileSelectFragment.ProfileType.PRIVATE);
+                newUserAwareContext = context.createContextAsUser(UserHandle.of(newUserId), 0);
+                break;
+            }
             case ProfileSelectFragment.ProfileType.PERSONAL: {
                 // Use the parent user of the current user if the current user is profile.
                 final UserHandle currentUser = UserHandle.of(currentUserId);
diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
index f007bc8..abe640b 100644
--- a/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
+++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
@@ -77,6 +77,15 @@
                         ? currentUserId : Utils.getManagedProfileId(userManager, currentUserId);
                 break;
             }
+            case ProfileSelectFragment.ProfileType.PRIVATE: {
+                // If the user is a private profile user, use currentUserId directly. Or get the
+                // private profile userId instead.
+                newUserId = userManager.isPrivateProfile()
+                        ? currentUserId
+                        : Utils.getCurrentUserIdOfType(
+                                userManager, ProfileSelectFragment.ProfileType.PRIVATE);
+                break;
+            }
             case ProfileSelectFragment.ProfileType.PERSONAL: {
                 final UserHandle primaryUser = userManager.getPrimaryUser().getUserHandle();
                 newUserId = primaryUser.getIdentifier();
diff --git a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
index 709814d..0abf8f7 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
@@ -131,7 +131,17 @@
         return false;
     }
 
-    static synchronized PrivateSpaceMaintainer getInstance(Context context) {
+    /** Returns true when the PS is locked or when PS doesn't exist, false otherwise. */
+    public synchronized boolean isPrivateSpaceLocked() {
+        if (!doesPrivateSpaceExist()) {
+            return true;
+        }
+
+        return mUserManager.isQuietModeEnabled(mUserHandle);
+    }
+
+    /** Returns the instance of {@link PrivateSpaceMaintainer} */
+    public static synchronized PrivateSpaceMaintainer getInstance(Context context) {
         if (sPrivateSpaceMaintainer == null) {
             sPrivateSpaceMaintainer = new PrivateSpaceMaintainer(context);
         }
diff --git a/src/com/android/settings/users/AutoSyncPrivateDataPreferenceController.kt b/src/com/android/settings/users/AutoSyncPrivateDataPreferenceController.kt
new file mode 100644
index 0000000..3eabafe
--- /dev/null
+++ b/src/com/android/settings/users/AutoSyncPrivateDataPreferenceController.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.users
+
+import android.content.Context
+import androidx.preference.PreferenceFragmentCompat
+import com.android.settings.Utils
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment
+
+class AutoSyncPrivateDataPreferenceController(
+        context: Context?, parent: PreferenceFragmentCompat?)
+    : AutoSyncDataPreferenceController(context, parent) {
+    init {
+        mUserHandle = Utils
+                .getProfileOfType(mUserManager, ProfileSelectFragment.ProfileType.PRIVATE)
+    }
+
+    override fun getPreferenceKey(): String {
+        return KEY_AUTO_SYNC_PRIVATE_ACCOUNT
+    }
+
+    override fun isAvailable(): Boolean {
+        return (mUserHandle != null
+                && mUserManager.getUserInfo(mUserHandle.identifier).isPrivateProfile)
+    }
+
+    companion object {
+        private const val KEY_AUTO_SYNC_PRIVATE_ACCOUNT = "auto_sync_private_account_data"
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/Android.bp b/tests/robotests/Android.bp
index fbfd888..0a7be86 100644
--- a/tests/robotests/Android.bp
+++ b/tests/robotests/Android.bp
@@ -59,6 +59,7 @@
         "androidx.test.rules",
         "androidx.test.runner",
         "flag-junit",
+        "flag-junit-base",
         "aconfig_settings_flags_lib",
         "platform-test-annotations",
         "Settings-testutils2",
diff --git a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
index b595d06..056935c 100644
--- a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectFragmentTest.java
@@ -19,6 +19,7 @@
 import static android.content.Intent.EXTRA_USER_ID;
 
 import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.PERSONAL_TAB;
+import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.PRIVATE_TAB;
 import static com.android.settings.dashboard.profileselector.ProfileSelectFragment.WORK_TAB;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -29,6 +30,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+import android.os.Flags;
+import android.os.UserHandle;
+import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
@@ -38,6 +42,7 @@
 import com.android.settings.testutils.shadow.ShadowUserManager;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
@@ -60,6 +65,7 @@
     private TestProfileSelectFragment mFragment;
     private FragmentActivity mActivity;
     private ShadowUserManager mUserManager;
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     @Before
     public void setUp() {
@@ -86,6 +92,14 @@
     }
 
     @Test
+    public void getTabId_setArgumentPrivate_setCorrectTab() {
+        final Bundle bundle = new Bundle();
+        bundle.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PRIVATE_TAB);
+
+        assertThat(mFragment.getTabId(mActivity, bundle)).isEqualTo(PRIVATE_TAB);
+    }
+
+    @Test
     public void getTabId_setArgumentPersonal_setCorrectTab() {
         final Bundle bundle = new Bundle();
         bundle.putInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, PERSONAL_TAB);
@@ -105,6 +119,16 @@
     }
 
     @Test
+    public void getTabId_setPrivateId_getCorrectTab() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        final Bundle bundle = new Bundle();
+        bundle.putInt(EXTRA_USER_ID, 11);
+        mUserManager.setPrivateProfile(11, "private", 0);
+
+        assertThat(mFragment.getTabId(mActivity, bundle)).isEqualTo(PRIVATE_TAB);
+    }
+
+    @Test
     public void getTabId_setPersonalId_getCorrectTab() {
         final Bundle bundle = new Bundle();
         bundle.putInt(EXTRA_USER_ID, 0);
@@ -124,12 +148,120 @@
         assertThat(mFragment.getTabId(mActivity, null)).isEqualTo(WORK_TAB);
     }
 
+    @Test
+    public void testGetFragments_whenOnlyPersonal_returnsOneFragment() {
+        mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        Fragment[] fragments = ProfileSelectFragment.getFragments(
+                mContext,
+                null /* bundle */,
+                TestProfileSelectFragment::new,
+                TestProfileSelectFragment::new,
+                TestProfileSelectFragment::new);
+        assertThat(fragments).hasLength(1);
+    }
+
+    @Test
+    public void testGetFragments_whenPrivateDisabled_returnsOneFragment() {
+        Fragment[] fragments = ProfileSelectFragment.getFragments(
+                mContext,
+                null /* bundle */,
+                TestProfileSelectFragment::new,
+                TestProfileSelectFragment::new,
+                TestProfileSelectFragment::new,
+                new ProfileSelectFragment.PrivateSpaceInfoProvider() {
+                    @Override
+                    public boolean isPrivateSpaceLocked(Context context) {
+                        return true;
+                    }
+                },
+                new ProfileSelectFragment.ManagedProfileInfoProvider() {
+                    @Override
+                    public UserHandle getManagedProfile(Context context) {
+                        return null;
+                    }
+                });
+        assertThat(fragments).hasLength(1);
+    }
+
+    @Test
+    public void testGetFragments_whenPrivateEnabled_returnsTwoFragments() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        Fragment[] fragments = ProfileSelectFragment.getFragments(
+                mContext,
+                null /* bundle */,
+                TestProfileSelectFragment::new,
+                TestProfileSelectFragment::new,
+                TestProfileSelectFragment::new,
+                new ProfileSelectFragment.PrivateSpaceInfoProvider() {
+                    @Override
+                    public boolean isPrivateSpaceLocked(Context context) {
+                        return false;
+                    }
+                },
+                new ProfileSelectFragment.ManagedProfileInfoProvider() {
+                    @Override
+                    public UserHandle getManagedProfile(Context context) {
+                        return null;
+                    }
+                });
+        assertThat(fragments).hasLength(2);
+    }
+
+    @Test
+    public void testGetFragments_whenManagedProfile_returnsTwoFragments() {
+        mSetFlagsRule.disableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        Fragment[] fragments = ProfileSelectFragment.getFragments(
+                mContext,
+                null /* bundle */,
+                TestProfileSelectFragment::new,
+                TestProfileSelectFragment::new,
+                TestProfileSelectFragment::new,
+                new ProfileSelectFragment.PrivateSpaceInfoProvider() {
+                    @Override
+                    public boolean isPrivateSpaceLocked(Context context) {
+                        return false;
+                    }
+                },
+                new ProfileSelectFragment.ManagedProfileInfoProvider() {
+                    @Override
+                    public UserHandle getManagedProfile(Context context) {
+                        return new UserHandle(123);
+                    }
+                });
+        assertThat(fragments).hasLength(2);
+    }
+
+    @Test
+    public void testGetFragments_whenAllProfiles_returnsThreeFragments() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_PRIVATE_PROFILE);
+        Fragment[] fragments = ProfileSelectFragment.getFragments(
+                mContext,
+                null /* bundle */,
+                TestProfileSelectFragment::new,
+                TestProfileSelectFragment::new,
+                TestProfileSelectFragment::new,
+                new ProfileSelectFragment.PrivateSpaceInfoProvider() {
+                    @Override
+                    public boolean isPrivateSpaceLocked(Context context) {
+                        return false;
+                    }
+                },
+                new ProfileSelectFragment.ManagedProfileInfoProvider() {
+                    @Override
+                    public UserHandle getManagedProfile(Context context) {
+                        return new UserHandle(123);
+                    }
+                });
+        assertThat(fragments).hasLength(3);
+    }
+
     public static class TestProfileSelectFragment extends ProfileSelectFragment {
 
         @Override
         public Fragment[] getFragments() {
             return new Fragment[]{
                     new SettingsPreferenceFragmentTest.TestFragment(), //0
+                    new SettingsPreferenceFragmentTest.TestFragment(),
                     new SettingsPreferenceFragmentTest.TestFragment()
             };
         }
diff --git a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragmentTest.java
index f463bec..fa2782f 100644
--- a/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/profileselector/ProfileSelectLocationFragmentTest.java
@@ -39,10 +39,12 @@
 
     @Test
     public void getFragments_containsCorrectBundle() {
-        assertThat(mProfileSelectLocationFragment.getFragments().length).isEqualTo(2);
+        assertThat(mProfileSelectLocationFragment.getFragments().length).isEqualTo(3);
         assertThat(mProfileSelectLocationFragment.getFragments()[0].getArguments().getInt(
                 EXTRA_PROFILE, -1)).isEqualTo(ProfileSelectFragment.ProfileType.PERSONAL);
         assertThat(mProfileSelectLocationFragment.getFragments()[1].getArguments().getInt(
                 EXTRA_PROFILE, -1)).isEqualTo(ProfileSelectFragment.ProfileType.WORK);
+        assertThat(mProfileSelectLocationFragment.getFragments()[1].getArguments().getInt(
+                EXTRA_PROFILE, -1)).isEqualTo(ProfileSelectFragment.ProfileType.PRIVATE);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
index 5db0243..b61f5ab 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
@@ -52,6 +52,7 @@
 import com.android.settings.SubSettings;
 import com.android.settings.applications.manageapplications.ManageApplications;
 import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
 import com.android.settings.deviceinfo.StorageItemPreference;
 import com.android.settings.testutils.shadow.ShadowUserManager;
 import com.android.settingslib.deviceinfo.StorageVolumeProvider;
@@ -99,7 +100,7 @@
         // Note: null is passed as the Lifecycle because we are handling it outside of the normal
         //       Settings fragment lifecycle for test purposes.
         mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp,
-                false /* isWorkProfile */);
+                ProfileSelectFragment.ProfileType.PERSONAL);
         mPreference = new StorageItemPreference(mContext);
 
         // Inflate the preference and the widget.
@@ -175,7 +176,7 @@
         mPreference.setKey(StorageItemPreferenceController.IMAGES_KEY);
         final Context mockContext = getMockContext();
         mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
-                mSvp, false /* isWorkProfile */);
+                mSvp, ProfileSelectFragment.ProfileType.PERSONAL);
         mController.handlePreferenceTreeClick(mPreference);
 
         final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -192,7 +193,7 @@
         mPreference.setKey(StorageItemPreferenceController.AUDIO_KEY);
         final Context mockContext = getMockContext();
         mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
-                mSvp, false /* isWorkProfile */);
+                mSvp, ProfileSelectFragment.ProfileType.PERSONAL);
         mController.handlePreferenceTreeClick(mPreference);
 
         final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -242,7 +243,7 @@
     @Test
     public void launchAppsIntent_forWork_settingsIntent() {
         mController = new FakeStorageItemPreferenceController(mContext, mFragment, mVolume, mSvp,
-                true /* isWorkProfile */);
+                ProfileType.WORK);
         mPreference.setKey(StorageItemPreferenceController.APPS_KEY);
         mController.handlePreferenceTreeClick(mPreference);
 
@@ -272,7 +273,7 @@
         mPreference.setKey(StorageItemPreferenceController.DOCUMENTS_AND_OTHER_KEY);
         final Context mockContext = getMockContext();
         mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
-                mSvp, false /* isWorkProfile */);
+                mSvp, ProfileSelectFragment.ProfileType.PERSONAL);
         mController.handlePreferenceTreeClick(mPreference);
 
         final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -307,7 +308,7 @@
         mPreference.setKey(StorageItemPreferenceController.VIDEOS_KEY);
         final Context mockContext = getMockContext();
         mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
-                mSvp, false /* isWorkProfile */);
+                mSvp, ProfileSelectFragment.ProfileType.PERSONAL);
         mController.handlePreferenceTreeClick(mPreference);
 
         final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -457,8 +458,8 @@
         private static final int CURRENT_USER_ID = 10;
 
         FakeStorageItemPreferenceController(Context context, Fragment hostFragment,
-                VolumeInfo volume, StorageVolumeProvider svp, boolean isWorkProfile) {
-            super(context, hostFragment, volume, svp, isWorkProfile);
+                VolumeInfo volume, StorageVolumeProvider svp, @ProfileType int profileType) {
+            super(context, hostFragment, volume, svp, profileType);
         }
 
         @Override
diff --git a/tests/robotests/testutils/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/testutils/com/android/settings/testutils/shadow/ShadowUserManager.java
index c8d2866..ce6dc6a 100644
--- a/tests/robotests/testutils/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/testutils/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -17,6 +17,7 @@
 package com.android.settings.testutils.shadow;
 
 import static android.os.Build.VERSION_CODES.LOLLIPOP;
+import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE;
 
 import android.annotation.UserIdInt;
 import android.content.pm.UserInfo;
@@ -223,6 +224,10 @@
         mManagedProfiles.addAll(profileIds);
     }
 
+    public void setPrivateProfile(int id, String name, int flags) {
+        mUserProfileInfos.add(new UserInfo(id, name, null, flags, USER_TYPE_PROFILE_PRIVATE));
+    }
+
     public void setUserSwitcherEnabled(boolean userSwitchEnabled) {
         mUserSwitchEnabled = userSwitchEnabled;
     }