summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/LaunchFullScreenIntentProvider.kt71
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java12
6 files changed, 139 insertions, 67 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
index 8a31ed9271ad..1e7e7f08a752 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
@@ -33,6 +33,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender.OnEndLifetimeExtensionCallback
+import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider
import com.android.systemui.statusbar.notification.collection.render.NodeController
import com.android.systemui.statusbar.notification.dagger.IncomingHeader
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
@@ -68,6 +69,7 @@ class HeadsUpCoordinator @Inject constructor(
private val mHeadsUpViewBinder: HeadsUpViewBinder,
private val mNotificationInterruptStateProvider: NotificationInterruptStateProvider,
private val mRemoteInputManager: NotificationRemoteInputManager,
+ private val mLaunchFullScreenIntentProvider: LaunchFullScreenIntentProvider,
@IncomingHeader private val mIncomingHeaderController: NodeController,
@Main private val mExecutor: DelayableExecutor,
) : Coordinator {
@@ -373,6 +375,12 @@ class HeadsUpCoordinator @Inject constructor(
* Notification was just added and if it should heads up, bind the view and then show it.
*/
override fun onEntryAdded(entry: NotificationEntry) {
+ // First check whether this notification should launch a full screen intent, and
+ // launch it if needed.
+ if (mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
+ mLaunchFullScreenIntentProvider.launchFullScreenIntent(entry)
+ }
+
// shouldHeadsUp includes check for whether this notification should be filtered
val shouldHeadsUpEver = mNotificationInterruptStateProvider.shouldHeadsUp(entry)
mPostedEntries[entry.key] = PostedEntry(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/LaunchFullScreenIntentProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/LaunchFullScreenIntentProvider.kt
new file mode 100644
index 000000000000..74ff78e25a2f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/LaunchFullScreenIntentProvider.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 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.notification.collection.provider
+
+import android.util.Log
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.util.ListenerSet
+import javax.inject.Inject
+
+/**
+ * A class that enables communication of decisions to launch a notification's full screen intent.
+ */
+@SysUISingleton
+class LaunchFullScreenIntentProvider @Inject constructor() {
+ companion object {
+ private const val TAG = "LaunchFullScreenIntentProvider"
+ }
+ private val listeners = ListenerSet<Listener>()
+
+ /**
+ * Registers a listener with this provider. These listeners will be alerted whenever a full
+ * screen intent should be launched for a notification entry.
+ */
+ fun registerListener(listener: Listener) {
+ listeners.addIfAbsent(listener)
+ }
+
+ /** Removes the specified listener. */
+ fun removeListener(listener: Listener) {
+ listeners.remove(listener)
+ }
+
+ /**
+ * Sends a request to launch full screen intent for the given notification entry to all
+ * registered listeners.
+ */
+ fun launchFullScreenIntent(entry: NotificationEntry) {
+ if (listeners.isEmpty()) {
+ // This should never happen, but we should definitely know if it does because having
+ // no listeners would indicate that FSIs are getting entirely dropped on the floor.
+ Log.wtf(TAG, "no listeners found when launchFullScreenIntent requested")
+ }
+ for (listener in listeners) {
+ listener.onFullScreenIntentRequested(entry)
+ }
+ }
+
+ /** Listener interface for passing full screen intent launch decisions. */
+ fun interface Listener {
+ /**
+ * Invoked whenever a full screen intent launch is requested for the given notification
+ * entry.
+ */
+ fun onFullScreenIntentRequested(entry: NotificationEntry)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 5cd2ba1b1cf3..b6ae4a088880 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -23,7 +23,6 @@ import static com.android.systemui.statusbar.phone.CentralSurfaces.getActivityOp
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
@@ -60,9 +59,8 @@ import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
-import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -126,7 +124,6 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
Context context,
Handler mainThreadHandler,
Executor uiBgExecutor,
- NotifPipeline notifPipeline,
NotificationVisibilityProvider visibilityProvider,
HeadsUpManagerPhone headsUpManager,
ActivityStarter activityStarter,
@@ -151,7 +148,8 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
NotificationPresenter presenter,
NotificationPanelViewController panel,
ActivityLaunchAnimator activityLaunchAnimator,
- NotificationLaunchAnimatorControllerProvider notificationAnimationProvider) {
+ NotificationLaunchAnimatorControllerProvider notificationAnimationProvider,
+ LaunchFullScreenIntentProvider launchFullScreenIntentProvider) {
mContext = context;
mMainThreadHandler = mainThreadHandler;
mUiBgExecutor = uiBgExecutor;
@@ -182,12 +180,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
mActivityLaunchAnimator = activityLaunchAnimator;
mNotificationAnimationProvider = notificationAnimationProvider;
- notifPipeline.addCollectionListener(new NotifCollectionListener() {
- @Override
- public void onEntryAdded(NotificationEntry entry) {
- handleFullScreenIntent(entry);
- }
- });
+ launchFullScreenIntentProvider.registerListener(entry -> launchFullScreenIntent(entry));
}
/**
@@ -549,38 +542,36 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
}
@VisibleForTesting
- void handleFullScreenIntent(NotificationEntry entry) {
- if (mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
- if (shouldSuppressFullScreenIntent(entry)) {
- mLogger.logFullScreenIntentSuppressedByDnD(entry);
- } else if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
- mLogger.logFullScreenIntentNotImportantEnough(entry);
- } else {
- // Stop screensaver if the notification has a fullscreen intent.
- // (like an incoming phone call)
- mUiBgExecutor.execute(() -> {
- try {
- mDreamManager.awaken();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- });
+ void launchFullScreenIntent(NotificationEntry entry) {
+ // Skip if device is in VR mode.
+ if (mPresenter.isDeviceInVrMode()) {
+ mLogger.logFullScreenIntentSuppressedByVR(entry);
+ return;
+ }
- // not immersive & a fullscreen alert should be shown
- final PendingIntent fullscreenIntent =
- entry.getSbn().getNotification().fullScreenIntent;
- mLogger.logSendingFullScreenIntent(entry, fullscreenIntent);
- try {
- EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
- entry.getKey());
- mCentralSurfaces.wakeUpForFullScreenIntent();
- fullscreenIntent.send();
- entry.notifyFullScreenIntentLaunched();
- mMetricsLogger.count("note_fullscreen", 1);
- } catch (PendingIntent.CanceledException e) {
- // ignore
- }
+ // Stop screensaver if the notification has a fullscreen intent.
+ // (like an incoming phone call)
+ mUiBgExecutor.execute(() -> {
+ try {
+ mDreamManager.awaken();
+ } catch (RemoteException e) {
+ e.printStackTrace();
}
+ });
+
+ // not immersive & a fullscreen alert should be shown
+ final PendingIntent fullscreenIntent =
+ entry.getSbn().getNotification().fullScreenIntent;
+ mLogger.logSendingFullScreenIntent(entry, fullscreenIntent);
+ try {
+ EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
+ entry.getKey());
+ mCentralSurfaces.wakeUpForFullScreenIntent();
+ fullscreenIntent.send();
+ entry.notifyFullScreenIntentLaunched();
+ mMetricsLogger.count("note_fullscreen", 1);
+ } catch (PendingIntent.CanceledException e) {
+ // ignore
}
}
@@ -607,12 +598,4 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
mMainThreadHandler.post(mShadeController::collapsePanel);
}
}
-
- private boolean shouldSuppressFullScreenIntent(NotificationEntry entry) {
- if (mPresenter.isDeviceInVrMode()) {
- return true;
- }
-
- return entry.shouldSuppressFullScreenIntent();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
index 81edff45c505..1f0b96a58da6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
@@ -96,19 +96,11 @@ class StatusBarNotificationActivityStarterLogger @Inject constructor(
})
}
- fun logFullScreenIntentSuppressedByDnD(entry: NotificationEntry) {
+ fun logFullScreenIntentSuppressedByVR(entry: NotificationEntry) {
buffer.log(TAG, DEBUG, {
str1 = entry.logKey
}, {
- "No Fullscreen intent: suppressed by DND: $str1"
- })
- }
-
- fun logFullScreenIntentNotImportantEnough(entry: NotificationEntry) {
- buffer.log(TAG, DEBUG, {
- str1 = entry.logKey
- }, {
- "No Fullscreen intent: not important enough: $str1"
+ "No Fullscreen intent: suppressed by VR mode: $str1"
})
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
index 3ff7639e9262..422720e4a1da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
@@ -34,6 +34,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender.OnEndLifetimeExtensionCallback
+import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider
import com.android.systemui.statusbar.notification.collection.render.NodeController
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider
@@ -86,6 +87,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
private val mRemoteInputManager: NotificationRemoteInputManager = mock()
private val mEndLifetimeExtension: OnEndLifetimeExtensionCallback = mock()
private val mHeaderController: NodeController = mock()
+ private val mLaunchFullScreenIntentProvider: LaunchFullScreenIntentProvider = mock()
private lateinit var mEntry: NotificationEntry
private lateinit var mGroupSummary: NotificationEntry
@@ -110,6 +112,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
mHeadsUpViewBinder,
mNotificationInterruptStateProvider,
mRemoteInputManager,
+ mLaunchFullScreenIntentProvider,
mHeaderController,
mExecutor)
mCoordinator.attach(mNotifPipeline)
@@ -242,6 +245,20 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
}
@Test
+ fun testOnEntryAdded_shouldFullScreen() {
+ setShouldFullScreen(mEntry)
+ mCollectionListener.onEntryAdded(mEntry)
+ verify(mLaunchFullScreenIntentProvider).launchFullScreenIntent(mEntry)
+ }
+
+ @Test
+ fun testOnEntryAdded_shouldNotFullScreen() {
+ setShouldFullScreen(mEntry, should = false)
+ mCollectionListener.onEntryAdded(mEntry)
+ verify(mLaunchFullScreenIntentProvider, never()).launchFullScreenIntent(any())
+ }
+
+ @Test
fun testPromotesAddedHUN() {
// GIVEN the current entry should heads up
whenever(mNotificationInterruptStateProvider.shouldHeadsUp(mEntry)).thenReturn(true)
@@ -755,6 +772,11 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
.thenReturn(should)
}
+ private fun setShouldFullScreen(entry: NotificationEntry, should: Boolean = true) {
+ whenever(mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+ .thenReturn(should)
+ }
+
private fun finishBind(entry: NotificationEntry) {
verify(mHeadsUpManager, never()).showNotification(entry)
withArgCaptor<BindCallback> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index c4098578197b..ce54d784520c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -67,8 +67,8 @@ import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
-import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -123,8 +123,6 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
@Mock
private ShadeControllerImpl mShadeController;
@Mock
- private NotifPipeline mNotifPipeline;
- @Mock
private NotificationVisibilityProvider mVisibilityProvider;
@Mock
private ActivityIntentHelper mActivityIntentHelper;
@@ -197,7 +195,6 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
getContext(),
mHandler,
mUiBgExecutor,
- mNotifPipeline,
mVisibilityProvider,
headsUpManager,
mActivityStarter,
@@ -222,7 +219,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
mock(NotificationPresenter.class),
mock(NotificationPanelViewController.class),
mActivityLaunchAnimator,
- notificationAnimationProvider
+ notificationAnimationProvider,
+ mock(LaunchFullScreenIntentProvider.class)
);
// set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg
@@ -384,11 +382,9 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
NotificationEntry entry = mock(NotificationEntry.class);
when(entry.getImportance()).thenReturn(NotificationManager.IMPORTANCE_HIGH);
when(entry.getSbn()).thenReturn(sbn);
- when(mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(eq(entry)))
- .thenReturn(true);
// WHEN
- mNotificationActivityStarter.handleFullScreenIntent(entry);
+ mNotificationActivityStarter.launchFullScreenIntent(entry);
// THEN display should try wake up for the full screen intent
verify(mCentralSurfaces).wakeUpForFullScreenIntent();