diff options
20 files changed, 224 insertions, 64 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java index e17d4e69093a..77abffc82d68 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java @@ -23,10 +23,13 @@ import android.os.Looper; import android.util.ArraySet; import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.statusbar.NotificationInteractionTracker; import com.android.systemui.statusbar.NotificationLifetimeExtender; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.util.time.SystemClock; +import javax.inject.Inject; + /** * Extends the lifetime of foreground notification services such that they show for at least * five seconds @@ -41,9 +44,14 @@ public class ForegroundServiceLifetimeExtender implements NotificationLifetimeEx private ArraySet<NotificationEntry> mManagedEntries = new ArraySet<>(); private Handler mHandler = new Handler(Looper.getMainLooper()); private final SystemClock mSystemClock; + private final NotificationInteractionTracker mInteractionTracker; - public ForegroundServiceLifetimeExtender(SystemClock systemClock) { + @Inject + public ForegroundServiceLifetimeExtender( + NotificationInteractionTracker interactionTracker, + SystemClock systemClock) { mSystemClock = systemClock; + mInteractionTracker = interactionTracker; } @Override @@ -58,8 +66,9 @@ public class ForegroundServiceLifetimeExtender implements NotificationLifetimeEx return false; } - long currentTime = mSystemClock.uptimeMillis(); - return currentTime - entry.getCreationTime() < MIN_FGS_TIME_MS; + boolean hasInteracted = mInteractionTracker.hasUserInteractedWith(entry.getKey()); + long aliveTime = mSystemClock.uptimeMillis() - entry.getCreationTime(); + return aliveTime < MIN_FGS_TIME_MS && !hasInteracted; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java index ef1f4e0afede..650b9a7f9c0c 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java @@ -51,6 +51,7 @@ public class ForegroundServiceNotificationListener { ForegroundServiceController foregroundServiceController, NotificationEntryManager notificationEntryManager, NotifPipeline notifPipeline, + ForegroundServiceLifetimeExtender fgsLifetimeExtender, SystemClock systemClock) { mContext = context; mForegroundServiceController = foregroundServiceController; @@ -78,8 +79,7 @@ public class ForegroundServiceNotificationListener { removeNotification(entry.getSbn()); } }); - mEntryManager.addNotificationLifetimeExtender( - new ForegroundServiceLifetimeExtender(systemClock)); + mEntryManager.addNotificationLifetimeExtender(fgsLifetimeExtender); notifPipeline.addCollectionListener(new NotifCollectionListener() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt new file mode 100644 index 000000000000..8248fc9f5844 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt @@ -0,0 +1,87 @@ +package com.android.systemui.statusbar + +import android.app.Notification +import android.os.RemoteException +import com.android.internal.statusbar.IStatusBarService +import com.android.internal.statusbar.NotificationVisibility +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.util.Assert +import java.util.concurrent.Executor +import javax.inject.Inject +import javax.inject.Singleton + +/** + * Class to shim calls to IStatusBarManager#onNotificationClick/#onNotificationActionClick that + * allow an in-process notification to go out (e.g., for tracking interactions) as well as + * sending the messages along to system server. + * + * NOTE: this class eats exceptions from system server, as no current client of these APIs cares + * about errors + */ +@Singleton +public class NotificationClickNotifier @Inject constructor( + val barService: IStatusBarService, + @Main val mainExecutor: Executor +) { + val listeners = mutableListOf<NotificationInteractionListener>() + + fun addNotificationInteractionListener(listener: NotificationInteractionListener) { + Assert.isMainThread() + listeners.add(listener) + } + + fun removeNotificationInteractionListener(listener: NotificationInteractionListener) { + Assert.isMainThread() + listeners.remove(listener) + } + + private fun notifyListenersAboutInteraction(key: String) { + for (l in listeners) { + l.onNotificationInteraction(key) + } + } + + fun onNotificationActionClick( + key: String, + actionIndex: Int, + action: Notification.Action, + visibility: NotificationVisibility, + generatedByAssistant: Boolean + ) { + try { + barService.onNotificationActionClick( + key, actionIndex, action, visibility, generatedByAssistant) + } catch (e: RemoteException) { + // nothing + } + + mainExecutor.execute { + notifyListenersAboutInteraction(key) + } + } + + fun onNotificationClick( + key: String, + visibility: NotificationVisibility + ) { + try { + barService.onNotificationClick(key, visibility) + } catch (e: RemoteException) { + // nothing + } + + mainExecutor.execute { + notifyListenersAboutInteraction(key) + } + } +} + +/** + * Interface for listeners to get notified when a notification is interacted with via a click or + * interaction with remote input or actions + */ +interface NotificationInteractionListener { + fun onNotificationInteraction(key: String) +} + +private const val TAG = "NotificationClickNotifier" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt new file mode 100644 index 000000000000..2ed04eb088a3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt @@ -0,0 +1,40 @@ +package com.android.systemui.statusbar + +import com.android.systemui.statusbar.notification.NotificationEntryManager +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener +import javax.inject.Inject +import javax.inject.Singleton + +/** + * Class to track user interaction with notifications. It's a glorified map of key : bool that can + * merge multiple "user interacted with notification" signals into a single place. + */ +@Singleton +class NotificationInteractionTracker @Inject constructor( + private val clicker: NotificationClickNotifier, + private val entryManager: NotificationEntryManager +) : NotifCollectionListener, NotificationInteractionListener { + private val interactions = mutableMapOf<String, Boolean>() + + init { + clicker.addNotificationInteractionListener(this) + entryManager.addCollectionListener(this) + } + + fun hasUserInteractedWith(key: String): Boolean = key in interactions + + override fun onEntryAdded(entry: NotificationEntry) { + interactions[entry.key] = false + } + + override fun onEntryCleanUp(entry: NotificationEntry) { + interactions.remove(entry.key) + } + + override fun onNotificationInteraction(key: String) { + interactions[key] = true + } +} + +private const val TAG = "NotificationInteractionTracker" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index 2baab61d861b..03424c4956ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -35,7 +35,6 @@ import android.content.IntentSender; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Handler; -import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -43,7 +42,6 @@ import android.util.Log; import android.util.SparseArray; import android.util.SparseBooleanArray; -import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; @@ -92,9 +90,9 @@ public class NotificationLockscreenUserManagerImpl implements private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray(); private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray(); private final UserManager mUserManager; - private final IStatusBarService mBarService; private final List<UserChangedListener> mListeners = new ArrayList<>(); private final BroadcastDispatcher mBroadcastDispatcher; + private final NotificationClickNotifier mClickNotifier; private boolean mShowLockscreenNotifications; private boolean mAllowLockscreenRemoteInput; @@ -170,11 +168,7 @@ public class NotificationLockscreenUserManagerImpl implements final NotificationVisibility nv = NotificationVisibility.obtain( notificationKey, rank, count, true, location); - try { - mBarService.onNotificationClick(notificationKey, nv); - } catch (RemoteException exception) { - /* ignore */ - } + mClickNotifier.onNotificationClick(notificationKey, nv); } break; } @@ -203,7 +197,7 @@ public class NotificationLockscreenUserManagerImpl implements BroadcastDispatcher broadcastDispatcher, DevicePolicyManager devicePolicyManager, UserManager userManager, - IStatusBarService iStatusBarService, + NotificationClickNotifier clickNotifier, KeyguardManager keyguardManager, StatusBarStateController statusBarStateController, @Main Handler mainHandler, @@ -214,7 +208,7 @@ public class NotificationLockscreenUserManagerImpl implements mDevicePolicyManager = devicePolicyManager; mUserManager = userManager; mCurrentUserId = ActivityManager.getCurrentUser(); - mBarService = iStatusBarService; + mClickNotifier = clickNotifier; statusBarStateController.addCallback(this); mLockPatternUtils = new LockPatternUtils(context); mKeyguardManager = keyguardManager; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index 9181c69e3722..a81c7d35c902 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -123,6 +123,7 @@ public class NotificationRemoteInputManager implements Dumpable { private final KeyguardManager mKeyguardManager; private final StatusBarStateController mStatusBarStateController; private final RemoteInputUriController mRemoteInputUriController; + private final NotificationClickNotifier mClickNotifier; protected RemoteInputController mRemoteInputController; protected NotificationLifetimeExtender.NotificationSafeToRemoveCallback @@ -214,11 +215,7 @@ public class NotificationRemoteInputManager implements Dumpable { mEntryManager.getActiveNotificationUnfiltered(key)); final NotificationVisibility nv = NotificationVisibility.obtain(key, rank, count, true, location); - try { - mBarService.onNotificationActionClick(key, buttonIndex, action, nv, false); - } catch (RemoteException e) { - // Ignore - } + mClickNotifier.onNotificationActionClick(key, buttonIndex, action, nv, false); } private NotificationEntry getNotificationForParent(ViewParent parent) { @@ -275,6 +272,7 @@ public class NotificationRemoteInputManager implements Dumpable { StatusBarStateController statusBarStateController, @Main Handler mainHandler, RemoteInputUriController remoteInputUriController, + NotificationClickNotifier clickNotifier, ActionClickLogger logger) { mContext = context; mLockscreenUserManager = lockscreenUserManager; @@ -290,6 +288,7 @@ public class NotificationRemoteInputManager implements Dumpable { mKeyguardManager = context.getSystemService(KeyguardManager.class); mStatusBarStateController = statusBarStateController; mRemoteInputUriController = remoteInputUriController; + mClickNotifier = clickNotifier; notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java index bb96f42758e6..7fc18b753d40 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java @@ -35,6 +35,7 @@ import java.util.Set; public class SmartReplyController { private final IStatusBarService mBarService; private final NotificationEntryManager mEntryManager; + private final NotificationClickNotifier mClickNotifier; private Set<String> mSendingKeys = new ArraySet<>(); private Callback mCallback; @@ -42,9 +43,11 @@ public class SmartReplyController { * Injected constructor. See {@link StatusBarModule}. */ public SmartReplyController(NotificationEntryManager entryManager, - IStatusBarService statusBarService) { + IStatusBarService statusBarService, + NotificationClickNotifier clickNotifier) { mBarService = statusBarService; mEntryManager = entryManager; + mClickNotifier = clickNotifier; } public void setCallback(Callback callback) { @@ -78,12 +81,8 @@ public class SmartReplyController { NotificationLogger.getNotificationLocation(entry); final NotificationVisibility nv = NotificationVisibility.obtain( entry.getKey(), rank, count, true, location); - try { - mBarService.onNotificationActionClick( - entry.getKey(), actionIndex, action, nv, generatedByAssistant); - } catch (RemoteException e) { - // Nothing to do, system going down - } + mClickNotifier.onNotificationActionClick( + entry.getKey(), actionIndex, action, nv, generatedByAssistant); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java index b08eb9fafe41..176e42667ab5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java @@ -28,6 +28,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.ActionClickLogger; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.MediaArtworkProcessor; +import com.android.systemui.statusbar.NotificationClickNotifier; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationMediaManager; @@ -75,6 +76,7 @@ public interface StatusBarDependenciesModule { StatusBarStateController statusBarStateController, Handler mainHandler, RemoteInputUriController remoteInputUriController, + NotificationClickNotifier clickNotifier, ActionClickLogger actionClickLogger) { return new NotificationRemoteInputManager( context, @@ -85,6 +87,7 @@ public interface StatusBarDependenciesModule { statusBarStateController, mainHandler, remoteInputUriController, + clickNotifier, actionClickLogger); } @@ -128,8 +131,10 @@ public interface StatusBarDependenciesModule { @Singleton @Provides static SmartReplyController provideSmartReplyController( - NotificationEntryManager entryManager, IStatusBarService statusBarService) { - return new SmartReplyController(entryManager, statusBarService); + NotificationEntryManager entryManager, + IStatusBarService statusBarService, + NotificationClickNotifier clickNotifier) { + return new SmartReplyController(entryManager, statusBarService, clickNotifier); } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java index 2beceb2c5e0a..97ae83ef3f6a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java @@ -90,7 +90,7 @@ public interface NotificationEntryListener { * @param removedByUser true if the notification was removed by a user action */ default void onEntryRemoved( - NotificationEntry entry, + @NonNull NotificationEntry entry, @Nullable NotificationVisibility visibility, boolean removedByUser, int reason) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java index 0caf0dc4a3a3..97c1523887ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java @@ -19,6 +19,8 @@ package com.android.systemui.statusbar.notification.collection; import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_NOT_CANCELED; import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.NOT_DISMISSED; +import com.android.systemui.statusbar.NotificationInteractionTracker; + import java.util.Arrays; import java.util.List; @@ -35,6 +37,7 @@ public class ListDumper { */ public static String dumpTree( List<ListEntry> entries, + NotificationInteractionTracker interactionTracker, boolean includeRecordKeeping, String indent) { StringBuilder sb = new StringBuilder(); @@ -46,7 +49,8 @@ public class ListDumper { indent, sb, true, - includeRecordKeeping); + includeRecordKeeping, + interactionTracker.hasUserInteractedWith(entry.getKey())); if (entry instanceof GroupEntry) { GroupEntry ge = (GroupEntry) entry; List<NotificationEntry> children = ge.getChildren(); @@ -56,7 +60,8 @@ public class ListDumper { childEntryIndent, sb, true, - includeRecordKeeping); + includeRecordKeeping, + interactionTracker.hasUserInteractedWith(entry.getKey())); } } } @@ -80,7 +85,8 @@ public class ListDumper { indent, sb, false, - includeRecordKeeping); + includeRecordKeeping, + false); } return sb.toString(); } @@ -91,7 +97,9 @@ public class ListDumper { String indent, StringBuilder sb, boolean includeParent, - boolean includeRecordKeeping) { + boolean includeRecordKeeping, + boolean hasBeenInteractedWith + ) { sb.append(indent) .append("[").append(index).append("] ") .append(entry.getKey()); @@ -157,6 +165,8 @@ public class ListDumper { .append(" "); } + rksb.append("interacted=").append(hasBeenInteractedWith ? "yes" : "no").append(" "); + String rkString = rksb.toString(); if (!rkString.isEmpty()) { sb.append("\n\t") diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java index 4cec383776b2..9d81d3563ebb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java @@ -36,6 +36,7 @@ import androidx.annotation.NonNull; import com.android.systemui.Dumpable; import com.android.systemui.dump.DumpManager; +import com.android.systemui.statusbar.NotificationInteractionTracker; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener; @@ -73,6 +74,7 @@ import javax.inject.Singleton; public class ShadeListBuilder implements Dumpable { private final SystemClock mSystemClock; private final ShadeListBuilderLogger mLogger; + private final NotificationInteractionTracker mInteractionTracker; private List<ListEntry> mNotifList = new ArrayList<>(); private List<ListEntry> mNewNotifList = new ArrayList<>(); @@ -105,10 +107,12 @@ public class ShadeListBuilder implements Dumpable { public ShadeListBuilder( SystemClock systemClock, ShadeListBuilderLogger logger, - DumpManager dumpManager) { + DumpManager dumpManager, + NotificationInteractionTracker interactionTracker) { Assert.isMainThread(); mSystemClock = systemClock; mLogger = logger; + mInteractionTracker = interactionTracker; dumpManager.registerDumpable(TAG, this); } @@ -821,6 +825,7 @@ public class ShadeListBuilder implements Dumpable { pw.println(ListDumper.dumpTree( getShadeList(), + mInteractionTracker, true, "\t\t")); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java index 3fab6f7c3857..75d772e8a1c5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java @@ -77,7 +77,7 @@ public interface NotifCollectionListener { * the entry during this call. Instead, use {@link #onEntryRemoved} which will be called before * deletion. */ - default void onEntryCleanUp(NotificationEntry entry) { + default void onEntryCleanUp(@NonNull NotificationEntry entry) { } /** 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 7924348d34d4..64e5f0a8184e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -45,7 +45,6 @@ import android.view.RemoteAnimationAdapter; import android.view.View; import com.android.internal.logging.MetricsLogger; -import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.ActivityIntentHelper; @@ -59,6 +58,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.FeatureFlags; +import com.android.systemui.statusbar.NotificationClickNotifier; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -103,7 +103,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private final NotifCollection mNotifCollection; private final HeadsUpManagerPhone mHeadsUpManager; private final ActivityStarter mActivityStarter; - private final IStatusBarService mBarService; + private final NotificationClickNotifier mClickNotifier; private final StatusBarStateController mStatusBarStateController; private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private final KeyguardManager mKeyguardManager; @@ -142,7 +142,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit NotifCollection notifCollection, HeadsUpManagerPhone headsUpManager, ActivityStarter activityStarter, - IStatusBarService statusBarService, + NotificationClickNotifier clickNotifier, StatusBarStateController statusBarStateController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, KeyguardManager keyguardManager, @@ -177,7 +177,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mNotifCollection = notifCollection; mHeadsUpManager = headsUpManager; mActivityStarter = activityStarter; - mBarService = statusBarService; + mClickNotifier = clickNotifier; mStatusBarStateController = statusBarStateController; mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mKeyguardManager = keyguardManager; @@ -379,11 +379,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit NotificationLogger.getNotificationLocation(entry); final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey, rank, count, true, location); - try { - mBarService.onNotificationClick(notificationKey, nv); - } catch (RemoteException ex) { - // system process is dead if we're here. - } + mClickNotifier.onNotificationClick(notificationKey, nv); if (!isBubble) { if (parentToCancelFinal != null) { @@ -651,7 +647,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private final NotifCollection mNotifCollection; private final HeadsUpManagerPhone mHeadsUpManager; private final ActivityStarter mActivityStarter; - private final IStatusBarService mStatusBarService; + private final NotificationClickNotifier mClickNotifier; private final StatusBarStateController mStatusBarStateController; private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private final KeyguardManager mKeyguardManager; @@ -689,7 +685,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit NotifCollection notifCollection, HeadsUpManagerPhone headsUpManager, ActivityStarter activityStarter, - IStatusBarService statusBarService, + NotificationClickNotifier clickNotifier, StatusBarStateController statusBarStateController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, KeyguardManager keyguardManager, @@ -720,7 +716,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mNotifCollection = notifCollection; mHeadsUpManager = headsUpManager; mActivityStarter = activityStarter; - mStatusBarService = statusBarService; + mClickNotifier = clickNotifier; mStatusBarStateController = statusBarStateController; mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mKeyguardManager = keyguardManager; @@ -777,7 +773,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mNotifCollection, mHeadsUpManager, mActivityStarter, - mStatusBarService, + mClickNotifier, mStatusBarStateController, mStatusBarKeyguardViewManager, mKeyguardManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java index 45f9437efc15..805254cda175 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java @@ -85,7 +85,8 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { mFsc = new ForegroundServiceController( mEntryManager, mAppOpsController, mMainHandler); mListener = new ForegroundServiceNotificationListener( - mContext, mFsc, mEntryManager, mNotifPipeline, mClock); + mContext, mFsc, mEntryManager, mNotifPipeline, + mock(ForegroundServiceLifetimeExtender.class), mClock); ArgumentCaptor<NotificationEntryListener> entryListenerCaptor = ArgumentCaptor.forClass(NotificationEntryListener.class); verify(mEntryManager).addNotificationEntryListener( diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java index bca8deeafd34..050b5538773d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java @@ -26,6 +26,7 @@ import android.app.Notification; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.systemui.statusbar.NotificationInteractionTracker; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.util.time.FakeSystemClock; @@ -33,6 +34,8 @@ import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) @SmallTest @@ -42,9 +45,13 @@ public class ForegroundServiceNotificationListenerTest extends SysuiTestCase { private Notification mNotif; private final FakeSystemClock mClock = new FakeSystemClock(); + @Mock + private NotificationInteractionTracker mInteractionTracker; + @Before public void setup() { - mExtender = new ForegroundServiceLifetimeExtender(mClock); + MockitoAnnotations.initMocks(this); + mExtender = new ForegroundServiceLifetimeExtender(mInteractionTracker, mClock); mNotif = new Notification.Builder(mContext, "") .setSmallIcon(R.drawable.ic_person) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java index a24fa842eca7..808f17b8ba70 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java @@ -52,7 +52,6 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; -import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.Dependency; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; @@ -86,7 +85,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { @Mock private DevicePolicyManager mDevicePolicyManager; @Mock - private IStatusBarService mIStatusBarService; + private NotificationClickNotifier mClickNotifier; @Mock private KeyguardManager mKeyguardManager; @Mock @@ -397,7 +396,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { extends NotificationLockscreenUserManagerImpl { public TestNotificationLockscreenUserManager(Context context) { super(context, mBroadcastDispatcher, mDevicePolicyManager, mUserManager, - mIStatusBarService, NotificationLockscreenUserManagerTest.this.mKeyguardManager, + mClickNotifier, NotificationLockscreenUserManagerTest.this.mKeyguardManager, mStatusBarStateController, Handler.createAsync(Looper.myLooper()), mDeviceProvisionedController, mKeyguardStateController); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java index 5a7dea4de29c..eaef43d133af 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java @@ -62,6 +62,7 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { @Mock private ExpandableNotificationRow mRow; @Mock private StatusBarStateController mStateController; @Mock private RemoteInputUriController mRemoteInputUriController; + @Mock private NotificationClickNotifier mClickNotifier; // Dependency mocks: @Mock private NotificationEntryManager mEntryManager; @@ -83,6 +84,7 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { mStateController, Handler.createAsync(Looper.myLooper()), mRemoteInputUriController, + mClickNotifier, mock(ActionClickLogger.class)); mEntry = new NotificationEntryBuilder() .setPkg(TEST_PACKAGE_NAME) @@ -266,6 +268,7 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { StatusBarStateController statusBarStateController, Handler mainHandler, RemoteInputUriController remoteInputUriController, + NotificationClickNotifier clickNotifier, ActionClickLogger actionClickLogger) { super( context, @@ -276,6 +279,7 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { statusBarStateController, mainHandler, remoteInputUriController, + clickNotifier, actionClickLogger); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java index 79507e96ae02..7cbc4e4e2c62 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java @@ -75,6 +75,7 @@ public class SmartReplyControllerTest extends SysuiTestCase { @Mock private IStatusBarService mIStatusBarService; @Mock private StatusBarStateController mStatusBarStateController; @Mock private RemoteInputUriController mRemoteInputUriController; + @Mock private NotificationClickNotifier mClickNotifier; @Before public void setUp() { @@ -83,7 +84,7 @@ public class SmartReplyControllerTest extends SysuiTestCase { mNotificationEntryManager); mSmartReplyController = new SmartReplyController(mNotificationEntryManager, - mIStatusBarService); + mIStatusBarService, mClickNotifier); mDependency.injectTestDependency(SmartReplyController.class, mSmartReplyController); @@ -93,6 +94,7 @@ public class SmartReplyControllerTest extends SysuiTestCase { mStatusBarStateController, Handler.createAsync(Looper.myLooper()), mRemoteInputUriController, + mClickNotifier, mock(ActionClickLogger.class)); mRemoteInputManager.setUpWithCallback(mCallback, mDelegate); mNotification = new Notification.Builder(mContext, "") diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java index a93b54ac1009..6fa5055c875d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java @@ -44,6 +44,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; +import com.android.systemui.statusbar.NotificationInteractionTracker; import com.android.systemui.statusbar.notification.collection.ShadeListBuilder.OnRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; @@ -86,6 +87,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { @Mock private ShadeListBuilderLogger mLogger; @Mock private NotifCollection mNotifCollection; + @Mock private NotificationInteractionTracker mInteractionTracker; @Spy private OnBeforeTransformGroupsListener mOnBeforeTransformGroupsListener; @Spy private OnBeforeSortListener mOnBeforeSortListener; @Spy private OnBeforeFinalizeFilterListener mOnBeforeFinalizeFilterListener; @@ -107,7 +109,8 @@ public class ShadeListBuilderTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); allowTestableLooperAsMainThread(); - mListBuilder = new ShadeListBuilder(mSystemClock, mLogger, mock(DumpManager.class)); + mListBuilder = new ShadeListBuilder( + mSystemClock, mLogger, mock(DumpManager.class), mInteractionTracker); mListBuilder.setOnRenderListListener(mOnRenderListListener); mListBuilder.attach(mNotifCollection); @@ -1280,7 +1283,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { } catch (AssertionError err) { throw new AssertionError( "List under test failed verification:\n" + dumpTree(mBuiltList, - true, ""), err); + mInteractionTracker, true, ""), err); } } 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 1afe132f00a9..53a1773b1bd1 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 @@ -48,7 +48,6 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; -import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.ActivityIntentHelper; @@ -59,6 +58,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.FeatureFlags; +import com.android.systemui.statusbar.NotificationClickNotifier; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -98,7 +98,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { @Mock private ActivityStarter mActivityStarter; @Mock - private IStatusBarService mStatusBarService; + private NotificationClickNotifier mClickNotifier; @Mock private StatusBarStateController mStatusBarStateController; @Mock @@ -188,7 +188,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { mNotifCollection, mock(HeadsUpManagerPhone.class), mActivityStarter, - mStatusBarService, + mClickNotifier, mock(StatusBarStateController.class), mStatusBarKeyguardViewManager, mock(KeyguardManager.class), @@ -263,7 +263,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { verify(mAssistManager).hideAssist(); - verify(mStatusBarService).onNotificationClick( + verify(mClickNotifier).onNotificationClick( eq(sbn.getKey()), any(NotificationVisibility.class)); // Notification is removed due to FLAG_AUTO_CANCEL @@ -289,7 +289,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { verify(mAssistManager).hideAssist(); - verify(mStatusBarService).onNotificationClick( + verify(mClickNotifier).onNotificationClick( eq(sbn.getKey()), any(NotificationVisibility.class)); // The content intent should NOT be sent on click. @@ -319,7 +319,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { verify(mAssistManager).hideAssist(); - verify(mStatusBarService).onNotificationClick( + verify(mClickNotifier).onNotificationClick( eq(sbn.getKey()), any(NotificationVisibility.class)); // The content intent should NOT be sent on click. @@ -349,7 +349,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { verify(mAssistManager).hideAssist(); - verify(mStatusBarService).onNotificationClick( + verify(mClickNotifier).onNotificationClick( eq(sbn.getKey()), any(NotificationVisibility.class)); // The content intent should NOT be sent on click. |