diff --git a/res/xml/modes_other_settings.xml b/res/xml/modes_other_settings.xml
new file mode 100644
index 00000000000..2dc2c7e0f61
--- /dev/null
+++ b/res/xml/modes_other_settings.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/xml/modes_rule_settings.xml b/res/xml/modes_rule_settings.xml
index 12a683e6bec..7a08a68d8c0 100644
--- a/res/xml/modes_rule_settings.xml
+++ b/res/xml/modes_rule_settings.xml
@@ -26,4 +26,8 @@
android:key="zen_mode_people"
android:title="@string/zen_category_people"/>
+
+
\ No newline at end of file
diff --git a/src/com/android/settings/notification/modes/ZenModeFragment.java b/src/com/android/settings/notification/modes/ZenModeFragment.java
index 1626d91bd85..51772f00a45 100644
--- a/src/com/android/settings/notification/modes/ZenModeFragment.java
+++ b/src/com/android/settings/notification/modes/ZenModeFragment.java
@@ -41,6 +41,8 @@ public class ZenModeFragment extends ZenModeFragmentBase {
prefControllers.add(new ZenModeHeaderController(context, "header", this, mBackend));
prefControllers.add(new ZenModePeopleLinkPreferenceController(
context, "zen_mode_people", mBackend));
+ prefControllers.add(new ZenModeOtherLinkPreferenceController(
+ context, "zen_other_settings", mBackend));
return prefControllers;
}
diff --git a/src/com/android/settings/notification/modes/ZenModeOtherFragment.java b/src/com/android/settings/notification/modes/ZenModeOtherFragment.java
new file mode 100644
index 00000000000..1149cd1312f
--- /dev/null
+++ b/src/com/android/settings/notification/modes/ZenModeOtherFragment.java
@@ -0,0 +1,64 @@
+/*
+ * 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 android.service.notification.ZenPolicy.PRIORITY_CATEGORY_ALARMS;
+import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_EVENTS;
+import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_MEDIA;
+import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_REMINDERS;
+import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_SYSTEM;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Mode > Alarms & Other Interruptions
+ */
+public class ZenModeOtherFragment extends ZenModeFragmentBase {
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ List controllers = new ArrayList<>();
+ controllers.add(new ZenModeOtherPreferenceController(
+ context, "modes_category_alarm", mBackend));
+ controllers.add(new ZenModeOtherPreferenceController(
+ context, "modes_category_media", mBackend));
+ controllers.add(new ZenModeOtherPreferenceController(
+ context, "modes_category_system", mBackend));
+ controllers.add(new ZenModeOtherPreferenceController(
+ context, "modes_category_reminders", mBackend));
+ controllers.add(new ZenModeOtherPreferenceController(
+ context, "modes_category_events", mBackend));
+ return controllers;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.modes_other_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ // TODO: b/332937635 - make this the correct metrics category
+ return SettingsEnums.NOTIFICATION_ZEN_MODE_PRIORITY;
+ }
+}
diff --git a/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java
new file mode 100644
index 00000000000..a43f8b056e1
--- /dev/null
+++ b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java
@@ -0,0 +1,52 @@
+/*
+ * 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.android.settings.notification.modes.ZenModeFragmentBase.MODE_ID;
+
+import android.content.Context;
+import android.os.Bundle;
+import androidx.preference.Preference;
+import com.android.settings.core.SubSettingLauncher;
+
+/**
+ * Preference with a link and summary about what other sounds can break through the mode
+ */
+public class ZenModeOtherLinkPreferenceController extends AbstractZenModePreferenceController {
+
+ ZenModeSummaryHelper mSummaryHelper;
+
+ public ZenModeOtherLinkPreferenceController(Context context, String key,
+ ZenModesBackend backend) {
+ super(context, key, backend);
+ mSummaryHelper = new ZenModeSummaryHelper(mContext, mBackend);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ Bundle bundle = new Bundle();
+ bundle.putString(MODE_ID, getMode().getId());
+ preference.setIntent(new SubSettingLauncher(mContext)
+ .setDestination(ZenModeOtherFragment.class.getName())
+ .setSourceMetricsCategory(0)
+ .setArguments(bundle)
+ .toIntent());
+ preference.setSummary(mSummaryHelper.getOtherSoundCategoriesSummary(getMode()));
+ }
+}
diff --git a/src/com/android/settings/notification/modes/ZenModeOtherPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeOtherPreferenceController.java
new file mode 100644
index 00000000000..e31fa0fa08b
--- /dev/null
+++ b/src/com/android/settings/notification/modes/ZenModeOtherPreferenceController.java
@@ -0,0 +1,74 @@
+/*
+ * 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 android.service.notification.ZenPolicy.PRIORITY_CATEGORY_ALARMS;
+import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_EVENTS;
+import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_MEDIA;
+import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_REMINDERS;
+import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_SYSTEM;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+import androidx.preference.Preference;
+import androidx.preference.TwoStatePreference;
+
+public class ZenModeOtherPreferenceController extends AbstractZenModePreferenceController
+ implements Preference.OnPreferenceChangeListener {
+
+ public ZenModeOtherPreferenceController(Context context, String key,
+ ZenModesBackend backend) {
+ super(context, key, backend);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+
+ TwoStatePreference pref = (TwoStatePreference) preference;
+ pref.setChecked(getMode().getPolicy().isCategoryAllowed(getCategory(), true));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean allow = (Boolean) newValue;
+
+ ZenPolicy diffPolicy = new ZenPolicy.Builder()
+ .allowCategory(getCategory(), allow)
+ .build();
+ getMode().setPolicy(diffPolicy);
+ mBackend.updateMode(getMode());
+
+ return true;
+ }
+
+ private int getCategory() {
+ switch (getPreferenceKey()) {
+ case "modes_category_alarm":
+ return PRIORITY_CATEGORY_ALARMS;
+ case "modes_category_media":
+ return PRIORITY_CATEGORY_MEDIA;
+ case "modes_category_system":
+ return PRIORITY_CATEGORY_SYSTEM;
+ case "modes_category_reminders":
+ return PRIORITY_CATEGORY_REMINDERS;
+ case "modes_category_events":
+ return PRIORITY_CATEGORY_EVENTS;
+ }
+ return -1;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java
new file mode 100644
index 00000000000..26da6ab8dc6
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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 android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.app.AutomaticZenRule;
+import android.app.Flags;
+import android.content.Context;
+import android.net.Uri;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.service.notification.ZenPolicy;
+import androidx.preference.Preference;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+@EnableFlags(Flags.FLAG_MODES_UI)
+public final class ZenModeOtherLinkPreferenceControllerTest {
+
+ private ZenModeOtherLinkPreferenceController mController;
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ private Context mContext;
+ @Mock
+ private ZenModesBackend mBackend;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application;
+
+ mController = new ZenModeOtherLinkPreferenceController(
+ mContext, "something", mBackend);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MODES_UI)
+ public void testHasSummary() {
+ Preference pref = mock(Preference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build())
+ .build(), true);
+ mController.updateZenMode(pref, zenMode);
+ verify(pref).setSummary(any());
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherPreferenceControllerTest.java
new file mode 100644
index 00000000000..6dd918a145f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherPreferenceControllerTest.java
@@ -0,0 +1,277 @@
+/*
+ * 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 android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
+import static android.service.notification.ZenPolicy.STATE_ALLOW;
+import static android.service.notification.ZenPolicy.STATE_UNSET;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.app.AutomaticZenRule;
+import android.app.Flags;
+import android.content.Context;
+import android.net.Uri;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.service.notification.ZenPolicy;
+import androidx.preference.TwoStatePreference;
+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.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+@EnableFlags(Flags.FLAG_MODES_UI)
+public final class ZenModeOtherPreferenceControllerTest {
+
+ private Context mContext;
+ @Mock
+ private ZenModesBackend mBackend;
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ }
+
+ @Test
+ public void testUpdateState_alarms() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
+ .build(), true);
+
+ ZenModeOtherPreferenceController controller =
+ new ZenModeOtherPreferenceController(mContext, "modes_category_alarm", mBackend);
+
+ controller.updateZenMode(preference, zenMode);
+
+ verify(preference).setChecked(true);
+ }
+
+ @Test
+ public void testOnPreferenceChange_alarms() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowAlarms(false).build())
+ .build(), true);
+
+ ZenModeOtherPreferenceController controller =
+ new ZenModeOtherPreferenceController(mContext, "modes_category_alarm", mBackend);
+
+ controller.updateZenMode(preference, zenMode);
+
+ controller.onPreferenceChange(preference, true);
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(ZenMode.class);
+ verify(mBackend).updateMode(captor.capture());
+ assertThat(captor.getValue().getPolicy().getPriorityCategoryAlarms())
+ .isEqualTo(STATE_ALLOW);
+ assertThat(captor.getValue().getPolicy().getPriorityCategoryEvents())
+ .isEqualTo(STATE_UNSET);
+ }
+
+ @Test
+ public void testUpdateState_media() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowMedia(true).build())
+ .build(), true);
+
+ ZenModeOtherPreferenceController controller =
+ new ZenModeOtherPreferenceController(mContext, "modes_category_media", mBackend);
+
+ controller.updateZenMode(preference, zenMode);
+
+ verify(preference).setChecked(true);
+ }
+
+ @Test
+ public void testOnPreferenceChange_media() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowMedia(false).build())
+ .build(), true);
+
+ ZenModeOtherPreferenceController controller =
+ new ZenModeOtherPreferenceController(mContext, "modes_category_media", mBackend);
+
+ controller.updateZenMode(preference, zenMode);
+
+ controller.onPreferenceChange(preference, true);
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(ZenMode.class);
+ verify(mBackend).updateMode(captor.capture());
+ assertThat(captor.getValue().getPolicy().getPriorityCategoryMedia())
+ .isEqualTo(STATE_ALLOW);
+ assertThat(captor.getValue().getPolicy().getPriorityCategoryEvents())
+ .isEqualTo(STATE_UNSET);
+ }
+
+ @Test
+ public void testUpdateState_system() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowSystem(true).build())
+ .build(), true);
+
+ ZenModeOtherPreferenceController controller =
+ new ZenModeOtherPreferenceController(mContext, "modes_category_system", mBackend);
+
+ controller.updateZenMode(preference, zenMode);
+
+ verify(preference).setChecked(true);
+ }
+
+ @Test
+ public void testOnPreferenceChange_system() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowSystem(false).build())
+ .build(), true);
+
+ ZenModeOtherPreferenceController controller =
+ new ZenModeOtherPreferenceController(mContext, "modes_category_system", mBackend);
+
+ controller.updateZenMode(preference, zenMode);
+
+ controller.onPreferenceChange(preference, true);
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(ZenMode.class);
+ verify(mBackend).updateMode(captor.capture());
+ assertThat(captor.getValue().getPolicy().getPriorityCategorySystem())
+ .isEqualTo(STATE_ALLOW);
+ assertThat(captor.getValue().getPolicy().getPriorityCategoryEvents())
+ .isEqualTo(STATE_UNSET);
+ }
+
+ @Test
+ public void testUpdateState_reminders() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowReminders(true).build())
+ .build(), true);
+
+ ZenModeOtherPreferenceController controller =
+ new ZenModeOtherPreferenceController(mContext, "modes_category_reminders",
+ mBackend);
+
+ controller.updateZenMode(preference, zenMode);
+
+ verify(preference).setChecked(true);
+ }
+
+ @Test
+ public void testOnPreferenceChange_reminders() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowReminders(false).build())
+ .build(), true);
+
+ ZenModeOtherPreferenceController controller =
+ new ZenModeOtherPreferenceController(mContext, "modes_category_reminders",
+ mBackend);
+
+ controller.updateZenMode(preference, zenMode);
+
+ controller.onPreferenceChange(preference, true);
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(ZenMode.class);
+ verify(mBackend).updateMode(captor.capture());
+ assertThat(captor.getValue().getPolicy().getPriorityCategoryReminders())
+ .isEqualTo(STATE_ALLOW);
+ assertThat(captor.getValue().getPolicy().getPriorityCategoryEvents())
+ .isEqualTo(STATE_UNSET);
+ }
+
+ @Test
+ public void testUpdateState_events() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowEvents(true).build())
+ .build(), true);
+
+ ZenModeOtherPreferenceController controller =
+ new ZenModeOtherPreferenceController(mContext, "modes_category_events", mBackend);
+
+ controller.updateZenMode(preference, zenMode);
+
+ verify(preference).setChecked(true);
+ }
+
+ @Test
+ public void testOnPreferenceChange_events() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowEvents(false).build())
+ .build(), true);
+
+ ZenModeOtherPreferenceController controller =
+ new ZenModeOtherPreferenceController(mContext, "modes_category_events", mBackend);
+
+ controller.updateZenMode(preference, zenMode);
+
+ controller.onPreferenceChange(preference, true);
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(ZenMode.class);
+ verify(mBackend).updateMode(captor.capture());
+ assertThat(captor.getValue().getPolicy().getPriorityCategoryEvents())
+ .isEqualTo(STATE_ALLOW);
+ assertThat(captor.getValue().getPolicy().getPriorityCategoryAlarms())
+ .isEqualTo(STATE_UNSET);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeRepeatCallersPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeRepeatCallersPreferenceControllerTest.java
new file mode 100644
index 00000000000..7bbb042c471
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeRepeatCallersPreferenceControllerTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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 android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
+import static android.service.notification.ZenPolicy.PEOPLE_TYPE_ANYONE;
+import static android.service.notification.ZenPolicy.PEOPLE_TYPE_STARRED;
+import static android.service.notification.ZenPolicy.STATE_ALLOW;
+import static android.service.notification.ZenPolicy.STATE_DISALLOW;
+import static android.service.notification.ZenPolicy.STATE_UNSET;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.app.AutomaticZenRule;
+import android.app.Flags;
+import android.content.Context;
+import android.net.Uri;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.service.notification.ZenPolicy;
+import androidx.preference.TwoStatePreference;
+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.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+@EnableFlags(Flags.FLAG_MODES_UI)
+public final class ZenModeRepeatCallersPreferenceControllerTest {
+
+ private Context mContext;
+ @Mock
+ private ZenModesBackend mBackend;
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ }
+
+ @Test
+ public void testUpdateState_allCalls() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(PEOPLE_TYPE_ANYONE)
+ .build())
+ .build(), true);
+
+ ZenModeRepeatCallersPreferenceController controller =
+ new ZenModeRepeatCallersPreferenceController(mContext, "repeat", mBackend, 1);
+
+ controller.updateZenMode(preference, zenMode);
+
+ verify(preference).setChecked(true);
+ verify(preference).setEnabled(false);
+ }
+
+ @Test
+ public void testUpdateState_someCalls() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(PEOPLE_TYPE_STARRED)
+ .allowRepeatCallers(true)
+ .build())
+ .build(), true);
+
+ ZenModeRepeatCallersPreferenceController controller =
+ new ZenModeRepeatCallersPreferenceController(mContext, "repeat", mBackend, 1);
+
+ controller.updateZenMode(preference, zenMode);
+
+ verify(preference).setChecked(true);
+ verify(preference).setEnabled(true);
+ }
+
+ @Test
+ public void testOnPreferenceChange() {
+ TwoStatePreference preference = mock(TwoStatePreference.class);
+ ZenMode zenMode = new ZenMode("id",
+ new AutomaticZenRule.Builder("Driving", Uri.parse("drive"))
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowRepeatCallers(true).build())
+ .build(), true);
+
+ ZenModeRepeatCallersPreferenceController controller =
+ new ZenModeRepeatCallersPreferenceController(mContext, "repeat", mBackend, 1);
+
+ controller.updateZenMode(preference, zenMode);
+
+ controller.onPreferenceChange(preference, false);
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(ZenMode.class);
+ verify(mBackend).updateMode(captor.capture());
+ assertThat(captor.getValue().getPolicy().getPriorityCategoryRepeatCallers())
+ .isEqualTo(STATE_DISALLOW);
+ assertThat(captor.getValue().getPolicy().getPriorityCategoryEvents())
+ .isEqualTo(STATE_UNSET);
+ assertThat(captor.getValue().getPolicy().getPriorityCallSenders())
+ .isEqualTo(STATE_UNSET);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java
index 621c5b06f9d..67be82f9032 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java
@@ -85,4 +85,84 @@ public class ZenModesSummaryHelperTest {
assertThat(mSummaryHelper.getPeopleSummary(zenMode)).isEqualTo("All people can interrupt");
}
+
+ @Test
+ public void getOtherSoundCategoriesSummary_single() {
+ AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
+ .setType(AutomaticZenRule.TYPE_BEDTIME)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).build())
+ .build();
+ ZenMode zenMode = new ZenMode("id", rule, true);
+
+ assertThat(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)).isEqualTo(
+ "Alarms can interrupt");
+ }
+
+ @Test
+ public void getOtherSoundCategoriesSummary_duo() {
+ AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
+ .setType(AutomaticZenRule.TYPE_BEDTIME)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder().allowAlarms(true).allowMedia(true).build())
+ .build();
+ ZenMode zenMode = new ZenMode("id", rule, true);
+
+ assertThat(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)).isEqualTo(
+ "Alarms and media can interrupt");
+ }
+
+ @Test
+ public void getOtherSoundCategoriesSummary_trio() {
+ AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
+ .setType(AutomaticZenRule.TYPE_BEDTIME)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .allowMedia(true)
+ .allowSystem(true)
+ .build())
+ .build();
+ ZenMode zenMode = new ZenMode("id", rule, true);
+
+ assertThat(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)).isEqualTo(
+ "Alarms, media, and touch sounds can interrupt");
+ }
+
+ @Test
+ public void getOtherSoundCategoriesSummary_quad() {
+ AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
+ .setType(AutomaticZenRule.TYPE_BEDTIME)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .allowMedia(true)
+ .allowSystem(true)
+ .allowReminders(true)
+ .build())
+ .build();
+ ZenMode zenMode = new ZenMode("id", rule, true);
+
+ assertThat(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)).isEqualTo(
+ "Alarms, media, and 2 more can interrupt");
+ }
+
+ @Test
+ public void getOtherSoundCategoriesSummary_all() {
+ AutomaticZenRule rule = new AutomaticZenRule.Builder("Bedtime", Uri.parse("bed"))
+ .setType(AutomaticZenRule.TYPE_BEDTIME)
+ .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)
+ .setZenPolicy(new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .allowMedia(true)
+ .allowSystem(true)
+ .allowReminders(true)
+ .allowEvents(true)
+ .build())
+ .build();
+ ZenMode zenMode = new ZenMode("id", rule, true);
+
+ assertThat(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)).isEqualTo(
+ "Alarms, media, and 3 more can interrupt");
+ }
}