Loading core/java/android/service/notification/NotificationStats.java +5 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,11 @@ public final class NotificationStats implements Parcelable { * Notification has been dismissed from the notification shade. */ public static final int DISMISSAL_SHADE = 3; /** * Notification has been dismissed as a bubble. * @hide */ public static final int DISMISSAL_BUBBLE = 3; /** @hide */ @IntDef(prefix = { "DISMISS_SENTIMENT_" }, value = { Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +52 −9 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import static android.service.notification.NotificationListenerService.REASON_CA import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL; import static android.service.notification.NotificationListenerService.REASON_CLICK; import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED; import static android.service.notification.NotificationStats.DISMISSAL_BUBBLE; import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.View.INVISIBLE; Loading Loading @@ -100,8 +102,11 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.coordinator.BubbleCoordinator; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ScrimController; Loading Loading @@ -277,7 +282,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * This can happen when an app cancels a bubbled notification or when the user dismisses a * bubble. */ void removeNotification(@NonNull NotificationEntry entry, int reason); void removeNotification( @NonNull NotificationEntry entry, @NonNull DismissedByUserStats stats, int reason); /** * Called when a bubbled notification has changed whether it should be Loading Loading @@ -543,6 +551,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } }); // The new pipeline takes care of this as a NotifDismissInterceptor BubbleCoordinator mNotificationEntryManager.addNotificationRemoveInterceptor( new NotificationRemoveInterceptor() { @Override Loading @@ -551,7 +560,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi NotificationEntry entry, int dismissReason) { final boolean isClearAll = dismissReason == REASON_CANCEL_ALL; final boolean isUserDimiss = dismissReason == REASON_CANCEL final boolean isUserDismiss = dismissReason == REASON_CANCEL || dismissReason == REASON_CLICK; final boolean isAppCancel = dismissReason == REASON_APP_CANCEL || dismissReason == REASON_APP_CANCEL_ALL; Loading @@ -562,7 +571,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi // previously been dismissed & entry.isRowDismissed would still be true boolean userRemovedNotif = (entry != null && entry.isRowDismissed() && !isAppCancel) || isClearAll || isUserDimiss || isSummaryCancel; || isClearAll || isUserDismiss || isSummaryCancel; if (userRemovedNotif) { return handleDismissalInterception(entry); Loading Loading @@ -591,8 +600,13 @@ public class BubbleController implements ConfigurationController.ConfigurationLi addNotifCallback(new NotifCallback() { @Override public void removeNotification(NotificationEntry entry, int reason) { mNotificationEntryManager.performRemoveNotification(entry.getSbn(), reason); public void removeNotification( NotificationEntry entry, DismissedByUserStats dismissedByUserStats, int reason ) { mNotificationEntryManager.performRemoveNotification(entry.getSbn(), dismissedByUserStats, reason); } @Override Loading @@ -612,7 +626,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mNotificationEntryManager.getActiveNotificationUnfiltered( mBubbleData.getSummaryKey(groupKey)); if (summary != null) { mNotificationEntryManager.performRemoveNotification(summary.getSbn(), mNotificationEntryManager.performRemoveNotification( summary.getSbn(), getDismissedByUserStats(summary, false), UNDEFINED_DISMISS_REASON); } } Loading @@ -634,7 +650,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi boolean isSummaryThisNotif = summary.getKey().equals(entry.getKey()); if (!isSummaryThisNotif && (summaryChildren == null || summaryChildren.isEmpty())) { mNotificationEntryManager.performRemoveNotification(summary.getSbn(), mNotificationEntryManager.performRemoveNotification( summary.getSbn(), getDismissedByUserStats(summary, false), UNDEFINED_DISMISS_REASON); } } Loading Loading @@ -1331,7 +1349,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi // time to actually remove it for (NotifCallback cb : mCallbacks) { if (entry != null) { cb.removeNotification(entry, REASON_CANCEL); cb.removeNotification( entry, getDismissedByUserStats(entry, true), REASON_CANCEL); } } } else { Loading Loading @@ -1487,7 +1508,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } else { // non-bubbled children can be removed for (NotifCallback cb : mCallbacks) { cb.removeNotification(child, REASON_GROUP_SUMMARY_CANCELED); cb.removeNotification( child, getDismissedByUserStats(child, true), REASON_GROUP_SUMMARY_CANCELED); } } } Loading @@ -1501,6 +1525,25 @@ public class BubbleController implements ConfigurationController.ConfigurationLi summary.getKey()); } /** * Gets the DismissedByUserStats used by {@link NotificationEntryManager}. * Will not be necessary when using the new notification pipeline's {@link NotifCollection}. * Instead, this is taken care of by {@link BubbleCoordinator}. */ private DismissedByUserStats getDismissedByUserStats( NotificationEntry entry, boolean isVisible) { return new DismissedByUserStats( DISMISSAL_BUBBLE, DISMISS_SENTIMENT_NEUTRAL, NotificationVisibility.obtain( entry.getKey(), entry.getRanking().getRank(), mNotificationEntryManager.getActiveNotificationsCount(), isVisible, NotificationLogger.getNotificationLocation(entry))); } /** * Updates the visibility of the bubbles based on current state. * Does not un-bubble, just hides or un-hides. Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +47 −59 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ package com.android.systemui.statusbar.notification; import static android.service.notification.NotificationListenerService.REASON_CANCEL; import static android.service.notification.NotificationListenerService.REASON_ERROR; import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_UNKNOWN; Loading @@ -24,14 +23,11 @@ import static com.android.systemui.statusbar.notification.row.NotificationRowCon import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.NotificationStats; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; import android.util.ArraySet; Loading @@ -41,7 +37,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.Dumpable; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLifetimeExtender; import com.android.systemui.statusbar.NotificationListener; Loading @@ -54,11 +49,11 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.dagger.NotificationsModule; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.util.Assert; import com.android.systemui.util.leak.LeakDetector; Loading Loading @@ -147,8 +142,6 @@ public class NotificationEntryManager implements private final NotificationRankingManager mRankingManager; private final FeatureFlags mFeatureFlags; private final ForegroundServiceDismissalFeatureController mFgsFeatureController; private final HeadsUpManager mHeadsUpManager; private final StatusBarStateController mStatusBarStateController; private NotificationPresenter mPresenter; private RankingMap mLatestRankingMap; Loading Loading @@ -213,8 +206,7 @@ public class NotificationEntryManager implements Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy, LeakDetector leakDetector, ForegroundServiceDismissalFeatureController fgsFeatureController, HeadsUpManager headsUpManager, StatusBarStateController statusBarStateController IStatusBarService statusBarService ) { mLogger = logger; mGroupManager = groupManager; Loading @@ -225,11 +217,7 @@ public class NotificationEntryManager implements mRemoteInputManagerLazy = notificationRemoteInputManagerLazy; mLeakDetector = leakDetector; mFgsFeatureController = fgsFeatureController; mHeadsUpManager = headsUpManager; mStatusBarStateController = statusBarStateController; mStatusBarService = IStatusBarService.Stub.asInterface( ServiceManager.checkService(Context.STATUS_BAR_SERVICE)); mStatusBarService = statusBarService; } /** Once called, the NEM will start processing notification events from system server. */ Loading Loading @@ -284,16 +272,23 @@ public class NotificationEntryManager implements } /** * Requests a notification to be removed. * User requests a notification to be removed. * * @param n the notification to remove. * @param reason why it is being removed e.g. {@link NotificationListenerService#REASON_CANCEL}, * or 0 if unknown. */ public void performRemoveNotification(StatusBarNotification n, int reason) { final NotificationVisibility nv = obtainVisibility(n.getKey()); public void performRemoveNotification( StatusBarNotification n, @NonNull DismissedByUserStats stats, int reason ) { removeNotificationInternal( n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */, n.getKey(), null, stats.notificationVisibility, false /* forceRemove */, stats, reason); } Loading Loading @@ -337,7 +332,11 @@ public class NotificationEntryManager implements */ private void handleInflationException(StatusBarNotification n, Exception e) { removeNotificationInternal( n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */, n.getKey(), null, null, true /* forceRemove */, null /* dismissedByUserStats */, REASON_ERROR); for (NotificationEntryListener listener : mNotificationEntryListeners) { listener.onInflationError(n, e); Loading Loading @@ -435,19 +434,28 @@ public class NotificationEntryManager implements reapplyFilterAndSort("addVisibleNotification"); } public void removeNotification(String key, RankingMap ranking, int reason) { removeNotificationInternal(key, ranking, obtainVisibility(key), false /* forceRemove */, false /* removedByUser */, reason); @VisibleForTesting protected void removeNotification(String key, RankingMap ranking, int reason) { removeNotificationInternal( key, ranking, obtainVisibility(key), false /* forceRemove */, null /* dismissedByUserStats */, reason); } /** * Internally remove a notification because system server has reported the notification * should be removed OR the user has manually dismissed the notification * @param dismissedByUserStats non-null if the user manually dismissed the notification */ private void removeNotificationInternal( String key, @Nullable RankingMap ranking, @Nullable NotificationVisibility visibility, boolean forceRemove, boolean removedByUser, DismissedByUserStats dismissedByUserStats, int reason) { final NotificationEntry entry = getActiveNotificationUnfiltered(key); Loading Loading @@ -512,11 +520,11 @@ public class NotificationEntryManager implements handleGroupSummaryRemoved(key); removeVisibleNotification(key); updateNotifications("removeNotificationInternal"); removedByUser |= entryDismissed; final boolean removedByUser = dismissedByUserStats != null; mLogger.logNotifRemoved(entry.getKey(), removedByUser); if (removedByUser && visibility != null) { sendNotificationRemovalToServer(entry.getKey(), entry.getSbn(), visibility); sendNotificationRemovalToServer(entry.getSbn(), dismissedByUserStats); } for (NotificationEntryListener listener : mNotificationEntryListeners) { listener.onEntryRemoved(entry, visibility, removedByUser, reason); Loading @@ -534,30 +542,18 @@ public class NotificationEntryManager implements } private void sendNotificationRemovalToServer( String key, StatusBarNotification notification, NotificationVisibility nv) { final String pkg = notification.getPackageName(); final String tag = notification.getTag(); final int id = notification.getId(); final int userId = notification.getUser().getIdentifier(); DismissedByUserStats dismissedByUserStats) { try { int dismissalSurface = NotificationStats.DISMISSAL_SHADE; if (mHeadsUpManager.isAlerting(key)) { dismissalSurface = NotificationStats.DISMISSAL_PEEK; } else if (mStatusBarStateController.isDozing()) { dismissalSurface = NotificationStats.DISMISSAL_AOD; } int dismissalSentiment = NotificationStats.DISMISS_SENTIMENT_NEUTRAL; mStatusBarService.onNotificationClear( pkg, tag, id, userId, notification.getPackageName(), notification.getTag(), notification.getId(), notification.getUser().getIdentifier(), notification.getKey(), dismissalSurface, dismissalSentiment, nv); dismissedByUserStats.dismissalSurface, dismissedByUserStats.dismissalSentiment, dismissedByUserStats.notificationVisibility); } catch (RemoteException ex) { // system process is dead if we're here. } Loading Loading @@ -641,11 +637,7 @@ public class NotificationEntryManager implements // Construct the expanded view. if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { mNotificationRowBinderLazy.get() .inflateViews( entry, () -> performRemoveNotification(notification, REASON_CANCEL), mInflationCallback); mNotificationRowBinderLazy.get().inflateViews(entry, mInflationCallback); } mPendingNotifications.put(key, entry); Loading Loading @@ -675,7 +667,7 @@ public class NotificationEntryManager implements final String key = notification.getKey(); abortExistingInflation(key, "updateNotification"); NotificationEntry entry = getActiveNotificationUnfiltered(key); final NotificationEntry entry = getActiveNotificationUnfiltered(key); if (entry == null) { return; } Loading @@ -701,11 +693,7 @@ public class NotificationEntryManager implements } if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { mNotificationRowBinderLazy.get() .inflateViews( entry, () -> performRemoveNotification(notification, REASON_CANCEL), mInflationCallback); mNotificationRowBinderLazy.get().inflateViews(entry, mInflationCallback); } updateNotifications("updateNotificationInternal"); Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java +0 −32 Original line number Diff line number Diff line Loading @@ -16,17 +16,10 @@ package com.android.systemui.statusbar.notification.collection; import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; import android.service.notification.NotificationStats; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.statusbar.notification.InflationException; import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager; import com.android.systemui.statusbar.notification.row.NotificationContentInflater; Loading Loading @@ -81,7 +74,6 @@ public class NotifInflaterImpl implements NotifInflater { try { requireBinder().inflateViews( entry, getDismissCallback(entry), wrapInflationCallback(callback)); } catch (InflationException e) { mNotifErrorManager.setInflationError(entry, e); Loading @@ -93,30 +85,6 @@ public class NotifInflaterImpl implements NotifInflater { entry.abortTask(); } private Runnable getDismissCallback(NotificationEntry entry) { return new Runnable() { @Override public void run() { int dismissalSurface = NotificationStats.DISMISSAL_SHADE; /* * TODO: determine dismissal surface (ie: shade / headsup / aod) * see {@link NotificationLogger#logNotificationClear} */ mNotifCollection.dismissNotification( entry, new DismissedByUserStats( dismissalSurface, DISMISS_SENTIMENT_NEUTRAL, NotificationVisibility.obtain(entry.getKey(), entry.getRanking().getRank(), mNotifPipeline.getShadeListCount(), true, NotificationLogger.getNotificationLocation(entry)) )); } }; } private NotificationContentInflater.InflationCallback wrapInflationCallback( InflationCallback callback) { return new NotificationContentInflater.InflationCallback() { Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java +7 −21 Original line number Diff line number Diff line Loading @@ -16,10 +16,6 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import static android.service.notification.NotificationStats.DISMISSAL_OTHER; import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; Loading @@ -27,7 +23,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import java.util.HashSet; import java.util.Set; Loading Loading @@ -101,7 +96,6 @@ public class BubbleCoordinator implements Coordinator { @Override public boolean shouldInterceptDismissal(NotificationEntry entry) { // TODO: b/149041810 add support for intercepting app-cancelled bubble notifications // for experimental bubbles if (mBubbleController.handleDismissalInterception(entry)) { mInterceptedDismissalEntries.add(entry.getKey()); Loading @@ -121,17 +115,21 @@ public class BubbleCoordinator implements Coordinator { private final BubbleController.NotifCallback mNotifCallback = new BubbleController.NotifCallback() { @Override public void removeNotification(NotificationEntry entry, int reason) { public void removeNotification( NotificationEntry entry, DismissedByUserStats dismissedByUserStats, int reason ) { if (isInterceptingDismissal(entry)) { mInterceptedDismissalEntries.remove(entry.getKey()); mOnEndDismissInterception.onEndDismissInterception(mDismissInterceptor, entry, createDismissedByUserStats(entry)); dismissedByUserStats); } else if (mNotifPipeline.getAllNotifs().contains(entry)) { // Bubbles are hiding the notifications from the shade, but the bubble was // deleted; therefore, the notification should be cancelled as if it were a user // dismissal (this won't re-enter handleInterceptDimissal because Bubbles // will have already marked it as no longer a bubble) mNotifCollection.dismissNotification(entry, createDismissedByUserStats(entry)); mNotifCollection.dismissNotification(entry, dismissedByUserStats); } } Loading @@ -149,16 +147,4 @@ public class BubbleCoordinator implements Coordinator { private boolean isInterceptingDismissal(NotificationEntry entry) { return mInterceptedDismissalEntries.contains(entry.getKey()); } private DismissedByUserStats createDismissedByUserStats(NotificationEntry entry) { return new DismissedByUserStats( DISMISSAL_OTHER, DISMISS_SENTIMENT_NEUTRAL, NotificationVisibility.obtain(entry.getKey(), entry.getRanking().getRank(), mNotifPipeline.getShadeListCount(), true, // was visible as a bubble NotificationLogger.getNotificationLocation(entry)) ); } } Loading
core/java/android/service/notification/NotificationStats.java +5 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,11 @@ public final class NotificationStats implements Parcelable { * Notification has been dismissed from the notification shade. */ public static final int DISMISSAL_SHADE = 3; /** * Notification has been dismissed as a bubble. * @hide */ public static final int DISMISSAL_BUBBLE = 3; /** @hide */ @IntDef(prefix = { "DISMISS_SENTIMENT_" }, value = { Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +52 −9 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import static android.service.notification.NotificationListenerService.REASON_CA import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL; import static android.service.notification.NotificationListenerService.REASON_CLICK; import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED; import static android.service.notification.NotificationStats.DISMISSAL_BUBBLE; import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.View.INVISIBLE; Loading Loading @@ -100,8 +102,11 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.coordinator.BubbleCoordinator; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.ScrimController; Loading Loading @@ -277,7 +282,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * This can happen when an app cancels a bubbled notification or when the user dismisses a * bubble. */ void removeNotification(@NonNull NotificationEntry entry, int reason); void removeNotification( @NonNull NotificationEntry entry, @NonNull DismissedByUserStats stats, int reason); /** * Called when a bubbled notification has changed whether it should be Loading Loading @@ -543,6 +551,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } }); // The new pipeline takes care of this as a NotifDismissInterceptor BubbleCoordinator mNotificationEntryManager.addNotificationRemoveInterceptor( new NotificationRemoveInterceptor() { @Override Loading @@ -551,7 +560,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi NotificationEntry entry, int dismissReason) { final boolean isClearAll = dismissReason == REASON_CANCEL_ALL; final boolean isUserDimiss = dismissReason == REASON_CANCEL final boolean isUserDismiss = dismissReason == REASON_CANCEL || dismissReason == REASON_CLICK; final boolean isAppCancel = dismissReason == REASON_APP_CANCEL || dismissReason == REASON_APP_CANCEL_ALL; Loading @@ -562,7 +571,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi // previously been dismissed & entry.isRowDismissed would still be true boolean userRemovedNotif = (entry != null && entry.isRowDismissed() && !isAppCancel) || isClearAll || isUserDimiss || isSummaryCancel; || isClearAll || isUserDismiss || isSummaryCancel; if (userRemovedNotif) { return handleDismissalInterception(entry); Loading Loading @@ -591,8 +600,13 @@ public class BubbleController implements ConfigurationController.ConfigurationLi addNotifCallback(new NotifCallback() { @Override public void removeNotification(NotificationEntry entry, int reason) { mNotificationEntryManager.performRemoveNotification(entry.getSbn(), reason); public void removeNotification( NotificationEntry entry, DismissedByUserStats dismissedByUserStats, int reason ) { mNotificationEntryManager.performRemoveNotification(entry.getSbn(), dismissedByUserStats, reason); } @Override Loading @@ -612,7 +626,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mNotificationEntryManager.getActiveNotificationUnfiltered( mBubbleData.getSummaryKey(groupKey)); if (summary != null) { mNotificationEntryManager.performRemoveNotification(summary.getSbn(), mNotificationEntryManager.performRemoveNotification( summary.getSbn(), getDismissedByUserStats(summary, false), UNDEFINED_DISMISS_REASON); } } Loading @@ -634,7 +650,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi boolean isSummaryThisNotif = summary.getKey().equals(entry.getKey()); if (!isSummaryThisNotif && (summaryChildren == null || summaryChildren.isEmpty())) { mNotificationEntryManager.performRemoveNotification(summary.getSbn(), mNotificationEntryManager.performRemoveNotification( summary.getSbn(), getDismissedByUserStats(summary, false), UNDEFINED_DISMISS_REASON); } } Loading Loading @@ -1331,7 +1349,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi // time to actually remove it for (NotifCallback cb : mCallbacks) { if (entry != null) { cb.removeNotification(entry, REASON_CANCEL); cb.removeNotification( entry, getDismissedByUserStats(entry, true), REASON_CANCEL); } } } else { Loading Loading @@ -1487,7 +1508,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } else { // non-bubbled children can be removed for (NotifCallback cb : mCallbacks) { cb.removeNotification(child, REASON_GROUP_SUMMARY_CANCELED); cb.removeNotification( child, getDismissedByUserStats(child, true), REASON_GROUP_SUMMARY_CANCELED); } } } Loading @@ -1501,6 +1525,25 @@ public class BubbleController implements ConfigurationController.ConfigurationLi summary.getKey()); } /** * Gets the DismissedByUserStats used by {@link NotificationEntryManager}. * Will not be necessary when using the new notification pipeline's {@link NotifCollection}. * Instead, this is taken care of by {@link BubbleCoordinator}. */ private DismissedByUserStats getDismissedByUserStats( NotificationEntry entry, boolean isVisible) { return new DismissedByUserStats( DISMISSAL_BUBBLE, DISMISS_SENTIMENT_NEUTRAL, NotificationVisibility.obtain( entry.getKey(), entry.getRanking().getRank(), mNotificationEntryManager.getActiveNotificationsCount(), isVisible, NotificationLogger.getNotificationLocation(entry))); } /** * Updates the visibility of the bubbles based on current state. * Does not un-bubble, just hides or un-hides. Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +47 −59 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ package com.android.systemui.statusbar.notification; import static android.service.notification.NotificationListenerService.REASON_CANCEL; import static android.service.notification.NotificationListenerService.REASON_ERROR; import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_UNKNOWN; Loading @@ -24,14 +23,11 @@ import static com.android.systemui.statusbar.notification.row.NotificationRowCon import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.NotificationStats; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; import android.util.ArraySet; Loading @@ -41,7 +37,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.Dumpable; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLifetimeExtender; import com.android.systemui.statusbar.NotificationListener; Loading @@ -54,11 +49,11 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.dagger.NotificationsModule; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.util.Assert; import com.android.systemui.util.leak.LeakDetector; Loading Loading @@ -147,8 +142,6 @@ public class NotificationEntryManager implements private final NotificationRankingManager mRankingManager; private final FeatureFlags mFeatureFlags; private final ForegroundServiceDismissalFeatureController mFgsFeatureController; private final HeadsUpManager mHeadsUpManager; private final StatusBarStateController mStatusBarStateController; private NotificationPresenter mPresenter; private RankingMap mLatestRankingMap; Loading Loading @@ -213,8 +206,7 @@ public class NotificationEntryManager implements Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy, LeakDetector leakDetector, ForegroundServiceDismissalFeatureController fgsFeatureController, HeadsUpManager headsUpManager, StatusBarStateController statusBarStateController IStatusBarService statusBarService ) { mLogger = logger; mGroupManager = groupManager; Loading @@ -225,11 +217,7 @@ public class NotificationEntryManager implements mRemoteInputManagerLazy = notificationRemoteInputManagerLazy; mLeakDetector = leakDetector; mFgsFeatureController = fgsFeatureController; mHeadsUpManager = headsUpManager; mStatusBarStateController = statusBarStateController; mStatusBarService = IStatusBarService.Stub.asInterface( ServiceManager.checkService(Context.STATUS_BAR_SERVICE)); mStatusBarService = statusBarService; } /** Once called, the NEM will start processing notification events from system server. */ Loading Loading @@ -284,16 +272,23 @@ public class NotificationEntryManager implements } /** * Requests a notification to be removed. * User requests a notification to be removed. * * @param n the notification to remove. * @param reason why it is being removed e.g. {@link NotificationListenerService#REASON_CANCEL}, * or 0 if unknown. */ public void performRemoveNotification(StatusBarNotification n, int reason) { final NotificationVisibility nv = obtainVisibility(n.getKey()); public void performRemoveNotification( StatusBarNotification n, @NonNull DismissedByUserStats stats, int reason ) { removeNotificationInternal( n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */, n.getKey(), null, stats.notificationVisibility, false /* forceRemove */, stats, reason); } Loading Loading @@ -337,7 +332,11 @@ public class NotificationEntryManager implements */ private void handleInflationException(StatusBarNotification n, Exception e) { removeNotificationInternal( n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */, n.getKey(), null, null, true /* forceRemove */, null /* dismissedByUserStats */, REASON_ERROR); for (NotificationEntryListener listener : mNotificationEntryListeners) { listener.onInflationError(n, e); Loading Loading @@ -435,19 +434,28 @@ public class NotificationEntryManager implements reapplyFilterAndSort("addVisibleNotification"); } public void removeNotification(String key, RankingMap ranking, int reason) { removeNotificationInternal(key, ranking, obtainVisibility(key), false /* forceRemove */, false /* removedByUser */, reason); @VisibleForTesting protected void removeNotification(String key, RankingMap ranking, int reason) { removeNotificationInternal( key, ranking, obtainVisibility(key), false /* forceRemove */, null /* dismissedByUserStats */, reason); } /** * Internally remove a notification because system server has reported the notification * should be removed OR the user has manually dismissed the notification * @param dismissedByUserStats non-null if the user manually dismissed the notification */ private void removeNotificationInternal( String key, @Nullable RankingMap ranking, @Nullable NotificationVisibility visibility, boolean forceRemove, boolean removedByUser, DismissedByUserStats dismissedByUserStats, int reason) { final NotificationEntry entry = getActiveNotificationUnfiltered(key); Loading Loading @@ -512,11 +520,11 @@ public class NotificationEntryManager implements handleGroupSummaryRemoved(key); removeVisibleNotification(key); updateNotifications("removeNotificationInternal"); removedByUser |= entryDismissed; final boolean removedByUser = dismissedByUserStats != null; mLogger.logNotifRemoved(entry.getKey(), removedByUser); if (removedByUser && visibility != null) { sendNotificationRemovalToServer(entry.getKey(), entry.getSbn(), visibility); sendNotificationRemovalToServer(entry.getSbn(), dismissedByUserStats); } for (NotificationEntryListener listener : mNotificationEntryListeners) { listener.onEntryRemoved(entry, visibility, removedByUser, reason); Loading @@ -534,30 +542,18 @@ public class NotificationEntryManager implements } private void sendNotificationRemovalToServer( String key, StatusBarNotification notification, NotificationVisibility nv) { final String pkg = notification.getPackageName(); final String tag = notification.getTag(); final int id = notification.getId(); final int userId = notification.getUser().getIdentifier(); DismissedByUserStats dismissedByUserStats) { try { int dismissalSurface = NotificationStats.DISMISSAL_SHADE; if (mHeadsUpManager.isAlerting(key)) { dismissalSurface = NotificationStats.DISMISSAL_PEEK; } else if (mStatusBarStateController.isDozing()) { dismissalSurface = NotificationStats.DISMISSAL_AOD; } int dismissalSentiment = NotificationStats.DISMISS_SENTIMENT_NEUTRAL; mStatusBarService.onNotificationClear( pkg, tag, id, userId, notification.getPackageName(), notification.getTag(), notification.getId(), notification.getUser().getIdentifier(), notification.getKey(), dismissalSurface, dismissalSentiment, nv); dismissedByUserStats.dismissalSurface, dismissedByUserStats.dismissalSentiment, dismissedByUserStats.notificationVisibility); } catch (RemoteException ex) { // system process is dead if we're here. } Loading Loading @@ -641,11 +637,7 @@ public class NotificationEntryManager implements // Construct the expanded view. if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { mNotificationRowBinderLazy.get() .inflateViews( entry, () -> performRemoveNotification(notification, REASON_CANCEL), mInflationCallback); mNotificationRowBinderLazy.get().inflateViews(entry, mInflationCallback); } mPendingNotifications.put(key, entry); Loading Loading @@ -675,7 +667,7 @@ public class NotificationEntryManager implements final String key = notification.getKey(); abortExistingInflation(key, "updateNotification"); NotificationEntry entry = getActiveNotificationUnfiltered(key); final NotificationEntry entry = getActiveNotificationUnfiltered(key); if (entry == null) { return; } Loading @@ -701,11 +693,7 @@ public class NotificationEntryManager implements } if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { mNotificationRowBinderLazy.get() .inflateViews( entry, () -> performRemoveNotification(notification, REASON_CANCEL), mInflationCallback); mNotificationRowBinderLazy.get().inflateViews(entry, mInflationCallback); } updateNotifications("updateNotificationInternal"); Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java +0 −32 Original line number Diff line number Diff line Loading @@ -16,17 +16,10 @@ package com.android.systemui.statusbar.notification.collection; import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; import android.service.notification.NotificationStats; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.statusbar.notification.InflationException; import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager; import com.android.systemui.statusbar.notification.row.NotificationContentInflater; Loading Loading @@ -81,7 +74,6 @@ public class NotifInflaterImpl implements NotifInflater { try { requireBinder().inflateViews( entry, getDismissCallback(entry), wrapInflationCallback(callback)); } catch (InflationException e) { mNotifErrorManager.setInflationError(entry, e); Loading @@ -93,30 +85,6 @@ public class NotifInflaterImpl implements NotifInflater { entry.abortTask(); } private Runnable getDismissCallback(NotificationEntry entry) { return new Runnable() { @Override public void run() { int dismissalSurface = NotificationStats.DISMISSAL_SHADE; /* * TODO: determine dismissal surface (ie: shade / headsup / aod) * see {@link NotificationLogger#logNotificationClear} */ mNotifCollection.dismissNotification( entry, new DismissedByUserStats( dismissalSurface, DISMISS_SENTIMENT_NEUTRAL, NotificationVisibility.obtain(entry.getKey(), entry.getRanking().getRank(), mNotifPipeline.getShadeListCount(), true, NotificationLogger.getNotificationLocation(entry)) )); } }; } private NotificationContentInflater.InflationCallback wrapInflationCallback( InflationCallback callback) { return new NotificationContentInflater.InflationCallback() { Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java +7 −21 Original line number Diff line number Diff line Loading @@ -16,10 +16,6 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import static android.service.notification.NotificationStats.DISMISSAL_OTHER; import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; Loading @@ -27,7 +23,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import java.util.HashSet; import java.util.Set; Loading Loading @@ -101,7 +96,6 @@ public class BubbleCoordinator implements Coordinator { @Override public boolean shouldInterceptDismissal(NotificationEntry entry) { // TODO: b/149041810 add support for intercepting app-cancelled bubble notifications // for experimental bubbles if (mBubbleController.handleDismissalInterception(entry)) { mInterceptedDismissalEntries.add(entry.getKey()); Loading @@ -121,17 +115,21 @@ public class BubbleCoordinator implements Coordinator { private final BubbleController.NotifCallback mNotifCallback = new BubbleController.NotifCallback() { @Override public void removeNotification(NotificationEntry entry, int reason) { public void removeNotification( NotificationEntry entry, DismissedByUserStats dismissedByUserStats, int reason ) { if (isInterceptingDismissal(entry)) { mInterceptedDismissalEntries.remove(entry.getKey()); mOnEndDismissInterception.onEndDismissInterception(mDismissInterceptor, entry, createDismissedByUserStats(entry)); dismissedByUserStats); } else if (mNotifPipeline.getAllNotifs().contains(entry)) { // Bubbles are hiding the notifications from the shade, but the bubble was // deleted; therefore, the notification should be cancelled as if it were a user // dismissal (this won't re-enter handleInterceptDimissal because Bubbles // will have already marked it as no longer a bubble) mNotifCollection.dismissNotification(entry, createDismissedByUserStats(entry)); mNotifCollection.dismissNotification(entry, dismissedByUserStats); } } Loading @@ -149,16 +147,4 @@ public class BubbleCoordinator implements Coordinator { private boolean isInterceptingDismissal(NotificationEntry entry) { return mInterceptedDismissalEntries.contains(entry.getKey()); } private DismissedByUserStats createDismissedByUserStats(NotificationEntry entry) { return new DismissedByUserStats( DISMISSAL_OTHER, DISMISS_SENTIMENT_NEUTRAL, NotificationVisibility.obtain(entry.getKey(), entry.getRanking().getRank(), mNotifPipeline.getShadeListCount(), true, // was visible as a bubble NotificationLogger.getNotificationLocation(entry)) ); } }