summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java157
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ActivityLaunchAnimCoordinator.kt95
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt81
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallback.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotifActivityLaunchEvents.kt39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotifActivityLaunchEventsModule.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java129
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt42
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java71
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ActivityLaunchAnimCoordinatorTest.kt138
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java119
26 files changed, 490 insertions, 618 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java
index 129fa5a7cc17..0c341cc92f83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.notification;
import android.content.Intent;
-import android.service.notification.StatusBarNotification;
import android.view.View;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -29,7 +28,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
*/
public interface NotificationActivityStarter {
/** Called when the user clicks on the surface of a notification. */
- void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row);
+ void onNotificationClicked(NotificationEntry entry, ExpandableNotificationRow row);
/** Called when the user clicks on a button in the notification guts which fires an intent. */
void startNotificationGutsIntent(Intent intent, int appUid,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
index 392145ad306a..c3ce593b54fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
@@ -104,7 +104,7 @@ public final class NotificationClicker implements View.OnClickListener {
mBubblesOptional.get().collapseStack();
}
- mNotificationActivityStarter.onNotificationClicked(entry.getSbn(), row);
+ mNotificationActivityStarter.onNotificationClicked(entry, row);
}
private boolean isMenuVisible(ExpandableNotificationRow row) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
index fbf033bd2291..ad3dfedcdb96 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
@@ -27,7 +27,7 @@ class NotificationClickerLogger @Inject constructor(
) {
fun logOnClick(entry: NotificationEntry) {
buffer.log(TAG, LogLevel.DEBUG, {
- str1 = entry.key
+ str1 = entry.logKey
str2 = entry.ranking.channel.id
}, {
"CLICK $str1 (channel=$str2)"
@@ -36,7 +36,7 @@ class NotificationClickerLogger @Inject constructor(
fun logMenuVisible(entry: NotificationEntry) {
buffer.log(TAG, LogLevel.DEBUG, {
- str1 = entry.key
+ str1 = entry.logKey
}, {
"Ignoring click on $str1; menu is visible"
})
@@ -44,7 +44,7 @@ class NotificationClickerLogger @Inject constructor(
fun logParentMenuVisible(entry: NotificationEntry) {
buffer.log(TAG, LogLevel.DEBUG, {
- str1 = entry.key
+ str1 = entry.logKey
}, {
"Ignoring click on $str1; parent menu is visible"
})
@@ -52,7 +52,7 @@ class NotificationClickerLogger @Inject constructor(
fun logChildrenExpanded(entry: NotificationEntry) {
buffer.log(TAG, LogLevel.DEBUG, {
- str1 = entry.key
+ str1 = entry.logKey
}, {
"Ignoring click on $str1; children are expanded"
})
@@ -60,7 +60,7 @@ class NotificationClickerLogger @Inject constructor(
fun logGutsExposed(entry: NotificationEntry) {
buffer.log(TAG, LogLevel.DEBUG, {
- str1 = entry.key
+ str1 = entry.logKey
}, {
"Ignoring click on $str1; guts are exposed"
})
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index c3cc97bc14a3..7cfb1571ccf0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -24,7 +24,8 @@ import android.widget.ImageView;
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.util.Compile;
/**
* A util class for various reusable functions
@@ -74,12 +75,18 @@ public class NotificationUtils {
return (int) (dimensionPixelSize * factor);
}
+ private static final boolean INCLUDE_HASH_CODE_IN_LIST_ENTRY_LOG_KEY = false;
+
/** Get the notification key, reformatted for logging, for the (optional) entry */
- public static String logKey(NotificationEntry entry) {
+ public static String logKey(ListEntry entry) {
if (entry == null) {
return "null";
}
- return logKey(entry.getKey());
+ if (Compile.IS_DEBUG && INCLUDE_HASH_CODE_IN_LIST_ENTRY_LOG_KEY) {
+ return logKey(entry.getKey()) + "@" + Integer.toHexString(entry.hashCode());
+ } else {
+ return logKey(entry.getKey());
+ }
}
/** Removes newlines from the notification key to prettify apps that have these in the tag */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
new file mode 100644
index 000000000000..432bac49fa9b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
@@ -0,0 +1,31 @@
+/*
+ * 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
+
+import android.service.notification.StatusBarNotification
+import com.android.systemui.statusbar.notification.collection.ListEntry
+
+/** Get the notification key, reformatted for logging, for the (optional) entry */
+val ListEntry?.logKey: String?
+ get() = this?.let { NotificationUtils.logKey(it) }
+
+/** Get the notification key, reformatted for logging, for the (optional) sbn */
+val StatusBarNotification?.logKey: String?
+ get() = this?.key?.let { NotificationUtils.logKey(it) }
+
+/** Removes newlines from the notification key to prettify apps that have these in the tag */
+fun logKey(key: String?): String? = NotificationUtils.logKey(key) \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index bcd8e594ffbd..6085096ee124 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -18,9 +18,12 @@ package com.android.systemui.statusbar.notification.collection;
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
+import static android.service.notification.NotificationListenerService.REASON_ASSISTANT_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
import static android.service.notification.NotificationListenerService.REASON_CHANNEL_BANNED;
+import static android.service.notification.NotificationListenerService.REASON_CHANNEL_REMOVED;
+import static android.service.notification.NotificationListenerService.REASON_CLEAR_DATA;
import static android.service.notification.NotificationListenerService.REASON_CLICK;
import static android.service.notification.NotificationListenerService.REASON_ERROR;
import static android.service.notification.NotificationListenerService.REASON_GROUP_OPTIMIZATION;
@@ -36,9 +39,11 @@ import static android.service.notification.NotificationListenerService.REASON_TI
import static android.service.notification.NotificationListenerService.REASON_UNAUTOBUNDLED;
import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
+import static com.android.systemui.statusbar.notification.NotificationUtils.logKey;
import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.DISMISSED;
import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.NOT_DISMISSED;
import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.PARENT_DISMISSED;
+import static com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLoggerKt.cancellationReasonDebugString;
import static java.util.Objects.requireNonNull;
@@ -99,6 +104,7 @@ import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -143,6 +149,7 @@ public class NotifCollection implements Dumpable {
private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
private final Collection<NotificationEntry> mReadOnlyNotificationSet =
Collections.unmodifiableCollection(mNotificationSet.values());
+ private final HashMap<String, FutureDismissal> mFutureDismissals = new HashMap<>();
@Nullable private CollectionReadyForBuildListener mBuildListener;
private final List<NotifCollectionListener> mNotifCollectionListeners = new ArrayList<>();
@@ -511,6 +518,7 @@ public class NotifCollection implements Dumpable {
cancelDismissInterception(entry);
mEventQueue.add(new EntryRemovedEvent(entry, entry.mCancellationReason));
mEventQueue.add(new CleanUpEntryEvent(entry));
+ handleFutureDismissal(entry);
return true;
} else {
return false;
@@ -519,31 +527,32 @@ public class NotifCollection implements Dumpable {
/**
* Get the group summary entry
- * @param group
+ * @param groupKey
* @return
*/
@Nullable
- public NotificationEntry getGroupSummary(String group) {
+ public NotificationEntry getGroupSummary(String groupKey) {
return mNotificationSet
.values()
.stream()
- .filter(it -> Objects.equals(it.getSbn().getGroup(), group))
+ .filter(it -> Objects.equals(it.getSbn().getGroupKey(), groupKey))
.filter(it -> it.getSbn().getNotification().isGroupSummary())
.findFirst().orElse(null);
}
/**
- * Checks if the entry is the only child in the logical group
- * @param entry
- * @return
+ * Checks if the entry is the only child in the logical group;
+ * it need not have a summary to qualify
+ *
+ * @param entry the entry to check
*/
public boolean isOnlyChildInGroup(NotificationEntry entry) {
- String group = entry.getSbn().getGroup();
+ String groupKey = entry.getSbn().getGroupKey();
return mNotificationSet.get(entry.getKey()) == entry
&& mNotificationSet
.values()
.stream()
- .filter(it -> Objects.equals(it.getSbn().getGroup(), group))
+ .filter(it -> Objects.equals(it.getSbn().getGroupKey(), groupKey))
.filter(it -> !it.getSbn().getNotification().isGroupSummary())
.count() == 1;
}
@@ -916,10 +925,139 @@ public class NotifCollection implements Dumpable {
dispatchEventsAndRebuildList();
}
+ /**
+ * A method to alert the collection that an async operation is happening, at the end of which a
+ * dismissal request will be made. This method has the additional guarantee that if a parent
+ * notification exists for a single child, then that notification will also be dismissed.
+ *
+ * The runnable returned must be run at the end of the async operation to enact the cancellation
+ *
+ * @param entry the notification we want to dismiss
+ * @param cancellationReason the reason for the cancellation
+ * @param statsCreator the callback for generating the stats for an entry
+ * @return the runnable to be run when the dismissal is ready to happen
+ */
+ public Runnable registerFutureDismissal(NotificationEntry entry, int cancellationReason,
+ DismissedByUserStatsCreator statsCreator) {
+ FutureDismissal dismissal = mFutureDismissals.get(entry.getKey());
+ if (dismissal != null) {
+ mLogger.logFutureDismissalReused(dismissal);
+ return dismissal;
+ }
+ dismissal = new FutureDismissal(entry, cancellationReason, statsCreator);
+ mFutureDismissals.put(entry.getKey(), dismissal);
+ mLogger.logFutureDismissalRegistered(dismissal);
+ return dismissal;
+ }
+
+ private void handleFutureDismissal(NotificationEntry entry) {
+ final FutureDismissal futureDismissal = mFutureDismissals.remove(entry.getKey());
+ if (futureDismissal != null) {
+ futureDismissal.onSystemServerCancel(entry.mCancellationReason);
+ }
+ }
+
+ /** A single method interface that callers can pass in when registering future dismissals */
+ public interface DismissedByUserStatsCreator {
+ DismissedByUserStats createDismissedByUserStats(NotificationEntry entry);
+ }
+
+ /** A class which tracks the double dismissal events coming in from both the system server and
+ * the ui */
+ public class FutureDismissal implements Runnable {
+ private final NotificationEntry mEntry;
+ private final DismissedByUserStatsCreator mStatsCreator;
+ @Nullable
+ private final NotificationEntry mSummaryToDismiss;
+ private final String mLabel;
+
+ private boolean mDidRun;
+ private boolean mDidSystemServerCancel;
+
+ private FutureDismissal(NotificationEntry entry, @CancellationReason int cancellationReason,
+ DismissedByUserStatsCreator statsCreator) {
+ mEntry = entry;
+ mStatsCreator = statsCreator;
+ mSummaryToDismiss = fetchSummaryToDismiss(entry);
+ mLabel = "<FutureDismissal@" + Integer.toHexString(hashCode())
+ + " entry=" + logKey(mEntry)
+ + " reason=" + cancellationReasonDebugString(cancellationReason)
+ + " summary=" + logKey(mSummaryToDismiss)
+ + ">";
+ }
+
+ @Nullable
+ private NotificationEntry fetchSummaryToDismiss(NotificationEntry entry) {
+ if (isOnlyChildInGroup(entry)) {
+ String group = entry.getSbn().getGroupKey();
+ NotificationEntry summary = getGroupSummary(group);
+ if (summary != null && summary.isDismissable()) return summary;
+ }
+ return null;
+ }
+
+ /** called when the entry has been removed from the collection */
+ public void onSystemServerCancel(@CancellationReason int cancellationReason) {
+ Assert.isMainThread();
+ if (mDidSystemServerCancel) {
+ mLogger.logFutureDismissalDoubleCancelledByServer(this);
+ return;
+ }
+ mLogger.logFutureDismissalGotSystemServerCancel(this, cancellationReason);
+ mDidSystemServerCancel = true;
+ // TODO: Internally dismiss the summary now instead of waiting for onUiCancel
+ }
+
+ private void onUiCancel() {
+ mFutureDismissals.remove(mEntry.getKey());
+ final NotificationEntry currentEntry = getEntry(mEntry.getKey());
+ // generate stats for the entry before dismissing summary, which could affect state
+ final DismissedByUserStats stats = mStatsCreator.createDismissedByUserStats(mEntry);
+ // dismiss the summary (if it exists)
+ if (mSummaryToDismiss != null) {
+ final NotificationEntry currentSummary = getEntry(mSummaryToDismiss.getKey());
+ if (currentSummary == mSummaryToDismiss) {
+ mLogger.logFutureDismissalDismissing(this, "summary");
+ dismissNotification(mSummaryToDismiss,
+ mStatsCreator.createDismissedByUserStats(mSummaryToDismiss));
+ } else {
+ mLogger.logFutureDismissalMismatchedEntry(this, "summary", currentSummary);
+ }
+ }
+ // dismiss this entry (if it is still around)
+ if (mDidSystemServerCancel) {
+ mLogger.logFutureDismissalAlreadyCancelledByServer(this);
+ } else if (currentEntry == mEntry) {
+ mLogger.logFutureDismissalDismissing(this, "entry");
+ dismissNotification(mEntry, stats);
+ } else {
+ mLogger.logFutureDismissalMismatchedEntry(this, "entry", currentEntry);
+ }
+ }
+
+ /** called when the dismissal should be completed */
+ @Override
+ public void run() {
+ Assert.isMainThread();
+ if (mDidRun) {
+ mLogger.logFutureDismissalDoubleRun(this);
+ return;
+ }
+ mDidRun = true;
+ onUiCancel();
+ }
+
+ /** provides a debug label for this instance */
+ public String getLabel() {
+ return mLabel;
+ }
+ }
+
@IntDef(prefix = { "REASON_" }, value = {
REASON_NOT_CANCELED,
REASON_UNKNOWN,
REASON_CLICK,
+ REASON_CANCEL,
REASON_CANCEL_ALL,
REASON_ERROR,
REASON_PACKAGE_CHANGED,
@@ -937,6 +1075,9 @@ public class NotifCollection implements Dumpable {
REASON_CHANNEL_BANNED,
REASON_SNOOZED,
REASON_TIMEOUT,
+ REASON_CHANNEL_REMOVED,
+ REASON_CLEAR_DATA,
+ REASON_ASSISTANT_CANCEL,
})
@Retention(RetentionPolicy.SOURCE)
public @interface CancellationReason {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ActivityLaunchAnimCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ActivityLaunchAnimCoordinator.kt
deleted file mode 100644
index b54163d29e80..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ActivityLaunchAnimCoordinator.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.coordinator
-
-import com.android.systemui.statusbar.notification.collection.NotifPipeline
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender.OnEndLifetimeExtensionCallback
-import com.android.systemui.statusbar.phone.NotifActivityLaunchEvents
-import dagger.Binds
-import dagger.Module
-import javax.inject.Inject
-
-/** Extends the lifetime of notifications while their activity launch animation is playing. */
-interface ActivityLaunchAnimCoordinator : Coordinator
-
-/** Provides an [ActivityLaunchAnimCoordinator] to [CoordinatorScope]. */
-@Module(includes = [PrivateActivityStarterCoordinatorModule::class])
-object ActivityLaunchAnimCoordinatorModule
-
-@Module
-private interface PrivateActivityStarterCoordinatorModule {
- @Binds
- fun bindCoordinator(impl: ActivityLaunchAnimCoordinatorImpl): ActivityLaunchAnimCoordinator
-}
-
-/**
- * Listens for [NotifActivityLaunchEvents], and then extends the lifetimes of any notifs while their
- * launch animation is playing.
- */
-@CoordinatorScope
-private class ActivityLaunchAnimCoordinatorImpl @Inject constructor(
- private val activityLaunchEvents: NotifActivityLaunchEvents
-) : ActivityLaunchAnimCoordinator {
- // Tracks notification launches, and whether or not their lifetimes are extended.
- private val notifsLaunchingActivities = mutableMapOf<String, Boolean>()
-
- private var onEndLifetimeExtensionCallback: OnEndLifetimeExtensionCallback? = null
-
- override fun attach(pipeline: NotifPipeline) {
- activityLaunchEvents.registerListener(activityStartEventListener)
- pipeline.addNotificationLifetimeExtender(extender)
- }
-
- private val activityStartEventListener = object : NotifActivityLaunchEvents.Listener {
- override fun onStartLaunchNotifActivity(entry: NotificationEntry) {
- notifsLaunchingActivities[entry.key] = false
- }
-
- override fun onFinishLaunchNotifActivity(entry: NotificationEntry) {
- if (notifsLaunchingActivities.remove(entry.key) == true) {
- // If we were extending the lifetime of this notification, stop.
- onEndLifetimeExtensionCallback?.onEndLifetimeExtension(extender, entry)
- }
- }
- }
-
- private val extender = object : NotifLifetimeExtender {
- override fun getName(): String = "ActivityStarterCoordinator"
-
- override fun setCallback(callback: OnEndLifetimeExtensionCallback) {
- onEndLifetimeExtensionCallback = callback
- }
-
- override fun maybeExtendLifetime(entry: NotificationEntry, reason: Int): Boolean {
- if (entry.key in notifsLaunchingActivities) {
- // Track that we're now extending this notif
- notifsLaunchingActivities[entry.key] = true
- return true
- }
- return false
- }
-
- override fun cancelLifetimeExtension(entry: NotificationEntry) {
- if (entry.key in notifsLaunchingActivities) {
- notifsLaunchingActivities[entry.key] = false
- }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
index b24d2922adfb..0b3a0dc9dd58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
@@ -56,7 +56,6 @@ class NotifCoordinatorsImpl @Inject constructor(
smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
viewConfigCoordinator: ViewConfigCoordinator,
visualStabilityCoordinator: VisualStabilityCoordinator,
- activityLaunchAnimCoordinator: ActivityLaunchAnimCoordinator
) : NotifCoordinators {
private val mCoordinators: MutableList<Coordinator> = ArrayList()
@@ -93,7 +92,6 @@ class NotifCoordinatorsImpl @Inject constructor(
mCoordinators.add(shadeEventCoordinator)
mCoordinators.add(viewConfigCoordinator)
mCoordinators.add(visualStabilityCoordinator)
- mCoordinators.add(activityLaunchAnimCoordinator)
if (notifPipelineFlags.isSmartspaceDedupingEnabled()) {
mCoordinators.add(smartspaceDedupingCoordinator)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt
index 8ecffcb7670a..839cf0d7ef92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.notification.collection.coordinator.dagger
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.collection.coordinator.ActivityLaunchAnimCoordinatorModule
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinatorsImpl
import dagger.Binds
@@ -48,7 +47,6 @@ interface CoordinatorsSubcomponent {
}
@Module(includes = [
- ActivityLaunchAnimCoordinatorModule::class,
])
private abstract class InternalCoordinatorsModule {
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java
index 3bd91b5c8480..7dd3672a6e30 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java
@@ -18,17 +18,17 @@ package com.android.systemui.statusbar.notification.collection.inflation;
import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
-import android.annotation.Nullable;
import android.os.SystemClock;
-import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationStats;
+import androidx.annotation.NonNull;
+
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.coordinator.VisualStabilityCoordinator;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
-import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -43,54 +43,33 @@ public class OnUserInteractionCallbackImpl implements OnUserInteractionCallback
private final HeadsUpManager mHeadsUpManager;
private final StatusBarStateController mStatusBarStateController;
private final VisualStabilityCoordinator mVisualStabilityCoordinator;
- private final GroupMembershipManager mGroupMembershipManager;
public OnUserInteractionCallbackImpl(
NotificationVisibilityProvider visibilityProvider,
NotifCollection notifCollection,
HeadsUpManager headsUpManager,
StatusBarStateController statusBarStateController,
- VisualStabilityCoordinator visualStabilityCoordinator,
- GroupMembershipManager groupMembershipManager
+ VisualStabilityCoordinator visualStabilityCoordinator
) {
mVisibilityProvider = visibilityProvider;
mNotifCollection = notifCollection;
mHeadsUpManager = headsUpManager;
mStatusBarStateController = statusBarStateController;
mVisualStabilityCoordinator = visualStabilityCoordinator;
- mGroupMembershipManager = groupMembershipManager;
}
- /**
- * Callback triggered when a user:
- * 1. Manually dismisses a notification {@see ExpandableNotificationRow}.
- * 2. Clicks on a notification with flag {@link android.app.Notification#FLAG_AUTO_CANCEL}.
- * {@see StatusBarNotificationActivityStarter}
- */
- @Override
- public void onDismiss(
- NotificationEntry entry,
- @NotificationListenerService.NotificationCancelReason int cancellationReason,
- @Nullable NotificationEntry groupSummaryToDismiss
- ) {
+ @NonNull
+ private DismissedByUserStats getDismissedByUserStats(NotificationEntry entry) {
int dismissalSurface = NotificationStats.DISMISSAL_SHADE;
if (mHeadsUpManager.isAlerting(entry.getKey())) {
dismissalSurface = NotificationStats.DISMISSAL_PEEK;
} else if (mStatusBarStateController.isDozing()) {
dismissalSurface = NotificationStats.DISMISSAL_AOD;
}
-
- if (groupSummaryToDismiss != null) {
- onDismiss(groupSummaryToDismiss, cancellationReason, null);
- }
-
- mNotifCollection.dismissNotification(
- entry,
- new DismissedByUserStats(
- dismissalSurface,
- DISMISS_SENTIMENT_NEUTRAL,
- mVisibilityProvider.obtain(entry, true))
- );
+ return new DismissedByUserStats(
+ dismissalSurface,
+ DISMISS_SENTIMENT_NEUTRAL,
+ mVisibilityProvider.obtain(entry, true));
}
@Override
@@ -100,19 +79,11 @@ public class OnUserInteractionCallbackImpl implements OnUserInteractionCallback
SystemClock.uptimeMillis());
}
- /**
- * @param entry that is being dismissed
- * @return the group summary to dismiss along with this entry if this is the last entry in
- * the group. Else, returns null.
- */
+ @NonNull
@Override
- @Nullable
- public NotificationEntry getGroupSummaryToDismiss(NotificationEntry entry) {
- String group = entry.getSbn().getGroup();
- if (mNotifCollection.isOnlyChildInGroup(entry)) {
- NotificationEntry summary = mNotifCollection.getGroupSummary(group);
- if (summary != null && summary.isDismissable()) return summary;
- }
- return null;
+ public Runnable registerFutureDismissal(@NonNull NotificationEntry entry,
+ @CancellationReason int cancellationReason) {
+ return mNotifCollection.registerFutureDismissal(
+ entry, cancellationReason, this::getDismissedByUserStats);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java
index 8daf8be0cc8f..103b14b09e9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java
@@ -18,12 +18,15 @@ package com.android.systemui.statusbar.notification.collection.legacy;
import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
-import android.annotation.Nullable;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationStats;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
@@ -68,8 +71,7 @@ public class OnUserInteractionCallbackImplLegacy implements OnUserInteractionCal
* along with this dismissal. If null, does not additionally
* dismiss any notifications.
*/
- @Override
- public void onDismiss(
+ private void onDismiss(
NotificationEntry entry,
@NotificationListenerService.NotificationCancelReason int cancellationReason,
@Nullable NotificationEntry groupSummaryToDismiss
@@ -106,14 +108,21 @@ public class OnUserInteractionCallbackImplLegacy implements OnUserInteractionCal
* @return the group summary to dismiss along with this entry if this is the last entry in
* the group. Else, returns null.
*/
- @Override
@Nullable
- public NotificationEntry getGroupSummaryToDismiss(NotificationEntry entry) {
+ private NotificationEntry getGroupSummaryToDismiss(NotificationEntry entry) {
if (mGroupMembershipManager.isOnlyChildInGroup(entry)) {
NotificationEntry groupSummary = mGroupMembershipManager.getLogicalGroupSummary(entry);
return groupSummary.isDismissable() ? groupSummary : null;
}
return null;
}
+
+ @Override
+ @NonNull
+ public Runnable registerFutureDismissal(@NonNull NotificationEntry entry,
+ @CancellationReason int cancellationReason) {
+ NotificationEntry groupSummaryToDismiss = getGroupSummaryToDismiss(entry);
+ return () -> onDismiss(entry, cancellationReason, groupSummaryToDismiss);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
index 7302de57e955..7e7936717b84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
@@ -28,7 +28,9 @@ import com.android.systemui.log.LogLevel.WTF
import com.android.systemui.log.dagger.NotificationLog
import com.android.systemui.statusbar.notification.collection.NotifCollection
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason
+import com.android.systemui.statusbar.notification.collection.NotifCollection.FutureDismissal
import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
fun cancellationReasonDebugString(@CancellationReason reason: Int) =
@@ -36,6 +38,7 @@ fun cancellationReasonDebugString(@CancellationReason reason: Int) =
-1 -> "REASON_NOT_CANCELED" // NotifCollection.REASON_NOT_CANCELED
NotifCollection.REASON_UNKNOWN -> "REASON_UNKNOWN"
NotificationListenerService.REASON_CLICK -> "REASON_CLICK"
+ NotificationListenerService.REASON_CANCEL -> "REASON_CANCEL"
NotificationListenerService.REASON_CANCEL_ALL -> "REASON_CANCEL_ALL"
NotificationListenerService.REASON_ERROR -> "REASON_ERROR"
NotificationListenerService.REASON_PACKAGE_CHANGED -> "REASON_PACKAGE_CHANGED"
@@ -53,6 +56,9 @@ fun cancellationReasonDebugString(@CancellationReason reason: Int) =
NotificationListenerService.REASON_CHANNEL_BANNED -> "REASON_CHANNEL_BANNED"
NotificationListenerService.REASON_SNOOZED -> "REASON_SNOOZED"
NotificationListenerService.REASON_TIMEOUT -> "REASON_TIMEOUT"
+ NotificationListenerService.REASON_CHANNEL_REMOVED -> "REASON_CHANNEL_REMOVED"
+ NotificationListenerService.REASON_CLEAR_DATA -> "REASON_CLEAR_DATA"
+ NotificationListenerService.REASON_ASSISTANT_CANCEL -> "REASON_ASSISTANT_CANCEL"
else -> "unknown"
}
@@ -241,6 +247,81 @@ class NotifCollectionLogger @Inject constructor(
"ERROR suppressed due to initialization forgiveness: $str1"
})
}
+
+ fun logFutureDismissalReused(dismissal: FutureDismissal) {
+ buffer.log(TAG, INFO, {
+ str1 = dismissal.label
+ }, {
+ "Reusing existing registration: $str1"
+ })
+ }
+
+ fun logFutureDismissalRegistered(dismissal: FutureDismissal) {
+ buffer.log(TAG, DEBUG, {
+ str1 = dismissal.label
+ }, {
+ "Registered: $str1"
+ })
+ }
+
+ fun logFutureDismissalDoubleCancelledByServer(dismissal: FutureDismissal) {
+ buffer.log(TAG, WARNING, {
+ str1 = dismissal.label
+ }, {
+ "System server double cancelled: $str1"
+ })
+ }
+
+ fun logFutureDismissalDoubleRun(dismissal: FutureDismissal) {
+ buffer.log(TAG, WARNING, {
+ str1 = dismissal.label
+ }, {
+ "Double run: $str1"
+ })
+ }
+
+ fun logFutureDismissalAlreadyCancelledByServer(dismissal: FutureDismissal) {
+ buffer.log(TAG, DEBUG, {
+ str1 = dismissal.label
+ }, {
+ "Ignoring: entry already cancelled by server: $str1"
+ })
+ }
+
+ fun logFutureDismissalGotSystemServerCancel(
+ dismissal: FutureDismissal,
+ @CancellationReason cancellationReason: Int
+ ) {
+ buffer.log(TAG, DEBUG, {
+ str1 = dismissal.label
+ int1 = cancellationReason
+ }, {
+ "SystemServer cancelled: $str1 reason=${cancellationReasonDebugString(int1)}"
+ })
+ }
+
+ fun logFutureDismissalDismissing(dismissal: FutureDismissal, type: String) {
+ buffer.log(TAG, DEBUG, {
+ str1 = dismissal.label
+ str2 = type
+ }, {
+ "Dismissing $str2 for: $str1"
+ })
+ }
+
+ fun logFutureDismissalMismatchedEntry(
+ dismissal: FutureDismissal,
+ type: String,
+ latestEntry: NotificationEntry?
+ ) {
+ buffer.log(TAG, WARNING, {
+ str1 = dismissal.label
+ str2 = type
+ str3 = latestEntry.logKey
+ }, {
+ "Mismatch: current $str2 is $str3 for: $str1"
+ })
+ }
}
private const val TAG = "NotifCollection"
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 d96590a82547..c9c7fe9e0ab6 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,7 +88,6 @@ import com.android.systemui.statusbar.notification.stack.NotificationSectionsMan
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotifActivityLaunchEventsModule;
import com.android.systemui.statusbar.phone.NotifPanelEventsModule;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -111,7 +110,6 @@ import dagger.Provides;
@Module(includes = {
CoordinatorsModule.class,
KeyguardNotificationVisibilityProviderModule.class,
- NotifActivityLaunchEventsModule.class,
NotifPanelEventsModule.class,
NotifPipelineChoreographerModule.class,
NotificationSectionHeadersModule.class,
@@ -350,8 +348,7 @@ public interface NotificationsModule {
notifCollection.get(),
headsUpManager,
statusBarStateController,
- visualStabilityCoordinator.get(),
- groupMembershipManagerLazy.get())
+ visualStabilityCoordinator.get())
: new OnUserInteractionCallbackImplLegacy(
entryManager,
visibilityProvider.get(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index f975799b4b85..d5088acaa61c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.notification.row;
import static android.app.Notification.Action.SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY;
-import static android.os.UserHandle.USER_SYSTEM;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
@@ -34,8 +33,6 @@ import android.app.Notification;
import android.app.NotificationChannel;
import android.app.role.RoleManager;
import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
@@ -51,7 +48,6 @@ import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.Trace;
-import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import android.util.AttributeSet;
@@ -113,7 +109,6 @@ import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.SwipeableView;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
@@ -1428,8 +1423,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
dismiss(fromAccessibility);
if (mEntry.isDismissable()) {
if (mOnUserInteractionCallback != null) {
- mOnUserInteractionCallback.onDismiss(mEntry, REASON_CANCEL,
- mOnUserInteractionCallback.getGroupSummaryToDismiss(mEntry));
+ mOnUserInteractionCallback.registerFutureDismissal(mEntry, REASON_CANCEL).run();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallback.java
index 94c5507cfbf4..98d43539841d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallback.java
@@ -16,8 +16,9 @@
package com.android.systemui.statusbar.notification.row;
-import android.service.notification.NotificationListenerService;
+import androidx.annotation.NonNull;
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
/**
@@ -26,29 +27,23 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
public interface OnUserInteractionCallback {
/**
- * Handle a user interaction that triggers a notification dismissal. Called when a user clicks
- * on an auto-cancelled notification or manually swipes to dismiss the notification.
- *
- * @param entry notification being dismissed
- * @param cancellationReason reason for the cancellation
- * @param groupSummaryToDismiss group summary to dismiss with `entry`.
- */
- void onDismiss(
- NotificationEntry entry,
- @NotificationListenerService.NotificationCancelReason int cancellationReason,
- NotificationEntry groupSummaryToDismiss);
-
- /**
* Triggered after a user has changed the importance of the notification via its
* {@link NotificationGuts}.
*/
void onImportanceChanged(NotificationEntry entry);
-
/**
- * @param entry being dismissed by the user
- * @return group summary that should be dismissed along with `entry`. Can be null if no
- * relevant group summary exists or the group summary should not be dismissed with `entry`.
+ * Called once it is known that a dismissal will take place for the given reason.
+ * This returns a Runnable which MUST be invoked when the dismissal is ready to be completed.
+ *
+ * Registering for future dismissal is typically done before notifying the NMS that a
+ * notification was clicked or dismissed, but the local dismissal may happen later.
+ *
+ * @param entry the entry being cancelled
+ * @param cancellationReason the reason for the cancellation
+ * @return the runnable to call when the dismissal can happen
*/
- NotificationEntry getGroupSummaryToDismiss(NotificationEntry entry);
+ @NonNull
+ Runnable registerFutureDismissal(@NonNull NotificationEntry entry,
+ @CancellationReason int cancellationReason);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotifActivityLaunchEvents.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotifActivityLaunchEvents.kt
deleted file mode 100644
index f46d07338206..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotifActivityLaunchEvents.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.phone
-
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-
-/** Provides events about [android.app.Activity] launches from Notifications. */
-interface NotifActivityLaunchEvents {
-
- /** Registers a [Listener] to be invoked when notification activity launch events occur. */
- fun registerListener(listener: Listener)
-
- /** Unregisters a [Listener] previously registered via [registerListener] */
- fun unregisterListener(listener: Listener)
-
- /** Listener for events about [android.app.Activity] launches from Notifications. */
- interface Listener {
-
- /** Invoked when an activity has started launching from a notification. */
- fun onStartLaunchNotifActivity(entry: NotificationEntry)
-
- /** Invoked when an activity has finished launching. */
- fun onFinishLaunchNotifActivity(entry: NotificationEntry)
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotifActivityLaunchEventsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotifActivityLaunchEventsModule.java
deleted file mode 100644
index 84ff538677b0..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotifActivityLaunchEventsModule.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.phone;
-
-import com.android.systemui.dagger.SysUISingleton;
-
-import dagger.Binds;
-import dagger.Module;
-
-/** Provides a {@link NotifActivityLaunchEvents} in {@link SysUISingleton} scope. */
-@Module
-public abstract class NotifActivityLaunchEventsModule {
- @Binds
- abstract NotifActivityLaunchEvents bindLaunchEvents(
- StatusBarNotificationActivityStarter.LaunchEventsEmitter impl);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index f15ea627af47..314ab2221b19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -3377,9 +3377,9 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
public void setIsLaunchAnimationRunning(boolean running) {
- boolean wasRunning = isLaunchTransitionRunning();
+ boolean wasRunning = mIsLaunchAnimationRunning;
super.setIsLaunchAnimationRunning(running);
- if (wasRunning != isLaunchTransitionRunning()) {
+ if (wasRunning != mIsLaunchAnimationRunning) {
mPanelEventsEmitter.notifyLaunchingActivityChanged(running);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
index 56b6dfc42ee3..c0922163903f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
@@ -20,7 +20,9 @@ class StatusBarLaunchAnimatorController(
override fun onIntentStarted(willAnimate: Boolean) {
delegate.onIntentStarted(willAnimate)
- if (!willAnimate) {
+ if (willAnimate) {
+ centralSurfaces.notificationPanelViewController.setIsLaunchAnimationRunning(true)
+ } else {
centralSurfaces.collapsePanelOnMainThread()
}
}
@@ -51,6 +53,7 @@ class StatusBarLaunchAnimatorController(
override fun onLaunchAnimationCancelled() {
delegate.onLaunchAnimationCancelled()
+ centralSurfaces.notificationPanelViewController.setIsLaunchAnimationRunning(false)
centralSurfaces.onLaunchAnimationCancelled(isLaunchForActivity)
}
} \ No newline at end of file
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 87ca942edff2..cf776e3b60d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -41,7 +41,6 @@ import android.text.TextUtils;
import android.util.EventLog;
import android.view.View;
-import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
@@ -52,7 +51,6 @@ import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.EventLogTags;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.assist.AssistManager;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
@@ -77,7 +75,6 @@ import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.ListenerSet;
import com.android.systemui.wmshell.BubblesManager;
import java.util.Optional;
@@ -131,7 +128,6 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
private final ActivityLaunchAnimator mActivityLaunchAnimator;
private final NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
private final OnUserInteractionCallback mOnUserInteractionCallback;
- private final LaunchEventsEmitter mLaunchEventsEmitter;
private boolean mIsCollapsingToShowActivityOverLockscreen;
@@ -170,8 +166,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
NotificationPresenter presenter,
NotificationPanelViewController panel,
ActivityLaunchAnimator activityLaunchAnimator,
- NotificationLaunchAnimatorControllerProvider notificationAnimationProvider,
- LaunchEventsEmitter launchEventsEmitter) {
+ NotificationLaunchAnimatorControllerProvider notificationAnimationProvider) {
mContext = context;
mCommandQueue = commandQueue;
mMainThreadHandler = mainThreadHandler;
@@ -207,7 +202,6 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
mNotificationPanel = panel;
mActivityLaunchAnimator = activityLaunchAnimator;
mNotificationAnimationProvider = notificationAnimationProvider;
- mLaunchEventsEmitter = launchEventsEmitter;
if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@@ -229,14 +223,13 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
/**
* Called when a notification is clicked.
*
- * @param sbn notification that was clicked
+ * @param entry notification that was clicked
* @param row row for that notification
*/
@Override
- public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) {
- mLogger.logStartingActivityFromClick(sbn.getKey());
+ public void onNotificationClicked(NotificationEntry entry, ExpandableNotificationRow row) {
+ mLogger.logStartingActivityFromClick(entry);
- final NotificationEntry entry = row.getEntry();
if (mRemoteInputManager.isRemoteInputActive(entry)
&& !TextUtils.isEmpty(row.getActiveRemoteInputText())) {
// We have an active remote input typed and the user clicked on the notification.
@@ -244,7 +237,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
mRemoteInputManager.closeRemoteInputs();
return;
}
- Notification notification = sbn.getNotification();
+ Notification notification = entry.getSbn().getNotification();
final PendingIntent intent = notification.contentIntent != null
? notification.contentIntent
: notification.fullScreenIntent;
@@ -254,12 +247,10 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
// The only valid case is Bubble notifications. Guard against other cases
// entering here.
if (intent == null && !isBubble) {
- mLogger.logNonClickableNotification(sbn.getKey());
+ mLogger.logNonClickableNotification(entry);
return;
}
- mLaunchEventsEmitter.notifyStartLaunchNotifActivity(entry);
-
boolean isActivityIntent = intent != null && intent.isActivity() && !isBubble;
final boolean willLaunchResolverActivity = isActivityIntent
&& mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
@@ -287,7 +278,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
} else {
mActivityStarter.dismissKeyguardThenExecute(
postKeyguardAction,
- () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry),
+ null,
willLaunchResolverActivity);
}
}
@@ -299,7 +290,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
boolean isActivityIntent,
boolean animate,
boolean showOverLockscreen) {
- mLogger.logHandleClickAfterKeyguardDismissed(entry.getKey());
+ mLogger.logHandleClickAfterKeyguardDismissed(entry);
final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
entry, row, intent, isActivityIntent, animate);
@@ -326,7 +317,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
boolean isActivityIntent,
boolean animate) {
String notificationKey = entry.getKey();
- mLogger.logHandleClickAfterPanelCollapsed(notificationKey);
+ mLogger.logHandleClickAfterPanelCollapsed(entry);
try {
// The intent we are sending is for the application, which
@@ -367,11 +358,9 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
}
final boolean canBubble = entry.canBubble();
if (canBubble) {
- mLogger.logExpandingBubble(notificationKey);
+ mLogger.logExpandingBubble(entry);
removeHunAfterClick(row);
expandBubbleStackOnMainThread(entry);
- mMainThreadHandler.post(
- () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry));
} else {
startNotificationIntent(intent, fillInIntent, entry, row, animate, isActivityIntent);
}
@@ -381,30 +370,13 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
final NotificationVisibility nv = mVisibilityProvider.obtain(entry, true);
- // retrieve the group summary to remove with this entry before we tell NMS the
- // notification was clicked to avoid a race condition
- final boolean shouldAutoCancel = shouldAutoCancel(entry.getSbn());
- final NotificationEntry summaryToRemove = shouldAutoCancel
- ? mOnUserInteractionCallback.getGroupSummaryToDismiss(entry) : null;
-
- // inform NMS that the notification was clicked
- mClickNotifier.onNotificationClick(notificationKey, nv);
-
- if (!canBubble && (shouldAutoCancel
+ if (!canBubble && (shouldAutoCancel(entry.getSbn())
|| mRemoteInputManager.isNotificationKeptForRemoteInputHistory(notificationKey))) {
+ final Runnable removeNotification =
+ mOnUserInteractionCallback.registerFutureDismissal(entry, REASON_CLICK);
// Immediately remove notification from visually showing.
// We have to post the removal to the UI thread for synchronization.
mMainThreadHandler.post(() -> {
- final Runnable removeNotification = () -> {
- mOnUserInteractionCallback.onDismiss(entry, REASON_CLICK, summaryToRemove);
- if (!animate) {
- // If we're animating, this would be invoked after the activity launch
- // animation completes. Since we're not animating, the launch already
- // happened synchronously, so we notify the launch is complete here after
- // onDismiss.
- mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry);
- }
- };
if (mPresenter.isCollapsing()) {
// To avoid lags we're only performing the remove after the shade is collapsed
mShadeController.addPostCollapseAction(removeNotification);
@@ -412,12 +384,11 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
removeNotification.run();
}
});
- } else if (!canBubble && !animate) {
- // Not animating, this is the end of the launch flow (see above comment for more info).
- mMainThreadHandler.post(
- () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry));
}
+ // inform NMS that the notification was clicked
+ mClickNotifier.onNotificationClick(notificationKey, nv);
+
mIsCollapsingToShowActivityOverLockscreen = false;
}
@@ -434,24 +405,14 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
// will focus follow operation only after drag-and-drop that notification.
final NotificationVisibility nv = mVisibilityProvider.obtain(entry, true);
- // retrieve the group summary to remove with this entry before we tell NMS the
- // notification was clicked to avoid a race condition
- final boolean shouldAutoCancel = shouldAutoCancel(entry.getSbn());
- final NotificationEntry summaryToRemove = shouldAutoCancel
- ? mOnUserInteractionCallback.getGroupSummaryToDismiss(entry) : null;
-
String notificationKey = entry.getKey();
- // inform NMS that the notification was clicked
- mClickNotifier.onNotificationClick(notificationKey, nv);
-
- if (shouldAutoCancel || mRemoteInputManager.isNotificationKeptForRemoteInputHistory(
- notificationKey)) {
+ if (shouldAutoCancel(entry.getSbn())
+ || mRemoteInputManager.isNotificationKeptForRemoteInputHistory(notificationKey)) {
+ final Runnable removeNotification =
+ mOnUserInteractionCallback.registerFutureDismissal(entry, REASON_CLICK);
// Immediately remove notification from visually showing.
// We have to post the removal to the UI thread for synchronization.
mMainThreadHandler.post(() -> {
- final Runnable removeNotification = () ->
- mOnUserInteractionCallback.onDismiss(
- entry, REASON_CLICK, summaryToRemove);
if (mPresenter.isCollapsing()) {
// To avoid lags we're only performing the remove
// after the shade is collapsed
@@ -462,6 +423,9 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
});
}
+ // inform NMS that the notification was clicked
+ mClickNotifier.onNotificationClick(notificationKey, nv);
+
mIsCollapsingToShowActivityOverLockscreen = false;
}
@@ -489,15 +453,11 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
ExpandableNotificationRow row,
boolean animate,
boolean isActivityIntent) {
- mLogger.logStartNotificationIntent(entry.getKey());
+ mLogger.logStartNotificationIntent(entry);
try {
- Runnable onFinishAnimationCallback = animate
- ? () -> mLaunchEventsEmitter.notifyFinishLaunchNotifActivity(entry)
- : null;
ActivityLaunchAnimator.Controller animationController =
new StatusBarLaunchAnimatorController(
- mNotificationAnimationProvider
- .getAnimatorController(row, onFinishAnimationCallback),
+ mNotificationAnimationProvider.getAnimatorController(row, null),
mCentralSurfaces,
isActivityIntent);
mActivityLaunchAnimator.startPendingIntentWithAnimation(
@@ -515,7 +475,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
: getActivityOptions(mCentralSurfaces.getDisplayId(), adapter);
int result = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
null, null, options);
- mLogger.logSendPendingIntent(entry.getKey(), intent, result);
+ mLogger.logSendPendingIntent(entry, intent, result);
return result;
});
} catch (PendingIntent.CanceledException e) {
@@ -622,9 +582,9 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
void handleFullScreenIntent(NotificationEntry entry) {
if (mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
if (shouldSuppressFullScreenIntent(entry)) {
- mLogger.logFullScreenIntentSuppressedByDnD(entry.getKey());
+ mLogger.logFullScreenIntentSuppressedByDnD(entry);
} else if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
- mLogger.logFullScreenIntentNotImportantEnough(entry.getKey());
+ mLogger.logFullScreenIntentNotImportantEnough(entry);
} else {
// Stop screensaver if the notification has a fullscreen intent.
// (like an incoming phone call)
@@ -639,7 +599,7 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
// not immersive & a fullscreen alert should be shown
final PendingIntent fullscreenIntent =
entry.getSbn().getNotification().fullScreenIntent;
- mLogger.logSendingFullScreenIntent(entry.getKey(), fullscreenIntent);
+ mLogger.logSendingFullScreenIntent(entry, fullscreenIntent);
try {
EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
entry.getKey());
@@ -685,35 +645,4 @@ class StatusBarNotificationActivityStarter implements NotificationActivityStarte
return entry.shouldSuppressFullScreenIntent();
}
-
- @SysUISingleton
- static class LaunchEventsEmitter implements NotifActivityLaunchEvents {
-
- private final ListenerSet<Listener> mListeners = new ListenerSet<>();
-
- @Inject
- LaunchEventsEmitter() {}
-
- @Override
- public void registerListener(@NonNull Listener listener) {
- mListeners.addIfAbsent(listener);
- }
-
- @Override
- public void unregisterListener(@NonNull Listener listener) {
- mListeners.remove(listener);
- }
-
- private void notifyStartLaunchNotifActivity(NotificationEntry entry) {
- for (Listener listener : mListeners) {
- listener.onStartLaunchNotifActivity(entry);
- }
- }
-
- private void notifyFinishLaunchNotifActivity(NotificationEntry entry) {
- for (Listener listener : mListeners) {
- listener.onFinishLaunchNotifActivity(entry);
- }
- }
- }
}
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 2fbe520a4b61..b9a1413ff791 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
@@ -23,46 +23,48 @@ import com.android.systemui.log.LogLevel.ERROR
import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.log.LogLevel.WARNING
import com.android.systemui.log.dagger.NotifInteractionLog
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
class StatusBarNotificationActivityStarterLogger @Inject constructor(
@NotifInteractionLog private val buffer: LogBuffer
) {
- fun logStartingActivityFromClick(key: String) {
+ fun logStartingActivityFromClick(entry: NotificationEntry) {
buffer.log(TAG, DEBUG, {
- str1 = key
+ str1 = entry.logKey
}, {
"(1/5) onNotificationClicked: $str1"
})
}
- fun logHandleClickAfterKeyguardDismissed(key: String) {
+ fun logHandleClickAfterKeyguardDismissed(entry: NotificationEntry) {
buffer.log(TAG, DEBUG, {
- str1 = key
+ str1 = entry.logKey
}, {
"(2/5) handleNotificationClickAfterKeyguardDismissed: $str1"
})
}
- fun logHandleClickAfterPanelCollapsed(key: String) {
+ fun logHandleClickAfterPanelCollapsed(entry: NotificationEntry) {
buffer.log(TAG, DEBUG, {
- str1 = key
+ str1 = entry.logKey
}, {
"(3/5) handleNotificationClickAfterPanelCollapsed: $str1"
})
}
- fun logStartNotificationIntent(key: String) {
+ fun logStartNotificationIntent(entry: NotificationEntry) {
buffer.log(TAG, INFO, {
- str1 = key
+ str1 = entry.logKey
}, {
"(4/5) startNotificationIntent: $str1"
})
}
- fun logSendPendingIntent(key: String, pendingIntent: PendingIntent, result: Int) {
+ fun logSendPendingIntent(entry: NotificationEntry, pendingIntent: PendingIntent, result: Int) {
buffer.log(TAG, INFO, {
- str1 = key
+ str1 = entry.logKey
str2 = pendingIntent.intent.toString()
int1 = result
}, {
@@ -70,9 +72,9 @@ class StatusBarNotificationActivityStarterLogger @Inject constructor(
})
}
- fun logExpandingBubble(key: String) {
+ fun logExpandingBubble(entry: NotificationEntry) {
buffer.log(TAG, DEBUG, {
- str1 = key
+ str1 = entry.logKey
}, {
"Expanding bubble for $str1 (rather than firing intent)"
})
@@ -86,33 +88,33 @@ class StatusBarNotificationActivityStarterLogger @Inject constructor(
})
}
- fun logNonClickableNotification(key: String) {
+ fun logNonClickableNotification(entry: NotificationEntry) {
buffer.log(TAG, ERROR, {
- str1 = key
+ str1 = entry.logKey
}, {
"onNotificationClicked called for non-clickable notification! $str1"
})
}
- fun logFullScreenIntentSuppressedByDnD(key: String) {
+ fun logFullScreenIntentSuppressedByDnD(entry: NotificationEntry) {
buffer.log(TAG, DEBUG, {
- str1 = key
+ str1 = entry.logKey
}, {
"No Fullscreen intent: suppressed by DND: $str1"
})
}
- fun logFullScreenIntentNotImportantEnough(key: String) {
+ fun logFullScreenIntentNotImportantEnough(entry: NotificationEntry) {
buffer.log(TAG, DEBUG, {
- str1 = key
+ str1 = entry.logKey
}, {
"No Fullscreen intent: not important enough: $str1"
})
}
- fun logSendingFullScreenIntent(key: String, pendingIntent: PendingIntent) {
+ fun logSendingFullScreenIntent(entry: NotificationEntry, pendingIntent: PendingIntent) {
buffer.log(TAG, INFO, {
- str1 = key
+ str1 = entry.logKey
str2 = pendingIntent.intent.toString()
}, {
"Notification $str1 has fullScreenIntent; sending fullScreenIntent $str2"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 706800940fd1..958d54230f1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -32,6 +32,8 @@ import static com.android.systemui.statusbar.notification.collection.Notificatio
import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.NOT_DISMISSED;
import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.PARENT_DISMISSED;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -47,6 +49,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static java.util.Collections.singletonList;
@@ -180,13 +183,14 @@ public class NotifCollectionTest extends SysuiTestCase {
@Test
public void testGetGroupSummary() {
- assertEquals(null, mCollection.getGroupSummary("group"));
- NotifEvent summary = mNoMan.postNotif(
- buildNotif(TEST_PACKAGE, 0)
- .setGroup(mContext, "group")
- .setGroupSummary(mContext, true));
+ final NotificationEntryBuilder entryBuilder = buildNotif(TEST_PACKAGE, 0)
+ .setGroup(mContext, "group")
+ .setGroupSummary(mContext, true);
+ final String groupKey = entryBuilder.build().getSbn().getGroupKey();
+ assertEquals(null, mCollection.getGroupSummary(groupKey));
+ NotifEvent summary = mNoMan.postNotif(entryBuilder);
- final NotificationEntry entry = mCollection.getGroupSummary("group");
+ final NotificationEntry entry = mCollection.getGroupSummary(groupKey);
assertEquals(summary.key, entry.getKey());
assertEquals(summary.sbn, entry.getSbn());
assertEquals(summary.ranking, entry.getRanking());
@@ -194,9 +198,9 @@ public class NotifCollectionTest extends SysuiTestCase {
@Test
public void testIsOnlyChildInGroup() {
- NotifEvent notif1 = mNoMan.postNotif(
- buildNotif(TEST_PACKAGE, 1)
- .setGroup(mContext, "group"));
+ final NotificationEntryBuilder entryBuilder = buildNotif(TEST_PACKAGE, 1)
+ .setGroup(mContext, "group");
+ NotifEvent notif1 = mNoMan.postNotif(entryBuilder);
final NotificationEntry entry = mCollection.getEntry(notif1.key);
assertTrue(mCollection.isOnlyChildInGroup(entry));
@@ -1488,6 +1492,55 @@ public class NotifCollectionTest extends SysuiTestCase {
}
@Test
+ public void testRegisterFutureDismissal() throws RemoteException {
+ // GIVEN a pipeline with one notification
+ NotifEvent notifEvent = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47, "myTag"));
+ NotificationEntry entry = requireNonNull(mCollection.getEntry(notifEvent.key));
+ clearInvocations(mCollectionListener);
+
+ // WHEN registering a future dismissal, nothing happens right away
+ final Runnable onDismiss = mCollection.registerFutureDismissal(entry, REASON_CLICK,
+ NotifCollectionTest::defaultStats);
+ verifyNoMoreInteractions(mCollectionListener);
+
+ // WHEN finally dismissing
+ onDismiss.run();
+ verify(mStatusBarService).onNotificationClear(any(), anyInt(), eq(notifEvent.key),
+ anyInt(), anyInt(), any());
+ verifyNoMoreInteractions(mStatusBarService);
+ verifyNoMoreInteractions(mCollectionListener);
+ }
+
+ @Test
+ public void testRegisterFutureDismissalWithRetractionAndRepost() {
+ // GIVEN a pipeline with one notification
+ NotifEvent notifEvent = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47, "myTag"));
+ NotificationEntry entry = requireNonNull(mCollection.getEntry(notifEvent.key));
+ clearInvocations(mCollectionListener);
+
+ // WHEN registering a future dismissal, nothing happens right away
+ final Runnable onDismiss = mCollection.registerFutureDismissal(entry, REASON_CLICK,
+ NotifCollectionTest::defaultStats);
+ verifyNoMoreInteractions(mCollectionListener);
+
+ // WHEN retracting the notification, and then reposting
+ mNoMan.retractNotif(notifEvent.sbn, REASON_CLICK);
+ mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47, "myTag"));
+ clearInvocations(mCollectionListener);
+
+ // KNOWING that the entry in the collection is different now
+ assertThat(mCollection.getEntry(notifEvent.key)).isNotSameInstanceAs(entry);
+
+ // WHEN finally dismissing
+ onDismiss.run();
+
+ // VERIFY that nothing happens; the notification should not be removed
+ verifyNoMoreInteractions(mCollectionListener);
+ assertThat(mCollection.getEntry(notifEvent.key)).isNotNull();
+ verifyNoMoreInteractions(mStatusBarService);
+ }
+
+ @Test
public void testCannotDismissOngoingNotificationChildren() {
// GIVEN an ongoing notification
final NotificationEntry container = new NotificationEntryBuilder()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ActivityLaunchAnimCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ActivityLaunchAnimCoordinatorTest.kt
deleted file mode 100644
index c6c043aafb20..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ActivityLaunchAnimCoordinatorTest.kt
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.coordinator
-
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.notification.collection.NotifPipeline
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
-import com.android.systemui.statusbar.phone.NotifActivityLaunchEvents
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.withArgCaptor
-import dagger.BindsInstance
-import dagger.Component
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertTrue
-import org.junit.Test
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
-
-@SmallTest
-class ActivityLaunchAnimCoordinatorTest : SysuiTestCase() {
-
- val activityLaunchEvents: NotifActivityLaunchEvents = mock()
- val pipeline: NotifPipeline = mock()
-
- val coordinator: ActivityLaunchAnimCoordinator =
- DaggerTestActivityStarterCoordinatorComponent
- .factory()
- .create(activityLaunchEvents)
- .coordinator
-
- @Test
- fun testNoLifetimeExtensionIfNoAssociatedActivityLaunch() {
- coordinator.attach(pipeline)
- val lifetimeExtender = withArgCaptor<NotifLifetimeExtender> {
- verify(pipeline).addNotificationLifetimeExtender(capture())
- }
- val fakeEntry = mock<NotificationEntry>().also {
- whenever(it.key).thenReturn("0")
- }
- assertFalse(lifetimeExtender.maybeExtendLifetime(fakeEntry, 0))
- }
-
- @Test
- fun testNoLifetimeExtensionIfAssociatedActivityLaunchAlreadyEnded() {
- coordinator.attach(pipeline)
- val lifetimeExtender = withArgCaptor<NotifLifetimeExtender> {
- verify(pipeline).addNotificationLifetimeExtender(capture())
- }
- val eventListener = withArgCaptor<NotifActivityLaunchEvents.Listener> {
- verify(activityLaunchEvents).registerListener(capture())
- }
- val fakeEntry = mock<NotificationEntry>().also {
- whenever(it.key).thenReturn("0")
- }
- eventListener.onStartLaunchNotifActivity(fakeEntry)
- eventListener.onFinishLaunchNotifActivity(fakeEntry)
- assertFalse(lifetimeExtender.maybeExtendLifetime(fakeEntry, 0))
- }
-
- @Test
- fun testLifetimeExtensionWhileActivityLaunchInProgress() {
- coordinator.attach(pipeline)
- val lifetimeExtender = withArgCaptor<NotifLifetimeExtender> {
- verify(pipeline).addNotificationLifetimeExtender(capture())
- }
- val eventListener = withArgCaptor<NotifActivityLaunchEvents.Listener> {
- verify(activityLaunchEvents).registerListener(capture())
- }
- val onEndLifetimeExtensionCallback =
- mock<NotifLifetimeExtender.OnEndLifetimeExtensionCallback>()
- lifetimeExtender.setCallback(onEndLifetimeExtensionCallback)
-
- val fakeEntry = mock<NotificationEntry>().also {
- whenever(it.key).thenReturn("0")
- }
- eventListener.onStartLaunchNotifActivity(fakeEntry)
- assertTrue(lifetimeExtender.maybeExtendLifetime(fakeEntry, 0))
-
- eventListener.onFinishLaunchNotifActivity(fakeEntry)
- verify(onEndLifetimeExtensionCallback).onEndLifetimeExtension(lifetimeExtender, fakeEntry)
- }
-
- @Test
- fun testCancelLifetimeExtensionDoesNotInvokeCallback() {
- coordinator.attach(pipeline)
- val lifetimeExtender = withArgCaptor<NotifLifetimeExtender> {
- verify(pipeline).addNotificationLifetimeExtender(capture())
- }
- val eventListener = withArgCaptor<NotifActivityLaunchEvents.Listener> {
- verify(activityLaunchEvents).registerListener(capture())
- }
- val onEndLifetimeExtensionCallback =
- mock<NotifLifetimeExtender.OnEndLifetimeExtensionCallback>()
- lifetimeExtender.setCallback(onEndLifetimeExtensionCallback)
-
- val fakeEntry = mock<NotificationEntry>().also {
- whenever(it.key).thenReturn("0")
- }
- eventListener.onStartLaunchNotifActivity(fakeEntry)
- assertTrue(lifetimeExtender.maybeExtendLifetime(fakeEntry, 0))
-
- lifetimeExtender.cancelLifetimeExtension(fakeEntry)
- eventListener.onFinishLaunchNotifActivity(fakeEntry)
- verify(onEndLifetimeExtensionCallback, never())
- .onEndLifetimeExtension(lifetimeExtender, fakeEntry)
- }
-}
-
-@CoordinatorScope
-@Component(modules = [ActivityLaunchAnimCoordinatorModule::class])
-interface TestActivityStarterCoordinatorComponent {
- val coordinator: ActivityLaunchAnimCoordinator
-
- @Component.Factory
- interface Factory {
- fun create(
- @BindsInstance activityLaunchEvents: NotifActivityLaunchEvents
- ): TestActivityStarterCoordinatorComponent
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 1f9af81d6508..f5a0e2d48859 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -346,7 +346,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
.build();
row.performDismiss(false);
verify(mNotificationTestHelper.mOnUserInteractionCallback)
- .onDismiss(any(), anyInt(), any());
+ .registerFutureDismissal(any(), anyInt());
}
@Test
@@ -358,6 +358,6 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
.build();
row.performDismiss(false);
verify(mNotificationTestHelper.mOnUserInteractionCallback, never())
- .onDismiss(any(), anyInt(), any());
+ .registerFutureDismissal(any(), anyInt());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index d5ed37a570d2..7a8b329bec64 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -23,8 +23,11 @@ import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -121,6 +124,7 @@ public class NotificationTestHelper {
private StatusBarStateController mStatusBarStateController;
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
public final OnUserInteractionCallback mOnUserInteractionCallback;
+ public final Runnable mFutureDismissalRunnable;
public NotificationTestHelper(
Context context,
@@ -182,6 +186,9 @@ public class NotificationTestHelper {
mBindPipelineEntryListener = collectionListenerCaptor.getValue();
mPeopleNotificationIdentifier = mock(PeopleNotificationIdentifier.class);
mOnUserInteractionCallback = mock(OnUserInteractionCallback.class);
+ mFutureDismissalRunnable = mock(Runnable.class);
+ when(mOnUserInteractionCallback.registerFutureDismissal(any(), anyInt()))
+ .thenReturn(mFutureDismissalRunnable);
}
/**
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 fa867e2796f7..ecea14c6a522 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
@@ -85,7 +85,6 @@ import com.android.systemui.wmshell.BubblesManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
@@ -93,6 +92,7 @@ import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
import java.util.ArrayList;
+import java.util.List;
import java.util.Optional;
@SmallTest
@@ -141,12 +141,13 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
@Mock
private OnUserInteractionCallback mOnUserInteractionCallback;
@Mock
+ private Runnable mFutureDismissalRunnable;
+ @Mock
private StatusBarNotificationActivityStarter mNotificationActivityStarter;
@Mock
private ActivityLaunchAnimator mActivityLaunchAnimator;
@Mock
private InteractionJankMonitor mJankMonitor;
- private StatusBarNotificationActivityStarter.LaunchEventsEmitter mLaunchEventsEmitter;
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private NotificationTestHelper mNotificationTestHelper;
private ExpandableNotificationRow mNotificationRow;
@@ -187,8 +188,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
when(mEntryManager.getVisibleNotifications()).thenReturn(mActiveNotifications);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
- when(mOnUserInteractionCallback.getGroupSummaryToDismiss(mNotificationRow.getEntry()))
- .thenReturn(null);
+ when(mOnUserInteractionCallback.registerFutureDismissal(eq(mNotificationRow.getEntry()),
+ anyInt())).thenReturn(mFutureDismissalRunnable);
when(mVisibilityProvider.obtain(anyString(), anyBoolean()))
.thenAnswer(invocation -> NotificationVisibility.obtain(
invocation.getArgument(0), 0, 1, false));
@@ -203,7 +204,6 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
NotificationListContainer.class),
headsUpManager,
mJankMonitor);
- mLaunchEventsEmitter = new StatusBarNotificationActivityStarter.LaunchEventsEmitter();
mNotificationActivityStarter =
new StatusBarNotificationActivityStarter(
getContext(),
@@ -239,8 +239,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
mock(NotificationPresenter.class),
mock(NotificationPanelViewController.class),
mActivityLaunchAnimator,
- notificationAnimationProvider,
- mLaunchEventsEmitter
+ notificationAnimationProvider
);
// set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg
@@ -264,16 +263,23 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
@Test
public void testOnNotificationClicked_keyGuardShowing()
throws PendingIntent.CanceledException, RemoteException {
+ // To get the order right, collect posted runnables and run them later
+ List<Runnable> runnables = new ArrayList<>();
+ doAnswer(answerVoid(r -> runnables.add((Runnable) r)))
+ .when(mHandler).post(any(Runnable.class));
// Given
- StatusBarNotification sbn = mNotificationRow.getEntry().getSbn();
- sbn.getNotification().contentIntent = mContentIntent;
- sbn.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
+ NotificationEntry entry = mNotificationRow.getEntry();
+ Notification notification = entry.getSbn().getNotification();
+ notification.contentIntent = mContentIntent;
+ notification.flags |= Notification.FLAG_AUTO_CANCEL;
when(mKeyguardStateController.isShowing()).thenReturn(true);
when(mCentralSurfaces.isOccluded()).thenReturn(true);
// When
- mNotificationActivityStarter.onNotificationClicked(sbn, mNotificationRow);
+ mNotificationActivityStarter.onNotificationClicked(entry, mNotificationRow);
+ // Run the collected runnables in fifo order, the way post() really does.
+ while (!runnables.isEmpty()) runnables.remove(0).run();
// Then
verify(mShadeController, atLeastOnce()).collapsePanel();
@@ -283,24 +289,27 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
verify(mAssistManager).hideAssist();
- InOrder orderVerifier = Mockito.inOrder(mClickNotifier, mOnUserInteractionCallback);
- orderVerifier.verify(mClickNotifier).onNotificationClick(
- eq(sbn.getKey()), any(NotificationVisibility.class));
+ InOrder orderVerifier = Mockito.inOrder(mClickNotifier, mOnUserInteractionCallback,
+ mFutureDismissalRunnable);
// Notification calls dismiss callback to remove notification due to FLAG_AUTO_CANCEL
- orderVerifier.verify(mOnUserInteractionCallback).onDismiss(mNotificationRow.getEntry(),
- REASON_CLICK, null);
+ orderVerifier.verify(mOnUserInteractionCallback)
+ .registerFutureDismissal(eq(entry), eq(REASON_CLICK));
+ orderVerifier.verify(mClickNotifier).onNotificationClick(
+ eq(entry.getKey()), any(NotificationVisibility.class));
+ orderVerifier.verify(mFutureDismissalRunnable).run();
}
@Test
public void testOnNotificationClicked_bubble_noContentIntent_noKeyGuard()
throws RemoteException {
- StatusBarNotification sbn = mBubbleNotificationRow.getEntry().getSbn();
+ NotificationEntry entry = mBubbleNotificationRow.getEntry();
+ StatusBarNotification sbn = entry.getSbn();
// Given
sbn.getNotification().contentIntent = null;
// When
- mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
+ mNotificationActivityStarter.onNotificationClicked(entry, mBubbleNotificationRow);
// Then
verify(mBubblesManager).expandStackAndSelectBubble(eq(mBubbleNotificationRow.getEntry()));
@@ -311,20 +320,22 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
verify(mAssistManager).hideAssist();
verify(mClickNotifier).onNotificationClick(
- eq(sbn.getKey()), any(NotificationVisibility.class));
+ eq(entry.getKey()), any(NotificationVisibility.class));
// The content intent should NOT be sent on click.
verifyZeroInteractions(mContentIntent);
// Notification should not be cancelled.
- verify(mOnUserInteractionCallback, never()).onDismiss(eq(mNotificationRow.getEntry()),
- anyInt(), eq(null));
+ verify(mOnUserInteractionCallback, never())
+ .registerFutureDismissal(eq(mNotificationRow.getEntry()), anyInt());
+ verify(mFutureDismissalRunnable, never()).run();
}
@Test
public void testOnNotificationClicked_bubble_noContentIntent_keyGuardShowing()
throws RemoteException {
- StatusBarNotification sbn = mBubbleNotificationRow.getEntry().getSbn();
+ NotificationEntry entry = mBubbleNotificationRow.getEntry();
+ StatusBarNotification sbn = entry.getSbn();
// Given
sbn.getNotification().contentIntent = null;
@@ -332,7 +343,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
when(mCentralSurfaces.isOccluded()).thenReturn(true);
// When
- mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
+ mNotificationActivityStarter.onNotificationClicked(entry, mBubbleNotificationRow);
// Then
verify(mBubblesManager).expandStackAndSelectBubble(eq(mBubbleNotificationRow.getEntry()));
@@ -342,7 +353,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
verify(mAssistManager).hideAssist();
verify(mClickNotifier).onNotificationClick(
- eq(sbn.getKey()), any(NotificationVisibility.class));
+ eq(entry.getKey()), any(NotificationVisibility.class));
// The content intent should NOT be sent on click.
verifyZeroInteractions(mContentIntent);
@@ -354,7 +365,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
@Test
public void testOnNotificationClicked_bubble_withContentIntent_keyGuardShowing()
throws RemoteException {
- StatusBarNotification sbn = mBubbleNotificationRow.getEntry().getSbn();
+ NotificationEntry entry = mBubbleNotificationRow.getEntry();
+ StatusBarNotification sbn = entry.getSbn();
// Given
sbn.getNotification().contentIntent = mContentIntent;
@@ -362,7 +374,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
when(mCentralSurfaces.isOccluded()).thenReturn(true);
// When
- mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
+ mNotificationActivityStarter.onNotificationClicked(entry, mBubbleNotificationRow);
// Then
verify(mBubblesManager).expandStackAndSelectBubble(mBubbleNotificationRow.getEntry());
@@ -372,7 +384,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
verify(mAssistManager).hideAssist();
verify(mClickNotifier).onNotificationClick(
- eq(sbn.getKey()), any(NotificationVisibility.class));
+ eq(entry.getKey()), any(NotificationVisibility.class));
// The content intent should NOT be sent on click.
verify(mContentIntent).getIntent();
@@ -405,57 +417,4 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
// THEN display should try wake up for the full screen intent
verify(mCentralSurfaces).wakeUpForFullScreenIntent();
}
-
- @Test
- public void testNotifActivityStarterEventSourceStartEvent_onNotificationClicked() {
- NotifActivityLaunchEvents.Listener listener =
- mock(NotifActivityLaunchEvents.Listener.class);
- mLaunchEventsEmitter.registerListener(listener);
- mNotificationActivityStarter
- .onNotificationClicked(mNotificationRow.getEntry().getSbn(), mNotificationRow);
- verify(listener).onStartLaunchNotifActivity(mNotificationRow.getEntry());
- }
-
- @Test
- public void testNotifActivityStarterEventSourceFinishEvent_dismissKeyguardCancelled() {
- NotifActivityLaunchEvents.Listener listener =
- mock(NotifActivityLaunchEvents.Listener.class);
- mLaunchEventsEmitter.registerListener(listener);
- // set up dismissKeyguardThenExecute to synchronously invoke the cancel runnable arg
- doAnswer(answerVoid(
- (OnDismissAction dismissAction, Runnable cancel, Boolean afterKeyguardGone) ->
- cancel.run()))
- .when(mActivityStarter)
- .dismissKeyguardThenExecute(any(OnDismissAction.class), any(), anyBoolean());
- mNotificationActivityStarter
- .onNotificationClicked(mNotificationRow.getEntry().getSbn(), mNotificationRow);
- verify(listener).onFinishLaunchNotifActivity(mNotificationRow.getEntry());
- }
-
- @Test
- public void testNotifActivityStarterEventSourceFinishEvent_postPanelCollapse()
- throws Exception {
- NotifActivityLaunchEvents.Listener listener =
- mock(NotifActivityLaunchEvents.Listener.class);
- mLaunchEventsEmitter.registerListener(listener);
- mNotificationActivityStarter
- .onNotificationClicked(mNotificationRow.getEntry().getSbn(), mNotificationRow);
- ArgumentCaptor<ActivityLaunchAnimator.Controller> controllerCaptor =
- ArgumentCaptor.forClass(ActivityLaunchAnimator.Controller.class);
- verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(
- controllerCaptor.capture(), anyBoolean(), any(), any());
- controllerCaptor.getValue().onIntentStarted(false);
- verify(listener).onFinishLaunchNotifActivity(mNotificationRow.getEntry());
- }
-
- @Test
- public void testNotifActivityStarterEventSourceFinishEvent_postPanelCollapse_noAnimate() {
- NotifActivityLaunchEvents.Listener listener =
- mock(NotifActivityLaunchEvents.Listener.class);
- mLaunchEventsEmitter.registerListener(listener);
- when(mCentralSurfaces.shouldAnimateLaunch(anyBoolean())).thenReturn(false);
- mNotificationActivityStarter
- .onNotificationClicked(mNotificationRow.getEntry().getSbn(), mNotificationRow);
- verify(listener).onFinishLaunchNotifActivity(mNotificationRow.getEntry());
- }
}