summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java7
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt57
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt44
-rw-r--r--packages/SystemUI/res/values/strings.xml10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/view/EmptyShadeView.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt26
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt2
8 files changed, 200 insertions, 21 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java
index 712ddc8aea4b..5eeb49a0b398 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/TestModeBuilder.java
@@ -167,6 +167,13 @@ public class TestModeBuilder {
return this;
}
+ public TestModeBuilder setVisualEffect(int effect, boolean allowed) {
+ ZenPolicy newPolicy = new ZenPolicy.Builder(mRule.getZenPolicy())
+ .showVisualEffect(effect, allowed).build();
+ setZenPolicy(newPolicy);
+ return this;
+ }
+
public TestModeBuilder setEnabled(boolean enabled) {
return setEnabled(enabled, /* byUser= */ false);
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt
index 925cf15feabc..f9b77697b767 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelTest.kt
@@ -16,17 +16,20 @@
package com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel
+import android.app.Flags
import android.app.NotificationManager.Policy
+import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.provider.Settings
+import android.service.notification.ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST
import androidx.test.filters.SmallTest
import com.android.settingslib.notification.data.repository.updateNotificationPolicy
+import com.android.settingslib.notification.modes.TestModeBuilder
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.andSceneContainer
import com.android.systemui.kosmos.testScope
-import com.android.systemui.res.R
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
@@ -117,6 +120,7 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
@EnableFlags(ModesEmptyShadeFix.FLAG_NAME)
+ @DisableFlags(Flags.FLAG_MODES_UI, Flags.FLAG_MODES_API)
fun text_changesWhenNotifsHiddenInShade() =
testScope.runTest {
val text by collectLastValue(underTest.text)
@@ -127,7 +131,7 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_OFF)
runCurrent()
- assertThat(text).isEqualTo(R.string.empty_shade_text)
+ assertThat(text).isEqualTo("No notifications")
zenModeRepository.updateNotificationPolicy(
suppressedVisualEffects = Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST
@@ -135,7 +139,54 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
zenModeRepository.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
runCurrent()
- assertThat(text).isEqualTo(R.string.dnd_suppressing_shade_text)
+ assertThat(text).isEqualTo("Notifications paused by Do Not Disturb")
+ }
+
+ @Test
+ @EnableFlags(ModesEmptyShadeFix.FLAG_NAME, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_API)
+ fun text_reflectsModesHidingNotifications() =
+ testScope.runTest {
+ val text by collectLastValue(underTest.text)
+
+ assertThat(text).isEqualTo("No notifications")
+
+ zenModeRepository.addMode(
+ TestModeBuilder()
+ .setId("Do not disturb")
+ .setName("Do not disturb")
+ .setActive(true)
+ .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
+ .build()
+ )
+ runCurrent()
+ assertThat(text).isEqualTo("Notifications paused by Do not disturb")
+
+ zenModeRepository.addMode(
+ TestModeBuilder()
+ .setId("Work")
+ .setName("Work")
+ .setActive(true)
+ .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
+ .build()
+ )
+ runCurrent()
+ assertThat(text).isEqualTo("Notifications paused by Do not disturb and one other mode")
+
+ zenModeRepository.addMode(
+ TestModeBuilder()
+ .setId("Gym")
+ .setName("Gym")
+ .setActive(true)
+ .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
+ .build()
+ )
+ runCurrent()
+ assertThat(text).isEqualTo("Notifications paused by Do not disturb and 2 other modes")
+
+ zenModeRepository.deactivateMode("Do not disturb")
+ zenModeRepository.deactivateMode("Work")
+ runCurrent()
+ assertThat(text).isEqualTo("Notifications paused by Gym")
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
index 0f6dc0723f42..c5ccf9e6a1d1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractorTest.kt
@@ -25,6 +25,7 @@ import android.provider.Settings.Secure.ZEN_DURATION
import android.provider.Settings.Secure.ZEN_DURATION_FOREVER
import android.provider.Settings.Secure.ZEN_DURATION_PROMPT
import android.service.notification.SystemZenRules
+import android.service.notification.ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.R
@@ -34,6 +35,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.shared.settings.data.repository.secureSettingsRepository
+import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository
import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository
import com.android.systemui.testKosmos
@@ -379,4 +381,46 @@ class ZenModeInteractorTest : SysuiTestCase() {
assertThat(dndMode!!.isActive).isTrue()
}
+
+ @Test
+ @EnableFlags(ModesEmptyShadeFix.FLAG_NAME, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_API)
+ fun modesHidingNotifications_onlyIncludesModesWithNotifListSuppression() =
+ testScope.runTest {
+ val modesHidingNotifications by collectLastValue(underTest.modesHidingNotifications)
+
+ zenModeRepository.addModes(
+ listOf(
+ TestModeBuilder()
+ .setName("Not active, no list suppression")
+ .setActive(false)
+ .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ true)
+ .build(),
+ TestModeBuilder()
+ .setName("Not active, has list suppression")
+ .setActive(false)
+ .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
+ .build(),
+ TestModeBuilder()
+ .setName("No list suppression")
+ .setActive(true)
+ .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ true)
+ .build(),
+ TestModeBuilder()
+ .setName("Has list suppression 1")
+ .setActive(true)
+ .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
+ .build(),
+ TestModeBuilder()
+ .setName("Has list suppression 2")
+ .setActive(true)
+ .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
+ .build(),
+ )
+ )
+ runCurrent()
+
+ assertThat(modesHidingNotifications?.map { it.name })
+ .containsExactly("Has list suppression 1", "Has list suppression 2")
+ .inOrder()
+ }
}
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ba3822bd3c23..d918cf5470c4 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1473,6 +1473,16 @@
<!-- The text to show in the notifications shade when dnd is suppressing notifications. [CHAR LIMIT=100] -->
<string name="dnd_suppressing_shade_text">Notifications paused by Do Not Disturb</string>
+ <!-- The text to show in the notifications shade when a mode is suppressing notifications. [CHAR LIMIT=100] -->
+ <string name="modes_suppressing_shade_text">
+ {count, plural, offset:1
+ =0 {No notifications}
+ =1 {Notifications paused by {mode}}
+ =2 {Notifications paused by {mode} and one other mode}
+ other {Notifications paused by {mode} and # other modes}
+ }
+ </string>
+
<!-- Media projection permission dialog action text. [CHAR LIMIT=60] -->
<string name="media_projection_action_text">Start now</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/view/EmptyShadeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/view/EmptyShadeView.java
index e6527032e19c..73477da247f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/view/EmptyShadeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/view/EmptyShadeView.java
@@ -39,12 +39,15 @@ import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import kotlin.Unit;
+import java.util.Objects;
+
public class EmptyShadeView extends StackScrollerDecorView implements LaunchableView {
private TextView mEmptyText;
private TextView mEmptyFooterText;
- private @StringRes int mText = R.string.empty_shade_text;
+ private @StringRes int mTextId = R.string.empty_shade_text;
+ private String mTextString;
private @DrawableRes int mFooterIcon;
private @StringRes int mFooterText;
@@ -62,7 +65,9 @@ public class EmptyShadeView extends StackScrollerDecorView implements Launchable
super(context, attrs);
mSize = getResources().getDimensionPixelSize(
R.dimen.notifications_unseen_footer_icon_size);
- if (!ModesEmptyShadeFix.isEnabled()) {
+ if (ModesEmptyShadeFix.isEnabled()) {
+ mTextString = getContext().getString(R.string.empty_shade_text);
+ } else {
// These will be set by the binder when appropriate if ModesEmptyShadeFix is on.
mFooterIcon = R.drawable.ic_friction_lock_closed;
mFooterText = R.string.unlock_to_see_notif_text;
@@ -97,7 +102,11 @@ public class EmptyShadeView extends StackScrollerDecorView implements Launchable
super.onConfigurationChanged(newConfig);
mSize = getResources().getDimensionPixelSize(
R.dimen.notifications_unseen_footer_icon_size);
- mEmptyText.setText(mText);
+ if (ModesEmptyShadeFix.isEnabled()) {
+ mEmptyText.setText(mTextString);
+ } else {
+ mEmptyText.setText(mTextId);
+ }
mEmptyFooterText.setVisibility(mFooterVisibility);
setFooterText(mFooterText);
setFooterIcon(mFooterIcon);
@@ -122,11 +131,18 @@ public class EmptyShadeView extends StackScrollerDecorView implements Launchable
/** Set the resource ID for the main text shown by the view. */
public void setText(@StringRes int text) {
- if (ModesEmptyShadeFix.isEnabled() && mText == text) {
- return; // nothing to change
+ ModesEmptyShadeFix.assertInLegacyMode();
+ mTextId = text;
+ mEmptyText.setText(mTextId);
+ }
+
+ /** Set the string for the main text shown by the view. */
+ public void setText(String text) {
+ if (ModesEmptyShadeFix.isUnexpectedlyInLegacyMode() || Objects.equals(mTextString, text)) {
+ return;
}
- mText = text;
- mEmptyText.setText(mText);
+ mTextString = text;
+ mEmptyText.setText(text);
}
/** Visibility for the footer (the additional icon+text shown below the main text). */
@@ -173,7 +189,7 @@ public class EmptyShadeView extends StackScrollerDecorView implements Launchable
@StringRes
public int getTextResource() {
ModesEmptyShadeFix.assertInLegacyMode();
- return mText;
+ return mTextId;
}
/** Get resource ID for footer text. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt
index 03b729c87aaa..d5417e7ae8f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModel.kt
@@ -16,7 +16,10 @@
package com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel
+import android.content.Context
+import android.icu.text.MessageFormat
import com.android.systemui.dump.DumpManager
+import com.android.systemui.modes.shared.ModesUi
import com.android.systemui.res.R
import com.android.systemui.shared.notifications.domain.interactor.NotificationSettingsInteractor
import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor
@@ -27,6 +30,7 @@ import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
import com.android.systemui.util.kotlin.FlowDumperImpl
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
+import java.util.Locale
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -40,6 +44,7 @@ import kotlinx.coroutines.flow.map
class EmptyShadeViewModel
@AssistedInject
constructor(
+ private val context: Context,
zenModeInteractor: ZenModeInteractor,
seenNotificationsInteractor: SeenNotificationsInteractor,
notificationSettingsInteractor: NotificationSettingsInteractor,
@@ -65,16 +70,38 @@ constructor(
}
}
- val text: Flow<Int> by lazy {
+ val text: Flow<String> by lazy {
if (ModesEmptyShadeFix.isUnexpectedlyInLegacyMode()) {
- flowOf(R.string.empty_shade_text)
+ flowOf(context.getString(R.string.empty_shade_text))
} else {
- areNotificationsHiddenInShade.map { areNotificationsHiddenInShade ->
- if (areNotificationsHiddenInShade) {
- // TODO(b/366003631): This should reflect the current mode instead of just DND.
- R.string.dnd_suppressing_shade_text
- } else {
- R.string.empty_shade_text
+ // Note: Flag modes_ui_empty_shade includes two pieces: refactoring the empty shade to
+ // recommended architecture, and making it so it reacts to changes for the new Modes.
+ // The former does not depend on the modes flags being on, but the latter does.
+ if (ModesUi.isEnabled) {
+ zenModeInteractor.modesHidingNotifications.map { modes ->
+ // Create a string that is either "No notifications" if no modes are filtering
+ // them
+ // out, or something like "Notifications paused by SomeMode" otherwise.
+ val msgFormat =
+ MessageFormat(
+ context.getString(R.string.modes_suppressing_shade_text),
+ Locale.getDefault(),
+ )
+ val count = modes.count()
+ val args: MutableMap<String, Any> = HashMap()
+ args["count"] = count
+ if (count >= 1) {
+ args["mode"] = modes[0].name
+ }
+ msgFormat.format(args)
+ }
+ } else {
+ areNotificationsHiddenInShade.map { areNotificationsHiddenInShade ->
+ if (areNotificationsHiddenInShade) {
+ context.getString(R.string.dnd_suppressing_shade_text)
+ } else {
+ context.getString(R.string.empty_shade_text)
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
index ba45942177a2..daba1099c49d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt
@@ -20,6 +20,7 @@ import android.content.Context
import android.provider.Settings
import android.provider.Settings.Secure.ZEN_DURATION_FOREVER
import android.provider.Settings.Secure.ZEN_DURATION_PROMPT
+import android.service.notification.ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST
import android.util.Log
import androidx.concurrent.futures.await
import com.android.settingslib.notification.data.repository.ZenModeRepository
@@ -29,6 +30,7 @@ import com.android.settingslib.notification.modes.ZenMode
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.modes.shared.ModesUi
import com.android.systemui.shared.notifications.data.repository.NotificationSettingsRepository
+import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix
import com.android.systemui.statusbar.policy.data.repository.DeviceProvisioningRepository
import com.android.systemui.statusbar.policy.data.repository.UserSetupRepository
import com.android.systemui.statusbar.policy.domain.model.ActiveZenModes
@@ -39,6 +41,7 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
@@ -54,8 +57,8 @@ constructor(
private val notificationSettingsRepository: NotificationSettingsRepository,
@Background private val bgDispatcher: CoroutineDispatcher,
private val iconLoader: ZenIconLoader,
- private val deviceProvisioningRepository: DeviceProvisioningRepository,
- private val userSetupRepository: UserSetupRepository,
+ deviceProvisioningRepository: DeviceProvisioningRepository,
+ userSetupRepository: UserSetupRepository,
) {
val isZenAvailable: Flow<Boolean> =
combine(
@@ -126,6 +129,25 @@ constructor(
val mainActiveMode: Flow<ZenModeInfo?> =
activeModes.map { a -> a.mainMode }.distinctUntilChanged()
+ val modesHidingNotifications: Flow<List<ZenMode>> by lazy {
+ if (ModesEmptyShadeFix.isUnexpectedlyInLegacyMode() || !ModesUi.isEnabled) {
+ flowOf(listOf())
+ } else {
+ modes
+ .map { modes ->
+ modes.filter { mode ->
+ mode.isActive &&
+ !mode.policy.isVisualEffectAllowed(
+ /* effect = */ VISUAL_EFFECT_NOTIFICATION_LIST,
+ /* defaultVal = */ true,
+ )
+ }
+ }
+ .flowOn(bgDispatcher)
+ .distinctUntilChanged()
+ }
+ }
+
suspend fun getModeIcon(mode: ZenMode): ZenIcon {
return iconLoader.getIcon(context, mode).await()
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt
index d61dd2811daa..8fdb948e2d1d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/emptyshade/ui/viewmodel/EmptyShadeViewModelKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel
+import android.content.applicationContext
import com.android.systemui.dump.dumpManager
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.shared.notifications.domain.interactor.notificationSettingsInteractor
@@ -25,6 +26,7 @@ import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor
val Kosmos.emptyShadeViewModel by
Kosmos.Fixture {
EmptyShadeViewModel(
+ applicationContext,
zenModeInteractor,
seenNotificationsInteractor,
notificationSettingsInteractor,