Remove obsolete "Gaming" zen rule
SystemUI used to create this AutomaticZenRule, but stopped doing so around Android S or thereabouts, and was left over in some devices (or any newer devices that restore from such backups).
Fixes: 372705480
Test: ZenModesCleanupTest
Flag: android.app.modes_ui
Change-Id: Idf49dd8d67d00d3d7ce904f552e4a1092478c775
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModesCleanupStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModesCleanupStartableTest.kt
new file mode 100644
index 0000000..4a53a7a
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ZenModesCleanupStartableTest.kt
@@ -0,0 +1,117 @@
+/*
+ * 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.systemui.statusbar.policy
+
+import android.app.AutomaticZenRule
+import android.app.NotificationManager
+import android.net.Uri
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.backgroundCoroutineContext
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ZenModesCleanupStartableTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ @Mock private lateinit var notificationManager: NotificationManager
+
+ private lateinit var underTest: ZenModesCleanupStartable
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ underTest =
+ ZenModesCleanupStartable(
+ testScope.backgroundScope,
+ kosmos.backgroundCoroutineContext,
+ notificationManager,
+ )
+ }
+
+ @Test
+ fun start_withGamingModeZenRule_deletesIt() =
+ testScope.runTest {
+ whenever(notificationManager.automaticZenRules)
+ .thenReturn(
+ mutableMapOf(
+ Pair(
+ "gaming",
+ AutomaticZenRule.Builder(
+ "Gaming Mode",
+ Uri.parse(
+ "android-app://com.android.systemui/game-mode-dnd-controller"
+ ),
+ )
+ .setPackage("com.android.systemui")
+ .build(),
+ ),
+ Pair(
+ "other",
+ AutomaticZenRule.Builder("Other Mode", Uri.parse("something-else"))
+ .setPackage("com.other.package")
+ .build(),
+ ),
+ )
+ )
+
+ underTest.start()
+ runCurrent()
+
+ verify(notificationManager).removeAutomaticZenRule(eq("gaming"))
+ }
+
+ @Test
+ fun start_withoutGamingModeZenRule_doesNothing() =
+ testScope.runTest {
+ whenever(notificationManager.automaticZenRules)
+ .thenReturn(
+ mutableMapOf(
+ Pair(
+ "other",
+ AutomaticZenRule.Builder("Other Mode", Uri.parse("something-else"))
+ .setPackage("com.android.systemui")
+ .build(),
+ )
+ )
+ )
+
+ underTest.start()
+ runCurrent()
+
+ verify(notificationManager, never()).removeAutomaticZenRule(any())
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index ca5f49d..684ce48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -88,6 +88,7 @@
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.ZenModesCleanupStartable;
import dagger.Binds;
import dagger.Module;
@@ -299,4 +300,10 @@
ZenModeRepository repository) {
return new NotificationsSoundPolicyInteractor(repository);
}
+
+ /** Binds {@link ZenModesCleanupStartable} as a {@link CoreStartable}. */
+ @Binds
+ @IntoMap
+ @ClassKey(ZenModesCleanupStartable.class)
+ CoreStartable bindsZenModesCleanup(ZenModesCleanupStartable zenModesCleanup);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModesCleanupStartable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModesCleanupStartable.kt
new file mode 100644
index 0000000..32b476b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModesCleanupStartable.kt
@@ -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.systemui.statusbar.policy
+
+import android.app.NotificationManager
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.modes.shared.ModesUi
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * Cleanup task that deletes the obsolete "Gaming" AutomaticZenRule that was created by SystemUI in
+ * the faraway past, and still exists on some devices through upgrades or B&R.
+ */
+// TODO: b/372874878 - Remove this thing once it has run long enough
+class ZenModesCleanupStartable
+@Inject
+constructor(
+ @Application private val applicationCoroutineScope: CoroutineScope,
+ @Background private val bgContext: CoroutineContext,
+ val notificationManager: NotificationManager,
+) : CoreStartable {
+
+ override fun start() {
+ if (!ModesUi.isEnabled) {
+ return
+ }
+ applicationCoroutineScope.launch { deleteObsoleteGamingMode() }
+ }
+
+ private suspend fun deleteObsoleteGamingMode() {
+ withContext(bgContext) {
+ val allRules = notificationManager.automaticZenRules
+ val gamingModeEntry =
+ allRules.entries.firstOrNull { entry ->
+ entry.value.packageName == "com.android.systemui" &&
+ entry.value.conditionId?.toString() ==
+ "android-app://com.android.systemui/game-mode-dnd-controller"
+ }
+ if (gamingModeEntry != null) {
+ notificationManager.removeAutomaticZenRule(gamingModeEntry.key)
+ }
+ }
+ }
+}