Merge "[Audiosharing] Handle add source from notif in receiver" into main
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ba0c998..9ded9ad 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -10798,7 +10798,7 @@
     <string name="apps_summary"><xliff:g id="count" example="24">%1$d</xliff:g> apps installed</string>
 
     <!-- Summary of storage usage [CHAR LIMIT=NONE] -->
-    <string name="storage_summary"><xliff:g id="percentage" example="54%">%1$s</xliff:g> used - <xliff:g id="free_space" example="32GB">%2$s</xliff:g> free</string>
+    <string name="storage_summary"><xliff:g id="percentage" example="54%">%1$s</xliff:g> used - <xliff:g id="free_space_value" example="32">%2$s</xliff:g> <xliff:g id="free_space_units" example="GB">%3$s</xliff:g> free</string>
 
     <!-- Summary for Display settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
     <string name="display_dashboard_summary">Dark theme, font size, brightness</string>
diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java b/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java
index 86f0314..f0bed94 100644
--- a/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java
+++ b/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java
@@ -46,7 +46,6 @@
 import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.HearingAidStatsLogUtils;
-import com.android.settingslib.flags.Flags;
 import com.android.settingslib.utils.ThreadUtils;
 
 import com.google.common.collect.ImmutableList;
@@ -63,7 +62,6 @@
 public abstract class BluetoothDevicePairingDetailBase extends DeviceListPreferenceFragment {
     private static final long AUTO_DISMISS_TIME_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(15);
     private static final int AUTO_DISMISS_MESSAGE_ID = 1001;
-    private static final int AUTO_FINISH_MESSAGE_ID = 1002;
     private static final ImmutableList<Integer> AUDIO_SHARING_PROFILES = ImmutableList.of(
             BluetoothProfile.LE_AUDIO,
             BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, BluetoothProfile.VOLUME_CONTROL);
@@ -91,8 +89,8 @@
     // onDeviceBondStateChanged(BOND_BONDED), BluetoothDevicePreference's summary has already
     // change from "Pairing..." to empty since it listens to metadata changes happens earlier.
     //
-    // In pairing flow during audio sharing, we have to wait on this page till the device is
-    // connected to check the device type and handle extra logic for audio sharing.
+    // In share then pair flow, we have to wait on this page till the device is connected to check
+    // the device type and handle extra logic for audio sharing.
     // The BluetoothDevicePreference summary will be blank for seconds between "Pairing..." and
     // "Connecting..." To help users better understand the process, we listen to metadata change
     // as well and show a progress dialog with "Connecting to ...." once BluetoothDevice.getState()
@@ -103,11 +101,10 @@
                 public void onMetadataChanged(@NonNull BluetoothDevice device, int key,
                         @Nullable byte[] value) {
                     Log.d(getLogTag(), "onMetadataChanged device = " + device + ", key  = " + key);
-                    if ((mShouldTriggerShareThenPairFlow || shouldSetTempBondMetadata())
-                            && mProgressDialog == null
+                    if (mShouldTriggerShareThenPairFlow && mProgressDialog == null
                             && device.getBondState() == BluetoothDevice.BOND_BONDED
                             && mSelectedList.contains(device)) {
-                        handleDeviceBondedInAudioSharing(device);
+                        handleShareThenPair(device);
                         // Once device is bonded, remove the listener
                         removeOnMetadataChangedListener(device);
                     }
@@ -181,12 +178,11 @@
 
     @Override
     public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
-        boolean shouldSetTempBond = shouldSetTempBondMetadata();
         if (bondState == BluetoothDevice.BOND_BONDED) {
-            if (cachedDevice != null && (mShouldTriggerShareThenPairFlow || shouldSetTempBond)) {
+            if (cachedDevice != null && mShouldTriggerShareThenPairFlow) {
                 BluetoothDevice device = cachedDevice.getDevice();
                 if (device != null && mSelectedList.contains(device)) {
-                    handleDeviceBondedInAudioSharing(device);
+                    handleShareThenPair(device);
                     removeOnMetadataChangedListener(device);
                     return;
                 }
@@ -195,7 +191,7 @@
             finish();
             return;
         } else if (bondState == BluetoothDevice.BOND_BONDING) {
-            if ((mShouldTriggerShareThenPairFlow || shouldSetTempBond) && cachedDevice != null) {
+            if (mShouldTriggerShareThenPairFlow && cachedDevice != null) {
                 BluetoothDevice device = cachedDevice.getDevice();
                 if (device != null && mSelectedList.contains(device)) {
                     addOnMetadataChangedListener(device);
@@ -208,7 +204,7 @@
                     pageId);
             HearingAidStatsLogUtils.setBondEntryForDevice(bondEntry, cachedDevice);
         } else if (bondState == BluetoothDevice.BOND_NONE) {
-            if ((mShouldTriggerShareThenPairFlow || shouldSetTempBond) && cachedDevice != null) {
+            if (mShouldTriggerShareThenPairFlow && cachedDevice != null) {
                 BluetoothDevice device = cachedDevice.getDevice();
                 if (device != null && mSelectedList.contains(device)) {
                     removeOnMetadataChangedListener(device);
@@ -240,22 +236,15 @@
                     && mSelectedList.contains(device)) {
                 var unused = ThreadUtils.postOnBackgroundThread(() -> {
                     if (BluetoothUtils.isAudioSharingUIAvailable(getContext())) {
-                        if ((mShouldTriggerShareThenPairFlow || shouldSetTempBondMetadata())
+                        if (mShouldTriggerShareThenPairFlow
                                 && state == BluetoothAdapter.STATE_CONNECTED
                                 && device.equals(mJustBonded)
                                 && AUDIO_SHARING_PROFILES.contains(bluetoothProfile)
                                 && isReadyForAudioSharing(cachedDevice, bluetoothProfile)) {
                             Log.d(getLogTag(), "onProfileConnectionStateChanged, lea eligible");
                             dismissConnectingDialog();
-                            BluetoothUtils.setTemporaryBondMetadata(device);
-                            if (mShouldTriggerShareThenPairFlow) {
-                                mHandler.removeMessages(AUTO_DISMISS_MESSAGE_ID);
-                                postOnMainThread(() ->
-                                        finishFragmentWithResultForAudioSharing(device));
-                            } else {
-                                mHandler.removeMessages(AUTO_FINISH_MESSAGE_ID);
-                                postOnMainThread(() -> finish());
-                            }
+                            mHandler.removeMessages(AUTO_DISMISS_MESSAGE_ID);
+                            postOnMainThread(() -> finishFragmentWithResultForAudioSharing(device));
                         }
                     } else {
                         postOnMainThread(() -> finish());
@@ -341,16 +330,6 @@
         return false;
     }
 
-    private boolean shouldSetTempBondMetadata() {
-        return Flags.enableTemporaryBondDevicesUi()
-                && BluetoothUtils.isAudioSharingUIAvailable(getContext())
-                && BluetoothUtils.isBroadcasting(mLocalManager)
-                && mLocalManager != null
-                && mLocalManager.getCachedDeviceManager() != null
-                && mLocalManager.getProfileManager().getLeAudioBroadcastAssistantProfile() != null
-                && !Utils.shouldBlockPairingInAudioSharing(mLocalManager);
-    }
-
     private boolean isReadyForAudioSharing(@NonNull CachedBluetoothDevice cachedDevice,
             int justConnectedProfile) {
         for (int profile : AUDIO_SHARING_PROFILES) {
@@ -405,10 +384,10 @@
         });
     }
 
-    private void handleDeviceBondedInAudioSharing(@Nullable BluetoothDevice device) {
+    private void handleShareThenPair(@Nullable BluetoothDevice device) {
         var unused = ThreadUtils.postOnBackgroundThread(() -> {
             if (mJustBonded != null) {
-                Log.d(getLogTag(), "Skip handleDeviceBondedInAudioSharing, already done");
+                Log.d(getLogTag(), "Skip handleShareThenPair, already done");
                 return;
             }
             mJustBonded = device;
@@ -417,38 +396,21 @@
             String deviceName = TextUtils.isEmpty(aliasName) ? device.getAddress()
                     : aliasName;
             showConnectingDialog(deviceName);
-            if (mShouldTriggerShareThenPairFlow) {
-                // For share then pair flow, we have strong signal that users wish to pair new
-                // device to join sharing.
-                // So we wait for AUTO_DISMISS_TIME_THRESHOLD_MS, if we find that the bonded device
-                // is lea in onProfileConnectionStateChanged, we finish the activity, set the device
-                // as temp bond and auto add source; otherwise, show dialog to notify that the
-                // device is incompatible for audio sharing.
-                if (!mHandler.hasMessages(AUTO_DISMISS_MESSAGE_ID)) {
-                    mHandler.postDelayed(() ->
-                            postOnMainThread(
-                                    () -> {
-                                        Log.d(getLogTag(),
-                                                "Show incompatible dialog when timeout");
-                                        dismissConnectingDialog();
-                                        AudioSharingIncompatibleDialogFragment.show(this,
-                                                deviceName,
-                                                () -> finish());
-                                    }), AUTO_DISMISS_MESSAGE_ID, AUTO_DISMISS_TIME_THRESHOLD_MS);
-                }
-            } else {
-                // For other pairing request during audio sharing with sinks < 2, we wait for
-                // AUTO_DISMISS_TIME_THRESHOLD_MS, if we find that the bonded device is lea in
-                // onProfileConnectionStateChanged, we finish the activity and set the device as
-                // temp bond; otherwise, we just finish the activity.
-                if (!mHandler.hasMessages(AUTO_FINISH_MESSAGE_ID)) {
-                    mHandler.postDelayed(() ->
-                            postOnMainThread(
-                                    () -> {
-                                        Log.d(getLogTag(), "Finish activity when timeout");
-                                        finish();
-                                    }), AUTO_FINISH_MESSAGE_ID, AUTO_DISMISS_TIME_THRESHOLD_MS);
-                }
+            // For share then pair flow, we have strong signal that users wish to pair new
+            // device to join sharing.
+            // So we wait for AUTO_DISMISS_TIME_THRESHOLD_MS, if we find that the bonded device
+            // is lea in onProfileConnectionStateChanged, we finish the activity, set the device
+            // as temp bond and auto add source; otherwise, show dialog to notify that the
+            // device is incompatible for audio sharing.
+            if (!mHandler.hasMessages(AUTO_DISMISS_MESSAGE_ID)) {
+                mHandler.postDelayed(() ->
+                        postOnMainThread(
+                                () -> {
+                                    Log.d(getLogTag(), "Show incompatible dialog when timeout");
+                                    dismissConnectingDialog();
+                                    AudioSharingIncompatibleDialogFragment.show(this, deviceName,
+                                            () -> finish());
+                                }), AUTO_DISMISS_MESSAGE_ID, AUTO_DISMISS_TIME_THRESHOLD_MS);
             }
         });
     }
diff --git a/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java b/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java
index 1955f36..785d84a 100644
--- a/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java
+++ b/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java
@@ -92,9 +92,10 @@
 
     private String getSummary(long usedBytes, long totalBytes) {
         NumberFormat percentageFormat = NumberFormat.getPercentInstance();
-
+        final String[] freeSpace =
+                Formatter.formatFileSize(mContext, totalBytes - usedBytes).split(" ");
         return mContext.getString(R.string.storage_summary,
                 totalBytes == 0L ? "0" : percentageFormat.format(((double) usedBytes) / totalBytes),
-                Formatter.formatFileSize(mContext, totalBytes - usedBytes));
+                freeSpace[0], freeSpace[1]);
     }
 }
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt b/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
index f765d8c..54331aa 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
+++ b/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
@@ -64,8 +64,12 @@
      * Also check [getIsAvailableAndUpdateEid] for other availability check which retrieved
      * asynchronously later.
      */
-    override fun getAvailabilityStatus() =
-        if (SubscriptionUtil.isSimHardwareVisible(mContext)) AVAILABLE else UNSUPPORTED_ON_DEVICE
+    override fun getAvailabilityStatus() = when {
+        !SubscriptionUtil.isSimHardwareVisible(mContext)
+            || Utils.isWifiOnly(mContext) -> UNSUPPORTED_ON_DEVICE
+        !mContext.userManager.isAdminUser -> DISABLED_FOR_USER
+        else -> AVAILABLE
+    }
 
     override fun displayPreference(screen: PreferenceScreen) {
         super.displayPreference(screen)
@@ -98,7 +102,6 @@
     }
 
     private fun getIsAvailableAndUpdateEid(): Boolean {
-        if (!mContext.userManager.isAdminUser || Utils.isWifiOnly(mContext)) return false
         eid = eidStatus?.eid ?: ""
         return eid.isNotEmpty()
     }
diff --git a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
index 22e3431..121bd82 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
@@ -64,7 +64,9 @@
 
         // Generate Low storage Slice.
         final String percentageString = NumberFormat.getPercentInstance().format(usedPercentage);
-        final String freeSizeString = Formatter.formatFileSize(mContext, info.freeBytes);
+        final String[] freeSizeString =
+                Formatter.formatFileSize(mContext, info.freeBytes).split(" ");
+
         final ListBuilder listBuilder = new ListBuilder(mContext,
                 CustomSliceRegistry.LOW_STORAGE_SLICE_URI, ListBuilder.INFINITY).setAccentColor(
                 Utils.getColorAccentDefaultColor(mContext));
@@ -74,7 +76,7 @@
             // For clients that ignore error checking, a generic storage slice will be given.
             final CharSequence titleStorage = mContext.getText(R.string.storage_settings);
             final String summaryStorage = mContext.getString(R.string.storage_summary,
-                    percentageString, freeSizeString);
+                    percentageString, freeSizeString[0], freeSizeString[1]);
 
             return listBuilder
                     .addRow(buildRowBuilder(titleStorage, summaryStorage, icon))
diff --git a/src/com/android/settings/notification/modes/ConfigurationActivityHelper.java b/src/com/android/settings/notification/modes/ConfigurationActivityHelper.java
index d001651..ad76802 100644
--- a/src/com/android/settings/notification/modes/ConfigurationActivityHelper.java
+++ b/src/com/android/settings/notification/modes/ConfigurationActivityHelper.java
@@ -48,21 +48,22 @@
     Intent getConfigurationActivityIntentForMode(ZenMode zenMode,
             Function<ComponentName, ComponentInfo> approvedServiceFinder) {
 
-        String owner = zenMode.getRule().getPackageName();
+        ZenMode.Owner owner = zenMode.getOwner();
         ComponentName configActivity = null;
-        if (zenMode.getRule().getConfigurationActivity() != null) {
+        if (owner.configurationActivity() != null) {
             // If a configuration activity is present, use that directly in the intent
-            configActivity = zenMode.getRule().getConfigurationActivity();
+            configActivity = owner.configurationActivity();
         } else {
             // Otherwise, look for a condition provider service for the rule's package
-            ComponentInfo ci = approvedServiceFinder.apply(zenMode.getRule().getOwner());
+            ComponentInfo ci = approvedServiceFinder.apply(owner.conditionProvider());
             if (ci != null) {
                 configActivity = extractConfigurationActivityFromComponent(ci);
             }
         }
 
         if (configActivity != null
-                && (owner == null || isSameOwnerPackage(owner, configActivity))
+                && (owner.packageName() == null
+                    || isSameOwnerPackage(owner.packageName(), configActivity))
                 && isResolvableActivity(configActivity)) {
             return new Intent()
                     .setComponent(configActivity)
diff --git a/src/com/android/settings/notification/modes/ZenModeButtonPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeButtonPreferenceController.java
index 72ff524..dbbc486 100644
--- a/src/com/android/settings/notification/modes/ZenModeButtonPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeButtonPreferenceController.java
@@ -51,7 +51,7 @@
     @Override
     public boolean isAvailable(ZenMode zenMode) {
         return zenMode.isEnabled()
-                && (zenMode.isActive() || zenMode.getRule().isManualInvocationAllowed());
+                && (zenMode.isActive() || zenMode.isManualInvocationAllowed());
     }
 
     @Override
diff --git a/src/com/android/settings/notification/modes/ZenModeEditNameIconFragment.java b/src/com/android/settings/notification/modes/ZenModeEditNameIconFragment.java
index 60f7316..f043298 100644
--- a/src/com/android/settings/notification/modes/ZenModeEditNameIconFragment.java
+++ b/src/com/android/settings/notification/modes/ZenModeEditNameIconFragment.java
@@ -54,8 +54,8 @@
             return;
         }
 
-        modeToUpdate.getRule().setName(mode.getRule().getName());
-        modeToUpdate.getRule().setIconResId(mode.getRule().getIconResId());
+        modeToUpdate.setName(mode.getName());
+        modeToUpdate.setIconResId(mode.getIconResId());
         requireBackend().updateMode(modeToUpdate);
         finish();
     }
diff --git a/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentBase.java b/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentBase.java
index 6dd9076..20a30f7 100644
--- a/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentBase.java
+++ b/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentBase.java
@@ -128,13 +128,13 @@
 
     @VisibleForTesting
     final void setModeName(String name) {
-        checkNotNull(mZenMode).getRule().setName(Strings.nullToEmpty(name));
+        checkNotNull(mZenMode).setName(Strings.nullToEmpty(name));
         forceUpdatePreferences(); // Updates confirmation button.
     }
 
     @VisibleForTesting
     final void setModeIcon(@DrawableRes int iconResId) {
-        checkNotNull(mZenMode).getRule().setIconResId(iconResId);
+        checkNotNull(mZenMode).setIconResId(iconResId);
         forceUpdatePreferences();  // Updates icon at the top.
     }
 
diff --git a/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceController.java
index 18e3fc1..7bf2e88 100644
--- a/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceController.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.notification.modes;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import android.content.Context;
 import android.service.notification.ZenModeConfig;
 
@@ -24,6 +26,7 @@
 import androidx.preference.TwoStatePreference;
 
 import com.android.settingslib.notification.modes.ZenMode;
+import com.android.settingslib.notification.modes.ZenModeSchedules;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 
 /**
@@ -40,7 +43,7 @@
 
     @Override
     public void updateState(Preference preference, @NonNull ZenMode zenMode) {
-        mSchedule = ZenModeConfig.tryParseScheduleConditionId(zenMode.getRule().getConditionId());
+        mSchedule = checkNotNull(ZenModeSchedules.getTimeSchedule(zenMode));
         ((TwoStatePreference) preference).setChecked(mSchedule.exitAtAlarm);
     }
 
diff --git a/src/com/android/settings/notification/modes/ZenModeNewCustomFragment.java b/src/com/android/settings/notification/modes/ZenModeNewCustomFragment.java
index d7dbaaf..8ff23e7 100644
--- a/src/com/android/settings/notification/modes/ZenModeNewCustomFragment.java
+++ b/src/com/android/settings/notification/modes/ZenModeNewCustomFragment.java
@@ -47,8 +47,7 @@
                 ? requireContext().getString(R.string.zen_mode_new_custom_default_name)
                 : mode.getName();
 
-        ZenMode created = requireBackend().addCustomManualMode(modeName,
-                mode.getRule().getIconResId());
+        ZenMode created = requireBackend().addCustomManualMode(modeName, mode.getIconResId());
         if (created != null) {
             // Open the mode view fragment and close the "add mode" fragment, so exiting the mode
             // view goes back to previous screen (which should be the modes list).
diff --git a/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceController.java
index 4f45c5c8..6788236 100644
--- a/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceController.java
@@ -32,6 +32,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settingslib.notification.modes.ZenMode;
+import com.android.settingslib.notification.modes.ZenModeSchedules;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 
 import java.util.ArrayList;
@@ -85,7 +86,7 @@
         mReply.setOnPreferenceChangeListener(mReplyChangeListener);
 
         // Parse the zen mode's condition to update our EventInfo object.
-        mEvent = ZenModeConfig.tryParseEventConditionId(zenMode.getRule().getConditionId());
+        mEvent = ZenModeSchedules.getCalendarSchedule(zenMode);
         if (mEvent != null) {
             reloadCalendar();
             updatePrefValues();
diff --git a/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceController.java b/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceController.java
index 651b7cc..d5e6a75 100644
--- a/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceController.java
@@ -32,6 +32,7 @@
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.notification.modes.ZenMode;
+import com.android.settingslib.notification.modes.ZenModeSchedules;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 import com.android.settingslib.widget.LayoutPreference;
 
@@ -62,7 +63,7 @@
 
     @Override
     public void updateState(Preference preference, @NonNull ZenMode zenMode) {
-        mSchedule = ZenModeConfig.tryParseScheduleConditionId(zenMode.getRule().getConditionId());
+        mSchedule = ZenModeSchedules.getTimeSchedule(zenMode);
         LayoutPreference layoutPref = (LayoutPreference) preference;
 
         TextView start = layoutPref.findViewById(R.id.start_time);
diff --git a/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java b/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java
index bbed5b9..a0e5b50 100644
--- a/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java
@@ -20,7 +20,6 @@
 import static android.app.AutomaticZenRule.TYPE_DRIVING;
 import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR;
 import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
-import static android.service.notification.ZenModeConfig.tryParseScheduleConditionId;
 
 import android.annotation.SuppressLint;
 import android.app.AlertDialog;
@@ -43,6 +42,7 @@
 import com.android.settings.Utils;
 import com.android.settingslib.PrimarySwitchPreference;
 import com.android.settingslib.notification.modes.ZenMode;
+import com.android.settingslib.notification.modes.ZenModeSchedules;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 
 import com.google.common.base.Strings;
@@ -105,8 +105,7 @@
 
             // [Clock Icon] 9:00 - 17:00 / Sun-Mon
             preference.setIcon(com.android.internal.R.drawable.ic_zen_mode_type_schedule_time);
-            ZenModeConfig.ScheduleInfo schedule =
-                    tryParseScheduleConditionId(mode.getRule().getConditionId());
+            ZenModeConfig.ScheduleInfo schedule = ZenModeSchedules.getTimeSchedule(mode);
             if (schedule != null) {
                 preference.setTitle(SystemZenRules.getTimeSummary(mContext, schedule));
                 String shortDaysSummary = SystemZenRules.getDaysOfWeekShort(mContext, schedule);
@@ -138,7 +137,7 @@
     @SuppressLint("SwitchIntDef")
     private void setUpForAppTrigger(Preference preference, ZenMode mode) {
         // App-owned mode may have triggerDescription, configurationActivity, or both/neither.
-        mServiceListing.loadApprovedComponents(mode.getRule().getPackageName());
+        mServiceListing.loadApprovedComponents(mode.getOwnerPackage());
         Intent configurationIntent =
                 mConfigurationActivityHelper.getConfigurationActivityIntentForMode(
                         mode, mServiceListing::findService);
@@ -152,11 +151,11 @@
         String summary;
         if (!Strings.isNullOrEmpty(mode.getTriggerDescription())) {
             summary = mode.getTriggerDescription();
-        } else if (!Strings.isNullOrEmpty(mode.getRule().getPackageName())) {
+        } else if (!Strings.isNullOrEmpty(mode.getOwnerPackage())) {
             String appName = null;
             try {
                 ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
-                        mode.getRule().getPackageName(), 0);
+                        mode.getOwnerPackage(), 0);
                 appName = appInfo.loadLabel(mPackageManager).toString();
             } catch (PackageManager.NameNotFoundException e) {
                 Log.e(TAG, "Couldn't resolve owner for mode: " + mode);
@@ -219,7 +218,7 @@
     private void setModeEnabled(boolean enabled) {
         saveMode((zenMode) -> {
             if (enabled != zenMode.isEnabled()) {
-                zenMode.getRule().setEnabled(enabled);
+                zenMode.setEnabled(enabled);
             }
             return zenMode;
         });
diff --git a/src/com/android/settings/notification/modes/ZenModesListFragment.java b/src/com/android/settings/notification/modes/ZenModesListFragment.java
index 00f652d..76a4366 100644
--- a/src/com/android/settings/notification/modes/ZenModesListFragment.java
+++ b/src/com/android/settings/notification/modes/ZenModesListFragment.java
@@ -125,7 +125,7 @@
         // If we find a new mode owned by the same package, presumably that's it. Open its page.
         Optional<ZenMode> createdZenMode = mBackend.getModes().stream()
                 .filter(m -> !previousIds.contains(m.getId()))
-                .filter(m -> m.getRule().getPackageName().equals(activityInvoked.getPackageName()))
+                .filter(m -> activityInvoked.getPackageName().equals(m.getOwnerPackage()))
                 .findFirst();
         createdZenMode.ifPresent(
                 mode ->
diff --git a/src/com/android/settings/wifi/calling/OWNERS b/src/com/android/settings/wifi/calling/OWNERS
index 87e5fcc..fc903a3 100644
--- a/src/com/android/settings/wifi/calling/OWNERS
+++ b/src/com/android/settings/wifi/calling/OWNERS
@@ -1,7 +1,6 @@
 # Default reviewers for this and subdirectories.
 allenwtsu@google.com
 andychou@google.com
-bonianchen@google.com
 leechou@google.com
 songferngwang@google.com
 tomhsu@google.com
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java
index 38a607a..78c771c 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java
@@ -18,7 +18,6 @@
 
 import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.EXTRA_BT_DEVICE_TO_AUTO_ADD_SOURCE;
 import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.EXTRA_PAIR_AND_JOIN_SHARING;
-import static com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -37,7 +36,6 @@
 import android.app.Activity;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothLeBroadcastReceiveState;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothStatusCodes;
 import android.content.Context;
@@ -66,15 +64,9 @@
 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
 import com.android.settings.testutils.shadow.ShadowFragment;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
-import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
-import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
-import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 import com.android.settingslib.flags.Flags;
 
-import com.google.common.collect.ImmutableList;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -122,14 +114,6 @@
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private LocalBluetoothManager mLocalManager;
     @Mock
-    private CachedBluetoothDeviceManager mDeviceManager;
-    @Mock
-    private LocalBluetoothProfileManager mProfileManager;
-    @Mock
-    private LocalBluetoothLeBroadcast mBroadcast;
-    @Mock
-    private LocalBluetoothLeBroadcastAssistant mAssistant;
-    @Mock
     private CachedBluetoothDevice mCachedBluetoothDevice;
     @Mock
     private Drawable mDrawable;
@@ -221,7 +205,6 @@
         when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
         mFragment.mSelectedList.add(mBluetoothDevice);
         setUpFragmentWithShareThenPairIntent(false);
-        setUpAudioSharingStates(/* enabled = */ false, /* needSetTempBondMetadata = */ false);
         mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED);
 
         verify(mFragment).finish();
@@ -236,31 +219,6 @@
         when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
         mFragment.mSelectedList.add(mBluetoothDevice);
         setUpFragmentWithShareThenPairIntent(true);
-        setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false);
-        mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED);
-        shadowOf(Looper.getMainLooper()).idle();
-
-        ProgressDialogFragment progressDialog = mFragment.mProgressDialog;
-        assertThat(progressDialog).isNotNull();
-        assertThat(progressDialog.getMessage()).isEqualTo(
-                mContext.getString(R.string.progress_dialog_connect_device_content,
-                        TEST_DEVICE_ADDRESS));
-        assertThat(
-                ShadowDialogFragment.isIsShowing(ProgressDialogFragment.class.getName())).isTrue();
-        verify(mFragment, never()).finish();
-
-        ShadowDialogFragment.reset();
-    }
-
-    @Test
-    @Config(shadows = ShadowDialogFragment.class)
-    @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
-    public void onDeviceBondStateChanged_bonded_pairAfterShare_handle() {
-        ShadowDialogFragment.reset();
-        when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
-        mFragment.mSelectedList.add(mBluetoothDevice);
-        setUpFragmentWithShareThenPairIntent(false);
-        setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true);
         mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED);
         shadowOf(Looper.getMainLooper()).idle();
 
@@ -283,7 +241,6 @@
         when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
         mFragment.mSelectedList.add(mBluetoothDevice);
         setUpFragmentWithShareThenPairIntent(false);
-        setUpAudioSharingStates(/* enabled = */ false, /* needSetTempBondMetadata = */ false);
         mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
 
         verify(mBluetoothAdapter, never()).addOnMetadataChangedListener(any(BluetoothDevice.class),
@@ -297,21 +254,6 @@
         when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
         mFragment.mSelectedList.add(mBluetoothDevice);
         setUpFragmentWithShareThenPairIntent(true);
-        setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false);
-        mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
-
-        verify(mBluetoothAdapter).addOnMetadataChangedListener(eq(mBluetoothDevice),
-                any(Executor.class),
-                any(BluetoothAdapter.OnMetadataChangedListener.class));
-    }
-
-    @Test
-    @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
-    public void onDeviceBondStateChanged_bonding_pairAfterShare_addListener() {
-        when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
-        mFragment.mSelectedList.add(mBluetoothDevice);
-        setUpFragmentWithShareThenPairIntent(false);
-        setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true);
         mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
 
         verify(mBluetoothAdapter).addOnMetadataChangedListener(eq(mBluetoothDevice),
@@ -337,21 +279,6 @@
         when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
         mFragment.mSelectedList.add(mBluetoothDevice);
         setUpFragmentWithShareThenPairIntent(true);
-        setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false);
-        mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
-        mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_NONE);
-
-        verify(mBluetoothAdapter).removeOnMetadataChangedListener(eq(mBluetoothDevice),
-                any(BluetoothAdapter.OnMetadataChangedListener.class));
-    }
-
-    @Test
-    @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
-    public void onDeviceBondStateChanged_unbonded_pairAfterShare_removeListener() {
-        when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
-        mFragment.mSelectedList.add(mBluetoothDevice);
-        setUpFragmentWithShareThenPairIntent(false);
-        setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true);
         mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDING);
         mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_NONE);
 
@@ -387,7 +314,6 @@
         when(mCachedBluetoothDevice.getDevice()).thenReturn(device);
         mFragment.mSelectedList.add(device);
         setUpFragmentWithShareThenPairIntent(true);
-        setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ false);
         mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED);
         shadowOf(Looper.getMainLooper()).idle();
 
@@ -400,7 +326,6 @@
                 BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
         shadowOf(Looper.getMainLooper()).idle();
 
-        verify(device).setMetadata(eq(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS), any());
         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
         verify(mFragment.getActivity()).setResult(eq(Activity.RESULT_OK), captor.capture());
         Intent intent = captor.getValue();
@@ -417,35 +342,6 @@
     }
 
     @Test
-    @Config(shadows = ShadowDialogFragment.class)
-    @EnableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
-    public void
-            onProfileConnectionStateChanged_inSelectedListAndConnected_pairAfterShare_handle() {
-        ShadowDialogFragment.reset();
-        BluetoothDevice device = spy(mBluetoothDevice);
-        when(mCachedBluetoothDevice.getDevice()).thenReturn(device);
-        mFragment.mSelectedList.add(device);
-        setUpFragmentWithShareThenPairIntent(false);
-        setUpAudioSharingStates(/* enabled = */ true, /* needSetTempBondMetadata = */ true);
-        mFragment.onDeviceBondStateChanged(mCachedBluetoothDevice, BluetoothDevice.BOND_BONDED);
-        shadowOf(Looper.getMainLooper()).idle();
-
-        when(mCachedBluetoothDevice.isConnected()).thenReturn(true);
-        when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
-        when(mCachedBluetoothDevice.isConnectedLeAudioBroadcastAssistantDevice()).thenReturn(true);
-        when(mCachedBluetoothDevice.isConnectedVolumeControlDevice()).thenReturn(true);
-
-        mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothAdapter.STATE_CONNECTED, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
-        shadowOf(Looper.getMainLooper()).idle();
-
-        verify(device).setMetadata(eq(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS), any());
-        verify(mFragment).finish();
-
-        ShadowDialogFragment.reset();
-    }
-
-    @Test
     @DisableFlags({Flags.FLAG_ENABLE_LE_AUDIO_SHARING, Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI})
     public void onProfileConnectionStateChanged_deviceNotInSelectedList_doNothing() {
         final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B);
@@ -537,38 +433,6 @@
         mFragment.mShouldTriggerShareThenPairFlow = mFragment.shouldTriggerShareThenPairFlow();
     }
 
-    private void setUpAudioSharingStates(boolean enabled, boolean needSetTempBondMetadata) {
-        when(mLocalManager.getProfileManager()).thenReturn(mProfileManager);
-        when(mProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast);
-        when(mProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant);
-        when(mLocalManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
-        if (!enabled) {
-            when(mBroadcast.isEnabled(null)).thenReturn(false);
-        } else {
-            when(mBroadcast.isEnabled(null)).thenReturn(true);
-            when(mBroadcast.getLatestBroadcastId()).thenReturn(1);
-            BluetoothDevice device1 = mock(BluetoothDevice.class);
-            CachedBluetoothDevice cachedDevice1 = mock(CachedBluetoothDevice.class);
-            when(mDeviceManager.findDevice(device1)).thenReturn(cachedDevice1);
-            when(cachedDevice1.getGroupId()).thenReturn(1);
-            when(cachedDevice1.getDevice()).thenReturn(device1);
-            BluetoothLeBroadcastReceiveState state = mock(BluetoothLeBroadcastReceiveState.class);
-            when(state.getBroadcastId()).thenReturn(1);
-            when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(state));
-            if (needSetTempBondMetadata) {
-                when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device1));
-            } else {
-                BluetoothDevice device2 = mock(BluetoothDevice.class);
-                CachedBluetoothDevice cachedDevice2 = mock(CachedBluetoothDevice.class);
-                when(mDeviceManager.findDevice(device2)).thenReturn(cachedDevice2);
-                when(cachedDevice2.getGroupId()).thenReturn(2);
-                when(cachedDevice2.getDevice()).thenReturn(device2);
-                when(mAssistant.getAllConnectedDevices()).thenReturn(
-                        ImmutableList.of(device1, device2));
-            }
-        }
-    }
-
     private static class TestBluetoothDevicePairingDetailBase extends
             BluetoothDevicePairingDetailBase {
 
diff --git a/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java
index 887a324..5149bf4 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java
@@ -130,7 +130,7 @@
         verify(mBackend).updateMode(captor.capture());
         assertThat(captor.getValue().getPolicy().getPriorityCategoryAlarms())
                 .isEqualTo(STATE_DISALLOW);
-        assertThat(captor.getValue().getRule().getInterruptionFilter())
+        assertThat(captor.getValue().getInterruptionFilter())
                 .isEqualTo(INTERRUPTION_FILTER_PRIORITY);
     }
 
@@ -162,7 +162,7 @@
         verify(mBackend).updateMode(captor.capture());
         assertThat(captor.getValue().getPolicy().getPriorityCategoryAlarms())
                 .isEqualTo(STATE_DISALLOW);
-        assertThat(captor.getValue().getRule().getInterruptionFilter())
+        assertThat(captor.getValue().getInterruptionFilter())
                 .isEqualTo(INTERRUPTION_FILTER_ALL);
     }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java
index 1140238..ad4112d 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsPreferenceControllerTest.java
@@ -183,7 +183,7 @@
         // NONE is not actually propagated to the backend as an interruption filter;
         // the filter is set to priority, and sounds and visual effects are disallowed.
         // See AbstractZenModePreferenceController.
-        assertThat(captor.getValue().getRule().getInterruptionFilter())
+        assertThat(captor.getValue().getInterruptionFilter())
                 .isEqualTo(INTERRUPTION_FILTER_PRIORITY);
 
         // After screen is refreshed, NONE is now checked; others are unchecked.
@@ -217,7 +217,7 @@
         ArgumentCaptor<ZenMode> captor = ArgumentCaptor.forClass(ZenMode.class);
         verify(mBackend).updateMode(captor.capture());
         // Checks the policy value for PRIORITY is propagated to the backend.
-        assertThat(captor.getValue().getRule().getInterruptionFilter())
+        assertThat(captor.getValue().getInterruptionFilter())
                 .isEqualTo(INTERRUPTION_FILTER_PRIORITY);
 
         // After screen is refreshed, PRIORITY is now checked; others are unchecked.
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentTest.java
index cb853bb..4a0d8d4 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentTest.java
@@ -124,7 +124,7 @@
         verify(mBackend).updateMode(captor.capture());
         ZenMode savedMode = captor.getValue();
         assertThat(savedMode.getName()).isEqualTo("A newer name");
-        assertThat(savedMode.getRule().getIconResId()).isEqualTo(
+        assertThat(savedMode.getIconKey().resId()).isEqualTo(
                 R.drawable.ic_zen_mode_type_theater);
 
         assertThat(mActivity.isFinishing()).isTrue();
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java
index c949fb8..abd0b67 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeExitAtAlarmPreferenceControllerTest.java
@@ -34,6 +34,7 @@
 
 import com.android.settingslib.notification.modes.TestModeBuilder;
 import com.android.settingslib.notification.modes.ZenMode;
+import com.android.settingslib.notification.modes.ZenModeSchedules;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 
 import org.junit.Before;
@@ -89,7 +90,7 @@
 
         // Now update state after changing exitAtAlarm
         scheduleInfo.exitAtAlarm = true;
-        mode.getRule().setConditionId(ZenModeConfig.toScheduleConditionId(scheduleInfo));
+        mode.setCustomModeConditionId(mContext, ZenModeConfig.toScheduleConditionId(scheduleInfo));
 
         // now can just call updateState
         mPrefController.updateState(preference, mode);
@@ -117,8 +118,8 @@
         mPrefController.onPreferenceChange(preference, false);
         ArgumentCaptor<ZenMode> captor = ArgumentCaptor.forClass(ZenMode.class);
         verify(mBackend).updateMode(captor.capture());
-        ZenModeConfig.ScheduleInfo newSchedule = ZenModeConfig.tryParseScheduleConditionId(
-                captor.getValue().getRule().getConditionId());
+        ZenModeConfig.ScheduleInfo newSchedule = ZenModeSchedules.getTimeSchedule(
+                captor.getValue());
         assertThat(newSchedule.exitAtAlarm).isFalse();
 
         // other properties remain the same
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java
index f0c2369..512e8af 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetCalendarPreferenceControllerTest.java
@@ -41,6 +41,7 @@
 
 import com.android.settingslib.notification.modes.TestModeBuilder;
 import com.android.settingslib.notification.modes.ZenMode;
+import com.android.settingslib.notification.modes.ZenModeSchedules;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 
 import org.junit.Before;
@@ -102,10 +103,10 @@
         // apply event mode updater to existing mode
         ZenMode out = mPrefController.updateEventMode(eventInfo).apply(mode);
 
-        assertThat(out.getRule().getOwner()).isEqualTo(ZenModeConfig.getEventConditionProvider());
-        assertThat(out.getRule().getConditionId()).isEqualTo(
-                ZenModeConfig.toEventConditionId(eventInfo));
-        assertThat(out.getRule().getTriggerDescription()).isEqualTo("My events");
+        assertThat(ZenModeSchedules.getCalendarSchedule(out)).isEqualTo(eventInfo);
+        assertThat(out.getOwner().conditionProvider()).isEqualTo(
+                ZenModeConfig.getEventConditionProvider());
+        assertThat(out.getTriggerDescription()).isEqualTo("My events");
     }
 
     @Test
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 b446d71..0ae37b6 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeSetSchedulePreferenceControllerTest.java
@@ -38,6 +38,7 @@
 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.ZenModeSchedules;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 
 import org.junit.Before;
@@ -92,11 +93,10 @@
         scheduleInfo.endHour = 2;
         ZenMode out = mPrefController.updateScheduleMode(scheduleInfo).apply(mode);
 
-        assertThat(out.getRule().getConditionId())
-                .isEqualTo(ZenModeConfig.toScheduleConditionId(scheduleInfo));
-        assertThat(out.getRule().getTriggerDescription()).isNotEmpty();
-        assertThat(out.getRule().getOwner()).isEqualTo(
+        assertThat(ZenModeSchedules.getTimeSchedule(out)).isEqualTo(scheduleInfo);
+        assertThat(out.getOwner().conditionProvider()).isEqualTo(
                 ZenModeConfig.getScheduleConditionProvider());
+        assertThat(out.getTriggerDescription()).isNotEmpty();
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerAddPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerAddPreferenceControllerTest.java
index 0a8e400..b8f8ff3 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerAddPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerAddPreferenceControllerTest.java
@@ -44,6 +44,7 @@
 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.ZenModeSchedules;
 import com.android.settingslib.notification.modes.ZenModesBackend;
 
 import org.junit.Before;
@@ -168,9 +169,9 @@
         verify(mBackend).updateMode(captor.capture());
         ZenMode updatedMode = captor.getValue();
         assertThat(updatedMode.getType()).isEqualTo(TYPE_SCHEDULE_TIME);
-        assertThat(updatedMode.getRule().getConditionId()).isEqualTo(scheduleUri);
-        assertThat(updatedMode.getRule().getTriggerDescription()).isNotEmpty();
-        assertThat(updatedMode.getRule().getOwner()).isEqualTo(
+        assertThat(ZenModeSchedules.getTimeSchedule(updatedMode)).isEqualTo(scheduleInfo);
+        assertThat(updatedMode.getTriggerDescription()).isNotEmpty();
+        assertThat(updatedMode.getOwner().conditionProvider()).isEqualTo(
                 ZenModeConfig.getScheduleConditionProvider());
     }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceControllerTest.java
index 6e6485e..b5d4203 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceControllerTest.java
@@ -161,7 +161,7 @@
         assertThat(mPreference.getCheckedState()).isFalse();
 
         // Now with the rule enabled
-        zenMode.getRule().setEnabled(true);
+        zenMode.setEnabled(true);
         mController.updateZenMode(mPreference, zenMode);
         assertThat(mPreference.getCheckedState()).isTrue();
     }
@@ -189,7 +189,7 @@
         // Verify the backend got asked to update the mode to be enabled
         ArgumentCaptor<ZenMode> captor = ArgumentCaptor.forClass(ZenMode.class);
         verify(mBackend).updateMode(captor.capture());
-        assertThat(captor.getValue().getRule().isEnabled()).isTrue();
+        assertThat(captor.getValue().isEnabled()).isTrue();
         assertThat(ShadowAlertDialog.getLatestAlertDialog().isShowing()).isFalse();
     }
 
@@ -216,7 +216,7 @@
         // Verify the backend got asked to update the mode to be disabled
         ArgumentCaptor<ZenMode> captor = ArgumentCaptor.forClass(ZenMode.class);
         verify(mBackend).updateMode(captor.capture());
-        assertThat(captor.getValue().getRule().isEnabled()).isFalse();
+        assertThat(captor.getValue().isEnabled()).isFalse();
         assertThat(ShadowAlertDialog.getLatestAlertDialog().isShowing()).isFalse();
     }
 
diff --git a/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceControllerTest.kt
index 5d68f98..67659ba 100644
--- a/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceControllerTest.kt
+++ b/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceControllerTest.kt
@@ -17,17 +17,23 @@
 package com.android.settings.deviceinfo.simstatus
 
 import android.content.Context
+import android.os.UserManager
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.dx.mockito.inline.extended.ExtendedMockito
 import com.android.settings.core.BasePreferenceController
 import com.android.settings.network.SubscriptionUtil
+import com.android.settingslib.Utils
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.MockitoSession
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
 import org.mockito.kotlin.whenever
 import org.mockito.quality.Strictness
 
@@ -35,7 +41,12 @@
 class SimEidPreferenceControllerTest {
     private lateinit var mockSession: MockitoSession
 
-    private val context: Context = ApplicationProvider.getApplicationContext()
+    private val mockUserManager = mock<UserManager>()
+
+    private val context: Context =
+        spy(ApplicationProvider.getApplicationContext()) {
+            on { getSystemService(UserManager::class.java) } doReturn mockUserManager
+        }
 
     private val controller = SimEidPreferenceController(context, TEST_KEY)
 
@@ -44,8 +55,16 @@
         mockSession = ExtendedMockito.mockitoSession()
             .initMocks(this)
             .mockStatic(SubscriptionUtil::class.java)
+            .mockStatic(Utils::class.java)
             .strictness(Strictness.LENIENT)
             .startMocking()
+
+        // By default, available
+        whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
+        whenever(Utils.isWifiOnly(context)).thenReturn(false)
+        mockUserManager.stub {
+            on { isAdminUser } doReturn true
+        }
     }
 
     @After
@@ -54,20 +73,35 @@
     }
 
     @Test
-    fun getAvailabilityStatus_isSimHardwareVisible() {
-        whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
-
+    fun getAvailabilityStatus_simHardwareVisible_userAdmin_notWifiOnly_displayed() {
+        // Use defaults from setup()
         val availabilityStatus = controller.availabilityStatus
-
         assertThat(availabilityStatus).isEqualTo(BasePreferenceController.AVAILABLE)
     }
 
     @Test
-    fun getAvailabilityStatus_notSimHardwareVisible() {
+    fun getAvailabilityStatus_notSimHardwareVisible_userAdmin_notWifiOnly_notDisplayed() {
         whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(false)
 
         val availabilityStatus = controller.availabilityStatus
+        assertThat(availabilityStatus).isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE)
+    }
 
+    @Test
+    fun getAvailabilityStatus_simHardwareVisible_notUserAdmin_notWifiOnly_notDisplayed() {
+        mockUserManager.stub {
+            on { isAdminUser } doReturn false
+        }
+
+        val availabilityStatus = controller.availabilityStatus
+        assertThat(availabilityStatus).isEqualTo(BasePreferenceController.DISABLED_FOR_USER)
+    }
+
+    @Test
+    fun getAvailabilityStatus_simHardwareVisible_userAdmin_wifiOnly_notDisplayed() {
+        whenever(Utils.isWifiOnly(context)).thenReturn(true)
+
+        val availabilityStatus = controller.availabilityStatus
         assertThat(availabilityStatus).isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE)
     }
 
diff --git a/tests/unit/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceControllerTest.java
index 6318c9c..300d028 100644
--- a/tests/unit/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceControllerTest.java
@@ -86,7 +86,7 @@
         when(mController.getStorageManagerVolumeProvider())
                 .thenReturn(mStorageManagerVolumeProvider);
         final String percentage = NumberFormat.getPercentInstance().format(1);
-        final String freeSpace = Formatter.formatFileSize(mContext, 0);
+        final String[] freeSpace = Formatter.formatFileSize(mContext, 0).split(" ");
         final Preference preference = new Preference(mContext);
 
         // Wait for asynchronous thread to finish, otherwise test will flake.
@@ -103,6 +103,6 @@
         // the background thread.
         TimeUnit.SECONDS.sleep(5);
         assertThat(preference.getSummary()).isEqualTo(ResourcesUtils.getResourcesString(
-                mContext, "storage_summary", percentage, freeSpace));
+                mContext, "storage_summary", percentage, freeSpace[0], freeSpace[1]));
     }
 }