Merge "Migrate DisplayScreen" into main
diff --git a/res/drawable/cloud_off.xml b/res/drawable/cloud_off.xml
new file mode 100644
index 0000000..cef728f
--- /dev/null
+++ b/res/drawable/cloud_off.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M19.400000,10.000000c-0.700000,-3.400000 -3.700000,-6.000000 -7.400000,-6.000000c-1.500000,0.000000 -2.900000,0.400000 -4.000000,1.200000l1.500000,1.500000C10.200000,6.200000 11.100000,6.000000 12.000000,6.000000c3.000000,0.000000 5.500000,2.500000 5.500000,5.500000L17.500000,12.000000L19.000000,12.000000c1.700000,0.000000 3.000000,1.300000 3.000000,3.000000c0.000000,1.100000 -0.600000,2.100000 -1.600000,2.600000l1.500000,1.500000c1.300000,-0.900000 2.100000,-2.400000 2.100000,-4.100000C24.000000,12.400000 21.900000,10.200000 19.400000,10.000000zM3.000000,5.300000L5.800000,8.000000C2.600000,8.200000 0.000000,10.800000 0.000000,14.000000c0.000000,3.300000 2.700000,6.000000 6.000000,6.000000l11.700000,0.000000l2.000000,2.000000l1.300000,-1.300000L4.300000,4.000000L3.000000,5.300000zM7.700000,10.000000l8.000000,8.000000L6.000000,18.000000c-2.200000,0.000000 -4.000000,-1.800000 -4.000000,-4.000000c0.000000,-2.200000 1.800000,-4.000000 4.000000,-4.000000L7.700000,10.000000z"
+        android:fillColor="#000000"/>
+</vector>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 600c08c..7ff00ce 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -13691,6 +13691,14 @@
     <string name="keywords_contacts_storage">contacts, storage, account</string>
     <!-- Text for Contacts Storage Settings title [CHAR LIMIT=50]-->
     <string name="contacts_storage_settings_title">Contacts storage</string>
+    <!-- Text for "device only" preference label in Contacts Storage Settings [CHAR LIMIT=34] -->
+    <string name="contacts_storage_device_only_preference_label">Device only</string>
+    <!-- Text for "device only" preference summary in Contacts Storage Settings [CHAR LIMIT=NONE] -->
+    <string name="contacts_storage_device_only_preference_summary">New contacts won\'t be synced with an account</string>
+    <!-- Text for explaining the selection in Contacts Storage Settings [CHAR LIMIT=NONE] -->
+    <string name="contacts_storage_selection_message">Contacts will be saved to your device and synced to your account by default</string>
     <!-- Text for displaying when no account is set as default account [CHAR LIMIT=50] -->
     <string name="contacts_storage_no_account_set">No default set</string>
+    <!-- Text for add account selection message when no account has been added [CHAR LIMIT=100] -->
+    <string name="contacts_storage_first_time_add_account_message">Add an account to get started</string>
 </resources>
diff --git a/res/xml/apps.xml b/res/xml/apps.xml
index a66cea3..77b210f 100644
--- a/res/xml/apps.xml
+++ b/res/xml/apps.xml
@@ -85,6 +85,7 @@
         android:summary="@string/summary_placeholder"
         android:order="13"
         settings:controller="com.android.settings.applications.contacts.ContactsStoragePreferenceController"
+        android:fragment="com.android.settings.applications.contacts.ContactsStorageSettings"
         settings:keywords="@string/keywords_contacts_storage">
     </Preference>
 
diff --git a/res/xml/contacts_storage_settings.xml b/res/xml/contacts_storage_settings.xml
new file mode 100644
index 0000000..7cbabe7
--- /dev/null
+++ b/res/xml/contacts_storage_settings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:title="@string/contacts_storage_settings_title">
+
+    <com.android.settingslib.widget.TopIntroPreference
+        android:title="@string/contacts_storage_selection_message" />
+
+    <com.android.settingslib.widget.SelectorWithWidgetPreference
+        android:key="device_only_account_preference"
+        android:summary="@string/contacts_storage_device_only_preference_summary"
+        android:title="@string/contacts_storage_device_only_preference_label"
+        android:icon="@drawable/cloud_off"
+        android:order="999"
+        settings:allowDividerAbove="true"/>
+</PreferenceScreen>
diff --git a/src/com/android/settings/applications/contacts/ContactsStorageSettings.java b/src/com/android/settings/applications/contacts/ContactsStorageSettings.java
new file mode 100644
index 0000000..90d593a
--- /dev/null
+++ b/src/com/android/settings/applications/contacts/ContactsStorageSettings.java
@@ -0,0 +1,195 @@
+
+/*
+ * Copyright (C) 2020 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.contacts;
+
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.provider.Settings.ACTION_ADD_ACCOUNT;
+import static android.provider.Settings.EXTRA_ACCOUNT_TYPES;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.provider.ContactsContract.Settings;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.UiThread;
+import androidx.preference.Preference;
+import androidx.preference.Preference.OnPreferenceClickListener;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.accounts.AddAccountSettings;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.RestrictedPreference;
+import com.android.settingslib.accounts.AuthenticatorHelper;
+import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Settings page for contacts default account
+ */
+@SearchIndexable
+public class ContactsStorageSettings extends DashboardFragment
+        implements SelectorWithWidgetPreference.OnClickListener, OnPreferenceClickListener {
+    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider(R.xml.contacts_storage_settings);
+    private static final String TAG = "ContactsStorageSettings";
+    private static final String PREF_KEY_ADD_ACCOUNT = "add_account";
+    private static final String PREF_KEY_DEVICE_ONLY = "device_only_account_preference";
+    private final Map<String, Account> mAccountMap = new HashMap<>();
+    private AuthenticatorHelper mAuthenticatorHelper;
+
+    @Override
+    public void onAttach(@NonNull Context context) {
+        super.onAttach(context);
+        mAuthenticatorHelper = new AuthenticatorHelper(context,
+                new UserHandle(UserHandle.myUserId()), null);
+    }
+
+    @UiThread
+    @Override
+    public void onRadioButtonClicked(@NonNull SelectorWithWidgetPreference selectedPref) {
+        final String selectedPreferenceKey = selectedPref.getKey();
+        // Check if current provider is different from the selected provider.
+        for (String preferenceKey : mAccountMap.keySet()) {
+            if (selectedPreferenceKey.equals(preferenceKey)) {
+                selectedPref.setChecked(true);
+                //TODO: Call DefaultAccount.setDefaultAccountForNewContacts once
+                // the implementation is ready.
+                Settings.setDefaultAccount(getContentResolver(), mAccountMap.get(preferenceKey));
+            } else {
+                SelectorWithWidgetPreference unSelectedPreference =
+                        getPreferenceScreen().findPreference(preferenceKey);
+                if (unSelectedPreference != null) {
+                    unSelectedPreference.setChecked(false);
+                }
+            }
+        }
+    }
+
+    public boolean onPreferenceClick(@NonNull Preference preference) {
+        if (PREF_KEY_ADD_ACCOUNT.equals(preference.getKey())) {
+            Resources resources = Resources.getSystem();
+            String[] accountTypesArray =
+                    resources.getStringArray(
+                            com.android.internal.R.array.config_rawContactsEligibleDefaultAccountTypes);
+            Intent intent = new Intent(ACTION_ADD_ACCOUNT);
+            intent.setClass(getContext(), AddAccountSettings.class);
+            intent.putExtra(EXTRA_ACCOUNT_TYPES, accountTypesArray);
+            intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
+            getContext().startActivity(intent);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void onCreatePreferences(@NonNull Bundle savedInstanceState,
+        @NonNull String rootKey) {
+        super.onCreatePreferences(savedInstanceState, rootKey);
+        refreshUI();
+    }
+
+    @UiThread
+    void refreshUI() {
+        // Clear all the accounts stored in the map and later on re-fetch the eligible accounts
+        // when creating eligible account preferences.
+        mAccountMap.clear();
+        final PreferenceScreen screen = getPreferenceScreen();
+        AccountManager accountManager = AccountManager.get(getPrefContext());
+        //TODO: Call DefaultAccount.getDefaultAccountForNewContacts once
+        // implementation is ready.
+        Account[] accounts = accountManager.getAccounts();
+
+        for (int i = 0; i < accounts.length; i++) {
+            screen.addPreference(buildAccountPreference(accounts[i], i));
+        }
+        screen.addPreference(buildAddAccountPreference(accounts.length == 0));
+        setupDeviceOnlyPreference();
+
+        //TODO: Call DefaultAccount.ListEligibleCloudAccounts once the
+        // implementation is ready. And differentiate device only account vs account not set case.
+        Account currentDefaultAccount = Settings.getDefaultAccount(getContentResolver());
+        String preferenceKey = currentDefaultAccount != null ?
+                String.valueOf(currentDefaultAccount.hashCode()) : PREF_KEY_DEVICE_ONLY;
+        SelectorWithWidgetPreference preference = getPreferenceScreen().findPreference(
+                preferenceKey);
+        if (preference != null) {
+            preference.setChecked(true);
+        }
+    }
+
+    private void setupDeviceOnlyPreference() {
+        SelectorWithWidgetPreference preference = findPreference(PREF_KEY_DEVICE_ONLY);
+        if (preference != null) {
+            preference.setOnClickListener(this);
+            mAccountMap.put(PREF_KEY_DEVICE_ONLY, null);
+        }
+    }
+
+    //TODO: Add preference category on account preferences.
+    private Preference buildAccountPreference(Account account, int order) {
+        SelectorWithWidgetPreference preference = new SelectorWithWidgetPreference(
+                getPrefContext());
+        preference.setTitle(mAuthenticatorHelper.getLabelForType(getPrefContext(), account.type));
+        preference.setIcon(mAuthenticatorHelper.getDrawableForType(getPrefContext(), account.type));
+        preference.setSummary(account.name);
+        preference.setKey(String.valueOf(account.hashCode()));
+        preference.setOnClickListener(this);
+        preference.setOrder(order);
+        mAccountMap.put(String.valueOf(account.hashCode()), account);
+        return preference;
+    }
+
+    private RestrictedPreference buildAddAccountPreference(boolean noAccountBeenAdded) {
+        RestrictedPreference preference = new RestrictedPreference(getPrefContext());
+        preference.setKey(PREF_KEY_ADD_ACCOUNT);
+        if (noAccountBeenAdded) {
+            preference.setTitle(R.string.contacts_storage_first_time_add_account_message);
+        } else {
+            preference.setTitle(R.string.add_account_label);
+        }
+        preference.setIcon(R.drawable.ic_add_24dp);
+        preference.setOnPreferenceClickListener(this);
+        preference.setOrder(998);
+        return preference;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.contacts_storage_settings;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.CONTACTS_STORAGE;
+    }
+}
diff --git a/src/com/android/settings/dashboard/profileselector/UserAdapter.java b/src/com/android/settings/dashboard/profileselector/UserAdapter.java
index 0fefa2f..54887d7 100644
--- a/src/com/android/settings/dashboard/profileselector/UserAdapter.java
+++ b/src/com/android/settings/dashboard/profileselector/UserAdapter.java
@@ -71,7 +71,9 @@
                         && userInfo.isPrivateProfile())) {
                 mIcon = context.getPackageManager().getUserBadgeForDensityNoBackground(
                         userHandle, /* density= */ 0);
-                mIcon.setTint(tintColor);
+                if (mIcon != null) {
+                    mIcon.setTint(tintColor);
+                }
             } else {
                 mIcon = UserIcons.getDefaultUserIconInColor(context.getResources(), tintColor);
             }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBroadcastReceiver.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBroadcastReceiver.java
index f710c71..5c250ab 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBroadcastReceiver.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBroadcastReceiver.java
@@ -106,6 +106,10 @@
 
     private void tryToFetchUsageData(Context context) {
         final Intent batteryIntent = BatteryUtils.getBatteryIntent(context);
+        if (batteryIntent == null) {
+            Log.w(TAG, "tryToFetchUsageData: ignore from null battery intent");
+            return;
+        }
         // Returns when battery is not fully charged.
         if (!BatteryStatus.isCharged(batteryIntent)) {
             return;
diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
index 235418e..82083b5 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
@@ -610,12 +610,8 @@
     }
 
     public static CharSequence getCurrentCarrierNameForDisplay(Context context) {
-        final SubscriptionInfo subInfo = getSubscriptionInfo(context,
+        return getCurrentCarrierNameForDisplay(context,
                 SubscriptionManager.getDefaultSubscriptionId());
-        if (subInfo != null) {
-            return subInfo.getCarrierName();
-        }
-        return getOperatorNameFromTelephonyManager(context);
     }
 
     private static @Nullable SubscriptionInfo getSubscriptionInfo(Context context, int subId) {
diff --git a/src/com/android/settings/notification/modes/ZenHelperBackend.java b/src/com/android/settings/notification/modes/ZenHelperBackend.java
index bf91678..31c1ce4 100644
--- a/src/com/android/settings/notification/modes/ZenHelperBackend.java
+++ b/src/com/android/settings/notification/modes/ZenHelperBackend.java
@@ -18,13 +18,17 @@
 
 import android.annotation.Nullable;
 import android.app.INotificationManager;
+import android.content.ContentProvider;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
 import android.service.notification.ConversationChannelWrapper;
 import android.util.Log;
 
@@ -39,6 +43,7 @@
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Function;
 
 /**
  * Class used for Settings-system_server interactions that are not <em>directly</em> related to
@@ -54,6 +59,7 @@
 
     private final Context mContext;
     private final INotificationManager mInm;
+    private final UserManager mUserManager;
 
     static ZenHelperBackend getInstance(Context context) {
         if (sInstance == null) {
@@ -66,6 +72,7 @@
         mContext = context;
         mInm = INotificationManager.Stub.asInterface(
                 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+        mUserManager = context.getSystemService(UserManager.class);
     }
 
     /**
@@ -81,10 +88,12 @@
         }
     }
 
+    /** Returns all conversation channels for profiles of the current user. */
     ImmutableList<ConversationChannelWrapper> getAllConversations() {
         return getConversations(false);
     }
 
+    /** Returns all important (priority) conversation channels for profiles of the current user. */
     ImmutableList<ConversationChannelWrapper> getImportantConversations() {
         return getConversations(true);
     }
@@ -97,7 +106,9 @@
                     onlyImportant);
             if (parceledList != null) {
                 for (ConversationChannelWrapper conversation : parceledList.getList()) {
-                    if (!conversation.getNotificationChannel().isDemoted()) {
+                    if (conversation.getShortcutInfo() != null
+                            && conversation.getNotificationChannel() != null
+                            && !conversation.getNotificationChannel().isDemoted()) {
                         list.add(conversation);
                     }
                 }
@@ -109,38 +120,52 @@
         }
     }
 
-    record Contact(long id, @Nullable String displayName, @Nullable Uri photoUri) { }
+    record Contact(UserHandle user, long contactId, @Nullable String displayName,
+                   @Nullable Uri photoUri) { }
 
+    /** Returns all contacts for profiles of the current user. */
     ImmutableList<Contact> getAllContacts() {
-        try (Cursor cursor = queryAllContactsData()) {
-            return getContactsFromCursor(cursor);
-        }
+        return getContactsForUserProfiles(this::queryAllContactsData);
     }
 
+    /** Returns all starred contacts for profiles of the current user. */
     ImmutableList<Contact> getStarredContacts() {
-        try (Cursor cursor = queryStarredContactsData()) {
-            return getContactsFromCursor(cursor);
-        }
+        return getContactsForUserProfiles(this::queryStarredContactsData);
     }
 
-    private ImmutableList<Contact> getContactsFromCursor(Cursor cursor) {
-        ImmutableList.Builder<Contact> list = new ImmutableList.Builder<>();
+    private ImmutableList<Contact> getContactsForUserProfiles(
+            Function<UserHandle, Cursor> userQuery) {
+        ImmutableList.Builder<Contact> contacts = new ImmutableList.Builder<>();
+        for (UserHandle user : mUserManager.getAllProfiles()) {
+            try (Cursor cursor = userQuery.apply(user)) {
+                loadContactsFromCursor(user, cursor, contacts);
+            }
+        }
+        return contacts.build();
+    }
+
+    private void loadContactsFromCursor(UserHandle user, Cursor cursor,
+            ImmutableList.Builder<Contact> contactsListBuilder) {
         if (cursor != null && cursor.moveToFirst()) {
             do {
                 long id = cursor.getLong(0);
                 String name = Strings.emptyToNull(cursor.getString(1));
                 String photoUriStr = cursor.getString(2);
                 Uri photoUri = !Strings.isNullOrEmpty(photoUriStr) ? Uri.parse(photoUriStr) : null;
-                list.add(new Contact(id, name, photoUri));
+                contactsListBuilder.add(new Contact(user, id, name,
+                        ContentProvider.maybeAddUserId(photoUri, user.getIdentifier())));
             } while (cursor.moveToNext());
         }
-        return list.build();
     }
 
     int getAllContactsCount() {
-        try (Cursor cursor = queryAllContactsData()) {
-            return cursor != null ? cursor.getCount() : 0;
+        int count = 0;
+        for (UserHandle user : mUserManager.getEnabledProfiles()) {
+            try (Cursor cursor = queryAllContactsData(user)) {
+                count += (cursor != null ? cursor.getCount() : 0);
+            }
         }
+        return count;
     }
 
     private static final String[] CONTACTS_PROJECTION = new String[] {
@@ -149,17 +174,17 @@
             ContactsContract.Contacts.PHOTO_THUMBNAIL_URI
     };
 
-    private Cursor queryStarredContactsData() {
+    private Cursor queryStarredContactsData(UserHandle user) {
         return mContext.getContentResolver().query(
-                ContactsContract.Contacts.CONTENT_URI,
+                ContentProvider.maybeAddUserId(Contacts.CONTENT_URI, user.getIdentifier()),
                 CONTACTS_PROJECTION,
                 /* selection= */ ContactsContract.Data.STARRED + "=1", /* selectionArgs= */ null,
                 /* sortOrder= */ ContactsContract.Contacts.DISPLAY_NAME_PRIMARY);
     }
 
-    private Cursor queryAllContactsData() {
+    private Cursor queryAllContactsData(UserHandle user) {
         return mContext.getContentResolver().query(
-                ContactsContract.Contacts.CONTENT_URI,
+                ContentProvider.maybeAddUserId(Contacts.CONTENT_URI, user.getIdentifier()),
                 CONTACTS_PROJECTION,
                 /* selection= */ null, /* selectionArgs= */ null,
                 /* sortOrder= */ ContactsContract.Contacts.DISPLAY_NAME_PRIMARY);
diff --git a/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceController.java b/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceController.java
index de1adc7..cd358bf 100644
--- a/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceController.java
@@ -17,7 +17,9 @@
 package com.android.settings.notification.modes;
 
 import android.content.Context;
+import android.view.View;
 import android.widget.Button;
+import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -32,6 +34,7 @@
 
     private final Runnable mConfirmSave;
     @Nullable private Button mButton;
+    private boolean mHasValidName;
 
     ZenModeEditDonePreferenceController(@NonNull Context context, @NonNull String key,
             Runnable confirmSave) {
@@ -46,15 +49,22 @@
         if (pref != null) {
             mButton = pref.findViewById(R.id.done);
             if (mButton != null) {
-                mButton.setOnClickListener(v -> mConfirmSave.run());
+                mButton.setOnClickListener(this::onButtonClick);
             }
         }
     }
 
+    private void onButtonClick(View view) {
+        if (mHasValidName) {
+            mConfirmSave.run();
+        } else {
+            Toast.makeText(mContext, R.string.zen_mode_edit_name_empty_error, Toast.LENGTH_SHORT)
+                    .show();
+        }
+    }
+
     @Override
     void updateState(Preference preference, @NonNull ZenMode zenMode) {
-        if (mButton != null) {
-            mButton.setEnabled(!zenMode.getName().isBlank());
-        }
+        mHasValidName = !zenMode.getName().isBlank();
     }
 }
diff --git a/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceController.java b/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceController.java
index 3b9311d..2a7ec90 100644
--- a/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceController.java
@@ -28,11 +28,14 @@
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import android.app.Dialog;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.icu.text.MessageFormat;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Contacts;
 import android.service.notification.ZenPolicy;
 import android.view.View;
@@ -46,6 +49,7 @@
 
 import com.android.settings.R;
 import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.profileselector.ProfileSelectDialog;
 import com.android.settings.notification.app.ConversationListSettings;
 import com.android.settingslib.notification.modes.ZenMode;
 import com.android.settingslib.notification.modes.ZenModesBackend;
@@ -55,6 +59,7 @@
 
 import java.util.HashMap;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
@@ -87,16 +92,18 @@
     private static final Intent STARRED_CONTACTS_INTENT =
             new Intent(Contacts.Intents.UI.LIST_STARRED_ACTION)
                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK  | Intent.FLAG_ACTIVITY_CLEAR_TASK);
-    private static final Intent FALLBACK_INTENT = new Intent(Intent.ACTION_MAIN)
+    private static final Intent FALLBACK_CONTACTS_INTENT = new Intent(Intent.ACTION_MAIN)
             .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
 
     private final ZenHelperBackend mHelperBackend;
+    private final UserManager mUserManager;
     private final PackageManager mPackageManager;
     private PreferenceCategory mPreferenceCategory;
     private final LinkedHashMap<String, SelectorWithWidgetPreference> mOptions =
             new LinkedHashMap<>();
 
     private final ZenModeSummaryHelper mZenModeSummaryHelper;
+    @Nullable private Dialog mProfileSelectDialog;
 
     public ZenModePrioritySendersPreferenceController(Context context, String key,
             boolean isMessages, ZenModesBackend backend, ZenHelperBackend helperBackend) {
@@ -107,11 +114,12 @@
         String contactsPackage = context.getString(R.string.config_contacts_package_name);
         ALL_CONTACTS_INTENT.setPackage(contactsPackage);
         STARRED_CONTACTS_INTENT.setPackage(contactsPackage);
-        FALLBACK_INTENT.setPackage(contactsPackage);
+        FALLBACK_CONTACTS_INTENT.setPackage(contactsPackage);
 
+        mUserManager = mContext.getSystemService(UserManager.class);
         mPackageManager = mContext.getPackageManager();
-        if (!FALLBACK_INTENT.hasCategory(Intent.CATEGORY_APP_CONTACTS)) {
-            FALLBACK_INTENT.addCategory(Intent.CATEGORY_APP_CONTACTS);
+        if (!FALLBACK_CONTACTS_INTENT.hasCategory(Intent.CATEGORY_APP_CONTACTS)) {
+            FALLBACK_CONTACTS_INTENT.addCategory(Intent.CATEGORY_APP_CONTACTS);
         }
         mZenModeSummaryHelper = new ZenModeSummaryHelper(mContext, mHelperBackend);
     }
@@ -270,32 +278,48 @@
         }
 
         return v -> {
-            if (KEY_STARRED.equals(key)
-                    && STARRED_CONTACTS_INTENT.resolveActivity(mPackageManager) != null) {
-                mContext.startActivity(STARRED_CONTACTS_INTENT);
-            } else if (KEY_CONTACTS.equals(key)
-                    && ALL_CONTACTS_INTENT.resolveActivity(mPackageManager) != null) {
-                mContext.startActivity(ALL_CONTACTS_INTENT);
+            if (KEY_STARRED.equals(key)) {
+                startContactsActivity(STARRED_CONTACTS_INTENT);
+            } else if (KEY_CONTACTS.equals(key)) {
+                startContactsActivity(ALL_CONTACTS_INTENT);
             } else if (KEY_ANY_CONVERSATIONS.equals(key)
                     || KEY_IMPORTANT_CONVERSATIONS.equals(key)) {
                 new SubSettingLauncher(mContext)
                         .setDestination(ConversationListSettings.class.getName())
                         .setSourceMetricsCategory(SettingsEnums.DND_MESSAGES)
                         .launch();
-            } else {
-                mContext.startActivity(FALLBACK_INTENT);
             }
         };
     }
 
+    private void startContactsActivity(Intent preferredIntent) {
+        Intent intent = preferredIntent.resolveActivity(mPackageManager) != null
+                ? preferredIntent : FALLBACK_CONTACTS_INTENT;
+
+        List<UserHandle> userProfiles = mUserManager.getEnabledProfiles();
+        if (userProfiles.size() <= 1) {
+            mContext.startActivity(intent);
+        }
+
+        mProfileSelectDialog = ProfileSelectDialog.createDialog(mContext, userProfiles,
+                position -> {
+                    mContext.startActivityAsUser(intent, userProfiles.get(position));
+                    if (mProfileSelectDialog != null) {
+                        mProfileSelectDialog.dismiss();
+                        mProfileSelectDialog = null;
+                    }
+                });
+        mProfileSelectDialog.show();
+    }
+
     private boolean isStarredIntentValid() {
         return STARRED_CONTACTS_INTENT.resolveActivity(mPackageManager) != null
-                || FALLBACK_INTENT.resolveActivity(mPackageManager) != null;
+                || FALLBACK_CONTACTS_INTENT.resolveActivity(mPackageManager) != null;
     }
 
     private boolean isContactsIntentValid() {
         return ALL_CONTACTS_INTENT.resolveActivity(mPackageManager) != null
-                || FALLBACK_INTENT.resolveActivity(mPackageManager) != null;
+                || FALLBACK_CONTACTS_INTENT.resolveActivity(mPackageManager) != null;
     }
 
     void updateSummaries() {
diff --git a/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceController.java b/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceController.java
index d6b2f01..651b7cc 100644
--- a/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceController.java
@@ -27,10 +27,10 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
-import androidx.fragment.app.Fragment;
 import androidx.preference.Preference;
 
 import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.notification.modes.ZenMode;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 import com.android.settingslib.widget.LayoutPreference;
@@ -51,11 +51,10 @@
     private final SimpleDateFormat mShortDayFormat = new SimpleDateFormat("EEEEE");
     private final SimpleDateFormat mLongDayFormat = new SimpleDateFormat("EEEE");
 
-    private static final String TAG = "ZenModeSetSchedulePreferenceController";
-    private Fragment mParent;
+    private DashboardFragment mParent;
     private ZenModeConfig.ScheduleInfo mSchedule;
 
-    ZenModeSetSchedulePreferenceController(Context context, Fragment parent, String key,
+    ZenModeSetSchedulePreferenceController(Context context, DashboardFragment parent, String key,
             ZenModesBackend backend) {
         super(context, key, backend);
         mParent = parent;
@@ -154,11 +153,7 @@
 
     private View.OnClickListener timePickerLauncher(int hour, int minute,
             ZenModeTimePickerFragment.TimeSetter timeSetter) {
-        return v -> {
-            final ZenModeTimePickerFragment frag = new ZenModeTimePickerFragment(mContext, hour,
-                    minute, timeSetter);
-            frag.show(mParent.getParentFragmentManager(), TAG);
-        };
+        return v -> ZenModeTimePickerFragment.show(mParent, hour, minute, timeSetter);
     }
 
     protected static int[] getDaysOfWeekForLocale(Calendar c) {
diff --git a/src/com/android/settings/notification/modes/ZenModeTimePickerFragment.java b/src/com/android/settings/notification/modes/ZenModeTimePickerFragment.java
index 3fa5394..4594e5c 100644
--- a/src/com/android/settings/notification/modes/ZenModeTimePickerFragment.java
+++ b/src/com/android/settings/notification/modes/ZenModeTimePickerFragment.java
@@ -16,10 +16,11 @@
 
 package com.android.settings.notification.modes;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import android.app.Dialog;
 import android.app.TimePickerDialog;
 import android.app.settings.SettingsEnums;
-import android.content.Context;
 import android.os.Bundle;
 import android.text.format.DateFormat;
 import android.widget.TimePicker;
@@ -27,37 +28,54 @@
 import androidx.annotation.NonNull;
 
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.dashboard.DashboardFragment;
 
 /**
  * Dialog that shows when a user selects a (start or end) time to edit for a schedule-based mode.
  */
 public class ZenModeTimePickerFragment extends InstrumentedDialogFragment implements
         TimePickerDialog.OnTimeSetListener {
-    private final Context mContext;
-    private final TimeSetter mTimeSetter;
-    private final int mHour;
-    private final int mMinute;
 
-    public ZenModeTimePickerFragment(Context context, int hour, int minute,
+    private static final String TAG = "ZenModeTimePickerFragment";
+
+    private TimeSetter mTimeSetter;
+    private int mHour;
+    private int mMinute;
+
+    public static void show(DashboardFragment parent, int hour, int minute,
             @NonNull TimeSetter timeSetter) {
-        super();
-        mContext = context;
-        mHour = hour;
-        mMinute = minute;
-        mTimeSetter = timeSetter;
+        ZenModeTimePickerFragment fragment = new ZenModeTimePickerFragment();
+        fragment.mHour = hour;
+        fragment.mMinute = minute;
+        fragment.mTimeSetter = timeSetter;
+
+        fragment.show(parent.getParentFragmentManager(), TAG);
     }
 
     @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (mTimeSetter == null) {
+            // Probably the dialog fragment was recreated after its activity was destroyed.
+            // It's pointless to re-show the dialog if we can't do anything when its options are
+            // selected, so we don't.
+            dismiss();
+        }
+    }
+
+    @NonNull
+    @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
-        return new TimePickerDialog(mContext, this, mHour, mMinute,
-                DateFormat.is24HourFormat(mContext));
+        return new TimePickerDialog(getContext(), this, mHour, mMinute,
+                DateFormat.is24HourFormat(getContext()));
     }
 
     /**
      * Calls the provided TimeSetter's setTime() method when a time is set on the TimePicker.
      */
+    @Override
     public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
-        mTimeSetter.setTime(hourOfDay, minute);
+        checkNotNull(mTimeSetter).setTime(hourOfDay, minute);
     }
 
     @Override
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index 97e41b4..4723b0e 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -276,8 +276,10 @@
             }
         }
         if (canFindNetwork) {
+            Log.e(TAG, "WiFi DPP check connection no matched security");
             return R.string.wifi_dpp_check_connection_no_matched_security;
         }
+        Log.e(TAG, "WiFi DPP check connection no matched SSID");
         return R.string.wifi_dpp_check_connection_no_matched_ssid;
     }
 
diff --git a/tests/robotests/src/com/android/settings/applications/contacts/ContactsStorageSettingsTest.java b/tests/robotests/src/com/android/settings/applications/contacts/ContactsStorageSettingsTest.java
new file mode 100644
index 0000000..785ef4a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/contacts/ContactsStorageSettingsTest.java
@@ -0,0 +1,240 @@
+/*
+ * 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.contacts;
+
+import static android.provider.ContactsContract.Settings.KEY_DEFAULT_ACCOUNT;
+import static android.provider.ContactsContract.Settings.QUERY_DEFAULT_ACCOUNT_METHOD;
+import static android.provider.ContactsContract.Settings.SET_DEFAULT_ACCOUNT_METHOD;
+import static android.provider.Settings.ACTION_ADD_ACCOUNT;
+import static android.provider.Settings.EXTRA_ACCOUNT_TYPES;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.settings.SettingsEnums;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.provider.SearchIndexableResource;
+
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.accounts.AddAccountSettings;
+import com.android.settings.testutils.shadow.ShadowAuthenticationHelper;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowAuthenticationHelper.class)
+public class ContactsStorageSettingsTest {
+    private static final String PREF_KEY_DEVICE_ONLY = "device_only_account_preference";
+
+    private static final String PREF_KEY_ADD_ACCOUNT = "add_account";
+
+    private static final Account TEST_ACCOUNT1 = new Account("test@gmail.com", "type1");
+
+    private static final Account TEST_ACCOUNT2 = new Account("test@samsung.com", "type2");
+
+    @Rule
+    public final MockitoRule mockito = MockitoJUnit.rule();
+    @Spy
+    public final Context mContext = spy(ApplicationProvider.getApplicationContext());
+    @Mock
+    private ContentResolver mContentResolver;
+    @Mock
+    private AccountManager mAccountManager;
+
+    private PreferenceManager mPreferenceManager;
+    private TestContactsStorageSettings mContactsStorageSettings;
+    private PreferenceScreen mScreen;
+
+    @Before
+    public void setUp() throws Exception {
+        mContactsStorageSettings = spy(new TestContactsStorageSettings(mContext, mContentResolver));
+        when(mContext.getSystemService(eq(Context.ACCOUNT_SERVICE))).thenReturn(mAccountManager);
+        when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[]{});
+        mPreferenceManager = new PreferenceManager(mContext);
+        when(mContactsStorageSettings.getPreferenceManager()).thenReturn(mPreferenceManager);
+        mScreen = spy(new PreferenceScreen(mContext, /* attrs= */ null));
+        when(mScreen.getPreferenceManager()).thenReturn(mPreferenceManager);
+        when(mContactsStorageSettings.getPreferenceScreen()).thenReturn(mScreen);
+        mContactsStorageSettings.onAttach(mContext);
+    }
+
+    @Test
+    public void getMetricsCategory() {
+        assertThat(mContactsStorageSettings.getMetricsCategory()).isEqualTo(
+                SettingsEnums.CONTACTS_STORAGE);
+    }
+
+    @Test
+    public void getPreferenceScreenResId() {
+        assertThat(mContactsStorageSettings.getPreferenceScreenResId()).isEqualTo(
+                R.xml.contacts_storage_settings);
+    }
+
+    @Test
+    public void verifyDeviceOnlyPreference_onClick_setDefaultAccountToNull() {
+        when(mAccountManager.getAccounts()).thenReturn(new Account[]{});
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(KEY_DEFAULT_ACCOUNT, null);
+        when(mContentResolver.call(eq(ContactsContract.AUTHORITY_URI),
+                eq(QUERY_DEFAULT_ACCOUNT_METHOD), any(), any())).thenReturn(bundle);
+
+        PreferenceScreen settingScreen = mPreferenceManager.inflateFromResource(mContext,
+                R.xml.contacts_storage_settings, mScreen);
+        SelectorWithWidgetPreference deviceOnlyPreference = settingScreen.findPreference(
+                PREF_KEY_DEVICE_ONLY);
+        when(mContactsStorageSettings.findPreference(eq(PREF_KEY_DEVICE_ONLY))).thenReturn(
+                deviceOnlyPreference);
+
+        assertThat(deviceOnlyPreference.getTitle()).isEqualTo("Device only");
+        assertThat(deviceOnlyPreference.getSummary()).isEqualTo(
+                "New contacts won't be synced with an account");
+        assertThat(deviceOnlyPreference.getOrder()).isEqualTo(999);
+
+        mContactsStorageSettings.refreshUI();
+        mContactsStorageSettings.onRadioButtonClicked(deviceOnlyPreference);
+
+        assertThat(deviceOnlyPreference.isChecked()).isTrue();
+        ArgumentCaptor<Bundle> captor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mContentResolver).call(eq(ContactsContract.AUTHORITY_URI),
+                eq(SET_DEFAULT_ACCOUNT_METHOD), any(), captor.capture());
+        Bundle accountBundle = captor.getValue();
+        assertThat(accountBundle.getString(ContactsContract.Settings.ACCOUNT_NAME)).isNull();
+        assertThat(accountBundle.getString(ContactsContract.Settings.ACCOUNT_TYPE)).isNull();
+    }
+
+    @Test
+    public void verifyAddAccountPreference_onClick_startAddAccountActivity() {
+        when(mAccountManager.getAccounts()).thenReturn(new Account[]{});
+        when(mContentResolver.call(eq(ContactsContract.AUTHORITY_URI),
+                eq(QUERY_DEFAULT_ACCOUNT_METHOD), any(), any())).thenReturn(Bundle.EMPTY);
+
+        mContactsStorageSettings.refreshUI();
+
+        assertThat(mScreen.findPreference(PREF_KEY_ADD_ACCOUNT).getTitle()).isEqualTo(
+                "Add an account to get started");
+        assertThat(mScreen.findPreference(PREF_KEY_ADD_ACCOUNT).getOrder()).isEqualTo(998);
+
+        mScreen.findPreference(PREF_KEY_ADD_ACCOUNT).performClick();
+
+        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).startActivity(captor.capture());
+        Intent addAccountIntent = captor.getValue();
+        assertThat(addAccountIntent.getAction()).isEqualTo(ACTION_ADD_ACCOUNT);
+        assertThat(addAccountIntent.getComponent().getClassName()).isEqualTo(
+                AddAccountSettings.class.getCanonicalName());
+        String[] eligibleAccounts = (String[]) addAccountIntent.getExtra(EXTRA_ACCOUNT_TYPES);
+        assertThat(eligibleAccounts).isEmpty();
+    }
+
+    @Test
+    public void verifyEligibleAccountPreference_onClick_setSelectedDefaultAccount() {
+        when(mAccountManager.getAccounts()).thenReturn(new Account[]{TEST_ACCOUNT1, TEST_ACCOUNT2});
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(KEY_DEFAULT_ACCOUNT, TEST_ACCOUNT2);
+        when(mContentResolver.call(eq(ContactsContract.AUTHORITY_URI),
+                eq(QUERY_DEFAULT_ACCOUNT_METHOD), any(), any())).thenReturn(bundle);
+
+        mContactsStorageSettings.refreshUI();
+
+        SelectorWithWidgetPreference account1Preference = mScreen.findPreference(
+                String.valueOf(TEST_ACCOUNT1.hashCode()));
+        assertThat(account1Preference.getTitle()).isEqualTo("LABEL1");
+        assertThat(account1Preference.getSummary()).isEqualTo("test@gmail.com");
+        assertThat(account1Preference.getIcon()).isNotNull();
+
+        SelectorWithWidgetPreference account2Preference = mScreen.findPreference(
+                String.valueOf(TEST_ACCOUNT2.hashCode()));
+        assertThat(account2Preference.getTitle()).isEqualTo("LABEL2");
+        assertThat(account2Preference.getSummary()).isEqualTo("test@samsung.com");
+        assertThat(account2Preference.getIcon()).isNotNull();
+
+        mContactsStorageSettings.onRadioButtonClicked(account2Preference);
+        assertThat(account1Preference.isChecked()).isFalse();
+        assertThat(account2Preference.isChecked()).isTrue();
+
+        ArgumentCaptor<Bundle> captor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mContentResolver).call(eq(ContactsContract.AUTHORITY_URI),
+                eq(SET_DEFAULT_ACCOUNT_METHOD), any(), captor.capture());
+        Bundle setAccountBundle = captor.getValue();
+        assertThat(setAccountBundle.getString(ContactsContract.Settings.ACCOUNT_NAME)).isEqualTo(
+                "test@samsung.com");
+        assertThat(setAccountBundle.getString(ContactsContract.Settings.ACCOUNT_TYPE)).isEqualTo(
+                "type2");
+    }
+
+    @Test
+    public void searchIndexProvider_shouldIndexResource() {
+        final List<SearchIndexableResource> indexRes =
+                ContactsStorageSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
+                        RuntimeEnvironment.application, true /* enabled */);
+
+        assertThat(indexRes).isNotNull();
+        assertThat(indexRes.get(0).xmlResId).isEqualTo(
+                mContactsStorageSettings.getPreferenceScreenResId());
+    }
+
+    private static class TestContactsStorageSettings extends ContactsStorageSettings {
+        private final Context mContext;
+        private final ContentResolver mContentResolver;
+
+        TestContactsStorageSettings(Context context, ContentResolver contentResolver) {
+            mContext = context;
+            mContentResolver = contentResolver;
+        }
+
+        @Override
+        public Context getContext() {
+            return mContext;
+        }
+
+        @Override
+        protected ContentResolver getContentResolver() {
+            // Override it so we can access this method in test
+            return mContentResolver;
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenHelperBackendTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenHelperBackendTest.java
new file mode 100644
index 0000000..2288099
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenHelperBackendTest.java
@@ -0,0 +1,260 @@
+/*
+ * 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.notification.modes;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.Shadows.shadowOf;
+
+import android.app.Flags;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.pm.ProviderInfo;
+import android.content.pm.UserInfo;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.ContactsContract;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.settings.notification.modes.ZenHelperBackend.Contact;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+@RunWith(RobolectricTestRunner.class)
+@EnableFlags(Flags.FLAG_MODES_UI)
+public class ZenHelperBackendTest {
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+    private Context mContext;
+    private ZenHelperBackend mBackend;
+    private HashMap<Integer, FakeContactsProvider> mContactsProviders = new HashMap<>();
+
+    private int mUserId;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.getApplication();
+        mBackend = new ZenHelperBackend(mContext);
+
+        mUserId = mContext.getUserId();
+        addContactsProvider(mUserId);
+    }
+
+    private int addMainUserProfile() {
+        UserInfo workProfile = new UserInfo(mUserId + 10, "Work Profile", 0);
+        workProfile.userType = UserManager.USER_TYPE_PROFILE_MANAGED;
+        UserManager userManager = mContext.getSystemService(UserManager.class);
+        shadowOf(userManager).addProfile(mUserId, workProfile.id, workProfile);
+
+        addContactsProvider(workProfile.id);
+
+        return workProfile.id;
+    }
+
+    private void addContactsProvider(int userId) {
+        ProviderInfo providerInfo = new ProviderInfo();
+        providerInfo.authority = String.format("%s@%s", userId, ContactsContract.AUTHORITY);
+        mContactsProviders.put(userId, Robolectric.buildContentProvider(FakeContactsProvider.class)
+                .create(providerInfo).get());
+    }
+
+    private void addContact(int userId, String name, boolean starred) {
+        mContactsProviders.get(userId).addContact(name, starred);
+    }
+
+    @Test
+    public void getAllContacts_singleProfile() {
+        addContact(mUserId, "Huey", false);
+        addContact(mUserId, "Dewey", true);
+        addContact(mUserId, "Louie", false);
+
+        ImmutableList<Contact> allContacts = mBackend.getAllContacts();
+
+        assertThat(allContacts).containsExactly(
+                new Contact(UserHandle.of(mUserId), 1, "Huey", null),
+                new Contact(UserHandle.of(mUserId), 2, "Dewey", null),
+                new Contact(UserHandle.of(mUserId), 3, "Louie", null));
+    }
+
+    @Test
+    public void getAllContacts_multipleProfiles() {
+        int profileId = addMainUserProfile();
+        addContact(mUserId, "Huey", false);
+        addContact(mUserId, "Dewey", true);
+        addContact(mUserId, "Louie", false);
+        addContact(profileId, "Fry", false);
+        addContact(profileId, "Bender", true);
+
+        ImmutableList<Contact> allContacts = mBackend.getAllContacts();
+
+        assertThat(allContacts).containsExactly(
+                new Contact(UserHandle.of(mUserId), 1, "Huey", null),
+                new Contact(UserHandle.of(mUserId), 2, "Dewey", null),
+                new Contact(UserHandle.of(mUserId), 3, "Louie", null),
+                new Contact(UserHandle.of(profileId), 1, "Fry", null),
+                new Contact(UserHandle.of(profileId), 2, "Bender", null));
+    }
+
+    @Test
+    public void getStarredContacts_singleProfile() {
+        addContact(mUserId, "Huey", false);
+        addContact(mUserId, "Dewey", true);
+        addContact(mUserId, "Louie", false);
+
+        ImmutableList<Contact> allContacts = mBackend.getStarredContacts();
+
+        assertThat(allContacts).containsExactly(
+                new Contact(UserHandle.of(mUserId), 2, "Dewey", null));
+    }
+
+    @Test
+    public void getStarredContacts_multipleProfiles() {
+        int profileId = addMainUserProfile();
+        addContact(mUserId, "Huey", false);
+        addContact(mUserId, "Dewey", true);
+        addContact(mUserId, "Louie", false);
+        addContact(profileId, "Fry", false);
+        addContact(profileId, "Bender", true);
+
+        ImmutableList<Contact> allContacts = mBackend.getStarredContacts();
+
+        assertThat(allContacts).containsExactly(
+                new Contact(UserHandle.of(mUserId), 2, "Dewey", null),
+                new Contact(UserHandle.of(profileId), 2, "Bender", null));
+    }
+
+    @Test
+    public void getAllContactsCount_singleProfile() {
+        addContact(mUserId, "Huey", false);
+        addContact(mUserId, "Dewey", true);
+        addContact(mUserId, "Louie", false);
+
+        assertThat(mBackend.getAllContactsCount()).isEqualTo(3);
+    }
+
+    @Test
+    public void getAllContactsCount_multipleProfiles() {
+        int profileId = addMainUserProfile();
+        addContact(mUserId, "Huey", false);
+        addContact(mUserId, "Dewey", true);
+        addContact(mUserId, "Louie", false);
+        addContact(profileId, "Fry", false);
+        addContact(profileId, "Bender", true);
+
+        assertThat(mBackend.getAllContactsCount()).isEqualTo(5);
+    }
+
+    private static class FakeContactsProvider extends ContentProvider {
+
+        private record ContactRow(int id, String name, boolean starred) {}
+
+        private final ArrayList<ContactRow> mContacts = new ArrayList<>();
+
+        FakeContactsProvider() {
+        }
+
+        @Override
+        public boolean onCreate() {
+            return true;
+        }
+
+        public int addContact(String name, boolean starred) {
+            mContacts.add(new ContactRow(mContacts.size() + 1, name, starred));
+            return mContacts.size();
+        }
+
+        @Nullable
+        @Override
+        public Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+                @Nullable String selection, @Nullable String[] selectionArgs,
+                @Nullable String sortOrder) {
+            Uri baseUri = ContentProvider.getUriWithoutUserId(uri);
+            if (!ContactsContract.Contacts.CONTENT_URI.equals(baseUri)) {
+                throw new IllegalArgumentException("Unsupported uri for fake: " + uri);
+            }
+
+            if (projection == null || !Iterables.elementsEqual(ImmutableList.copyOf(projection),
+                    ImmutableList.of(ContactsContract.Contacts._ID,
+                            ContactsContract.Contacts.DISPLAY_NAME_PRIMARY,
+                            ContactsContract.Contacts.PHOTO_THUMBNAIL_URI))) {
+                throw new IllegalArgumentException(
+                        "Unsupported projection for fake: " + Arrays.toString(projection));
+            }
+
+            if (selection != null && !selection.equals(ContactsContract.Data.STARRED + "=1")) {
+                throw new IllegalArgumentException("Unsupported selection for fake: " + selection);
+            }
+            boolean selectingStarred = selection != null; // Checked as only valid selection above
+
+
+            MatrixCursor cursor = new MatrixCursor(projection);
+            for (ContactRow contactRow : mContacts) {
+                if (!selectingStarred || contactRow.starred) {
+                    cursor.addRow(ImmutableList.of(contactRow.id, contactRow.name, Uri.EMPTY));
+                }
+            }
+
+            return cursor;
+        }
+
+        @Override
+        @Nullable
+        public String getType(@NonNull Uri uri) {
+            return "";
+        }
+
+        @Nullable
+        @Override
+        public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int delete(@NonNull Uri uri, @Nullable String selection,
+                @Nullable String[] selectionArgs) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int update(@NonNull Uri uri, @Nullable ContentValues values,
+                @Nullable String selection, @Nullable String[] selectionArgs) {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceControllerTest.java
index 74328be..3d076a1 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceControllerTest.java
@@ -43,6 +43,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowToast;
 
 @RunWith(RobolectricTestRunner.class)
 @EnableFlags(Flags.FLAG_MODES_UI)
@@ -74,29 +75,23 @@
     }
 
     @Test
-    public void updateState_nameNonEmpty_buttonEnabled() {
+    public void buttonClick_nameNonEmpty_buttonSaves() {
         ZenMode mode = new TestModeBuilder().setName("Such a nice name").build();
 
         mController.updateState(mPreference, mode);
-
-        assertThat(mButton.isEnabled()).isTrue();
-        verifyNoMoreInteractions(mConfirmSave);
-    }
-
-    @Test
-    public void updateState_nameEmpty_buttonDisabled() {
-        ZenMode aModeHasNoName = new TestModeBuilder().setName("").build();
-
-        mController.updateState(mPreference, aModeHasNoName);
-
-        assertThat(mButton.isEnabled()).isFalse();
-        verifyNoMoreInteractions(mConfirmSave);
-    }
-
-    @Test
-    public void onButtonClick_callsConfirmSave() {
         mButton.performClick();
 
         verify(mConfirmSave).run();
     }
+
+    @Test
+    public void buttonClick_nameEmpty_buttonErrors() {
+        ZenMode aModeHasNoName = new TestModeBuilder().setName("").build();
+
+        mController.updateState(mPreference, aModeHasNoName);
+        mButton.performClick();
+
+        verifyNoMoreInteractions(mConfirmSave);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo("Mode name cannot be empty");
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java
index 85fd004..8a66253 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java
@@ -43,6 +43,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.UserHandle;
 import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.service.notification.ConversationChannelWrapper;
@@ -229,13 +230,13 @@
 
     private void setUpContacts(Collection<Integer> allIds, Collection<Integer> starredIds) {
         when(mHelperBackend.getAllContacts()).thenReturn(ImmutableList.copyOf(
-                allIds.stream()
-                        .map(id -> new Contact(id, "#" + id, Uri.parse("photo://" + id)))
+                allIds.stream().map(id -> new Contact(UserHandle.SYSTEM, id, "#" + id,
+                                Uri.parse("photo://" + id)))
                         .toList()));
 
         when(mHelperBackend.getStarredContacts()).thenReturn(ImmutableList.copyOf(
-                starredIds.stream()
-                        .map(id -> new Contact(id, "#" + id, Uri.parse("photo://" + id)))
+                starredIds.stream().map(id -> new Contact(UserHandle.SYSTEM, id, "#" + id,
+                                Uri.parse("photo://" + id)))
                         .toList()));
     }
 
@@ -253,6 +254,6 @@
     }
 
     private static ColorDrawable photoOf(Contact contact) {
-        return new ColorDrawable((int) contact.id());
+        return new ColorDrawable((int) contact.contactId());
     }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java
index eb57094..486a880 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModePrioritySendersPreferenceControllerTest.java
@@ -39,21 +39,41 @@
 
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
 
+import android.app.Activity;
+import android.app.Dialog;
 import android.app.Flags;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Contacts;
 import android.service.notification.ZenPolicy;
 import android.service.notification.ZenPolicy.ConversationSenders;
 import android.service.notification.ZenPolicy.PeopleType;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
 
+import androidx.fragment.app.testing.EmptyFragmentActivity;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
+import androidx.preference.PreferenceViewHolder;
 import androidx.preference.TwoStatePreference;
+import androidx.test.core.content.pm.PackageInfoBuilder;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
 
+import com.android.settings.R;
 import com.android.settingslib.notification.modes.TestModeBuilder;
 import com.android.settingslib.notification.modes.ZenMode;
 import com.android.settingslib.notification.modes.ZenModesBackend;
@@ -70,6 +90,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowDialog;
 
 import java.util.function.Consumer;
 import java.util.function.Predicate;
@@ -84,7 +105,13 @@
     @Rule
     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
+    @Rule
+    public ActivityScenarioRule<EmptyFragmentActivity> mActivityScenario =
+            new ActivityScenarioRule<>(EmptyFragmentActivity.class);
+
     private Context mContext;
+    private Activity mActivity;
+    private PackageManager mPackageManager;
     @Mock private ZenModesBackend mBackend;
     @Mock private ZenHelperBackend mHelperBackend;
 
@@ -97,6 +124,9 @@
         MockitoAnnotations.initMocks(this);
 
         mContext = RuntimeEnvironment.application;
+        mContext.setTheme(androidx.appcompat.R.style.Theme_AppCompat);
+        mActivityScenario.getScenario().onActivity(activity -> mActivity = activity);
+        mPackageManager = mContext.getPackageManager();
 
         mMessagesController = new ZenModePrioritySendersPreferenceController(mContext, "messages",
                 true, mBackend, mHelperBackend);
@@ -114,8 +144,8 @@
         mPreferenceScreen.addPreference(mMessagesPrefCategory);
 
         when(mHelperBackend.getStarredContacts()).thenReturn(ImmutableList.of());
-        when(mHelperBackend.getAllContacts()).thenReturn(
-                ImmutableList.of(new ZenHelperBackend.Contact(1, "The only contact", null)));
+        when(mHelperBackend.getAllContacts()).thenReturn(ImmutableList.of(
+                new ZenHelperBackend.Contact(UserHandle.SYSTEM, 1, "The only contact", null)));
         when(mHelperBackend.getAllContactsCount()).thenReturn(1);
 
         when(mHelperBackend.getImportantConversations()).thenReturn(ImmutableList.of());
@@ -1439,4 +1469,142 @@
         assertThat(captor.getValue().getPolicy().getPriorityCallSenders())
                 .isEqualTo(PEOPLE_TYPE_NONE);
     }
+
+    @Test
+    public void displayPreference_hasContactsApp_hasSettingsButton() {
+        String contactsPackage = mContext.getString(R.string.config_contacts_package_name);
+        setUpContactsApp(contactsPackage, /* withPreciseIntents= */ false);
+        mCallsController.displayPreference(mPreferenceScreen);
+
+        SelectorWithWidgetPreference contactsPref = getBoundSelectorPreference(KEY_STARRED);
+
+        assertThat(((View) contactsPref.getExtraWidget().getParent()).getVisibility()).isEqualTo(
+                View.VISIBLE);
+    }
+
+    @Test
+    public void displayPreference_noContactsApp_noSettingsButton() {
+        String contactsPackage = mContext.getString(R.string.config_contacts_package_name);
+        shadowOf(mPackageManager).removePackage(contactsPackage);
+        mCallsController.displayPreference(mPreferenceScreen);
+
+        SelectorWithWidgetPreference contactsPref = getBoundSelectorPreference(KEY_STARRED);
+
+        assertThat(((View) contactsPref.getExtraWidget().getParent()).getVisibility()).isEqualTo(
+                View.GONE);
+    }
+
+    @Test
+    public void contactsSettingsClick_usesBestIntent() {
+        String contactsPackage = mContext.getString(R.string.config_contacts_package_name);
+        setUpContactsApp(contactsPackage, /* withPreciseIntents= */ true);
+
+        mCallsController.displayPreference(mPreferenceScreen);
+        mCallsController.updateZenMode(mCallsPrefCategory, TestModeBuilder.EXAMPLE);
+
+        SelectorWithWidgetPreference contactsPref = getBoundSelectorPreference(KEY_CONTACTS);
+        contactsPref.getExtraWidget().performClick();
+
+        Intent nextActivity = shadowOf(mActivity).getNextStartedActivity();
+        assertThat(nextActivity).isNotNull();
+        assertThat(nextActivity.getPackage()).isEqualTo(contactsPackage);
+        assertThat(nextActivity.getAction()).isEqualTo(Contacts.Intents.UI.LIST_DEFAULT);
+    }
+
+    @Test
+    public void starredContactsSettingsClick_usesBestIntent() {
+        String contactsPackage = mContext.getString(R.string.config_contacts_package_name);
+        setUpContactsApp(contactsPackage, /* withPreciseIntents= */  true);
+
+        mCallsController.displayPreference(mPreferenceScreen);
+        mCallsController.updateZenMode(mCallsPrefCategory, TestModeBuilder.EXAMPLE);
+        SelectorWithWidgetPreference contactsPref = getBoundSelectorPreference(KEY_STARRED);
+
+        contactsPref.getExtraWidget().performClick();
+
+        Intent nextActivity = shadowOf(mActivity).getNextStartedActivity();
+        assertThat(nextActivity).isNotNull();
+        assertThat(nextActivity.getPackage()).isEqualTo(contactsPackage);
+        assertThat(nextActivity.getAction()).isEqualTo(Contacts.Intents.UI.LIST_STARRED_ACTION);
+    }
+
+    @Test
+    public void contactsSettingsClick_usesFallbackIntent() {
+        String contactsPackage = mContext.getString(R.string.config_contacts_package_name);
+        setUpContactsApp(contactsPackage, /* withPreciseIntents= */ false);
+
+        mCallsController.displayPreference(mPreferenceScreen);
+        mCallsController.updateZenMode(mCallsPrefCategory, TestModeBuilder.EXAMPLE);
+        SelectorWithWidgetPreference contactsPref = getBoundSelectorPreference(KEY_CONTACTS);
+
+        contactsPref.getExtraWidget().performClick();
+
+        Intent nextActivity = shadowOf(mActivity).getNextStartedActivity();
+        assertThat(nextActivity).isNotNull();
+        assertThat(nextActivity.getPackage()).isEqualTo(contactsPackage);
+        assertThat(nextActivity.getAction()).isEqualTo(Intent.ACTION_MAIN);
+    }
+
+    @Test
+    public void contactsSettingsClick_multipleProfiles_showsProfileChooserDialog() {
+        String contactsPackage = mContext.getString(R.string.config_contacts_package_name);
+        setUpContactsApp(contactsPackage, /* withPreciseIntents= */ true);
+
+        UserInfo workProfile = new UserInfo(mContext.getUserId() + 10, "Work Profile", 0);
+        workProfile.userType = UserManager.USER_TYPE_PROFILE_MANAGED;
+        UserManager userManager = mContext.getSystemService(UserManager.class);
+        shadowOf(userManager).addProfile(mContext.getUserId(), workProfile.id, workProfile);
+
+        mCallsController.displayPreference(mPreferenceScreen);
+        mCallsController.updateZenMode(mCallsPrefCategory, TestModeBuilder.EXAMPLE);
+        SelectorWithWidgetPreference contactsPref = getBoundSelectorPreference(KEY_CONTACTS);
+
+        contactsPref.getExtraWidget().performClick();
+
+        Dialog profileSelectDialog = ShadowDialog.getLatestDialog();
+        assertThat(profileSelectDialog).isNotNull();
+        TextView dialogTitle = profileSelectDialog.findViewById(android.R.id.title);
+        assertThat(dialogTitle.getText().toString()).isEqualTo("Choose profile");
+    }
+
+    private void setUpContactsApp(String contactsPackage, boolean withPreciseIntents) {
+        ComponentName contactsActivity = new ComponentName(contactsPackage, "ContactsActivity");
+        shadowOf(mPackageManager).installPackage(
+                PackageInfoBuilder.newBuilder()
+                        .setPackageName(contactsPackage)
+                        .build());
+        shadowOf(mPackageManager).addActivityIfNotPresent(contactsActivity);
+
+        // Fallback / default intent filter.
+        IntentFilter mainFilter = new IntentFilter(Intent.ACTION_MAIN);
+        mainFilter.addCategory(Intent.CATEGORY_DEFAULT);
+        mainFilter.addCategory(Intent.CATEGORY_APP_CONTACTS);
+        shadowOf(mPackageManager).addIntentFilterForActivity(contactsActivity, mainFilter);
+
+        if (withPreciseIntents) {
+            IntentFilter listFilter = new IntentFilter(Contacts.Intents.UI.LIST_DEFAULT);
+            listFilter.addCategory(Intent.CATEGORY_DEFAULT);
+            shadowOf(mPackageManager).addIntentFilterForActivity(contactsActivity, listFilter);
+
+            IntentFilter starredFilter = new IntentFilter(Contacts.Intents.UI.LIST_STARRED_ACTION);
+            starredFilter.addCategory(Intent.CATEGORY_DEFAULT);
+            shadowOf(mPackageManager).addIntentFilterForActivity(contactsActivity, starredFilter);
+        }
+    }
+
+    private SelectorWithWidgetPreference getBoundSelectorPreference(String key) {
+        SelectorWithWidgetPreference selectorPref = checkNotNull(
+                mCallsPrefCategory.findPreference(key));
+
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        View view = inflater.inflate(selectorPref.getLayoutResource(), null);
+        LinearLayout widgetView = view.findViewById(android.R.id.widget_frame);
+        assertThat(widgetView).isNotNull();
+        inflater.inflate(selectorPref.getWidgetLayoutResource(), widgetView, true);
+
+        PreferenceViewHolder viewHolder = PreferenceViewHolder.createInstanceForTests(view);
+        selectorPref.onBindViewHolder(viewHolder);
+
+        return selectorPref;
+    }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java
index d5c7f61..c378e9d 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java
@@ -32,10 +32,10 @@
 import android.view.ViewGroup;
 import android.widget.ToggleButton;
 
-import androidx.fragment.app.Fragment;
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.notification.modes.TestModeBuilder;
 import com.android.settingslib.notification.modes.ZenMode;
 import com.android.settingslib.notification.modes.ZenModesBackend;
@@ -60,7 +60,7 @@
     private Context mContext;
 
     @Mock
-    private Fragment mParent;
+    private DashboardFragment mParent;
     @Mock
     private Calendar mCalendar;
     @Mock
diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
index 69f1886..1cf365e 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
@@ -120,7 +120,6 @@
         assertThat(fakeSlice.getSummary()).isEqualTo(FAKE_SUMMARY);
         assertThat(fakeSlice.getScreenTitle()).isEqualTo(FAKE_SCREEN_TITLE);
         assertThat(fakeSlice.getKeywords()).isNull();
-        assertThat(fakeSlice.getIconResource()).isNotNull();
         assertThat(fakeSlice.getUri().toString())
                 .isEqualTo("content://com.android.settings.slices/action/key");
         assertThat(fakeSlice.getFragmentClassName()).isEqualTo(FAKE_FRAGMENT_CLASSNAME);