Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +52 −23 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.systemui.bubbles; 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_CANCEL; import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.View.INVISIBLE; Loading Loading @@ -53,13 +57,13 @@ import androidx.annotation.MainThread; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.statusbar.NotificationRemoveInterceptor; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider; Loading Loading @@ -210,6 +214,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); mNotificationEntryManager.addNotificationEntryListener(mEntryListener); mNotificationEntryManager.setNotificationRemoveInterceptor(mRemoveInterceptor); mStatusBarWindowController = statusBarWindowController; mStatusBarStateListener = new StatusBarStateListener(); Loading Loading @@ -388,6 +393,46 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } @SuppressWarnings("FieldCanBeLocal") private final NotificationRemoveInterceptor mRemoveInterceptor = new NotificationRemoveInterceptor() { @Override public boolean onNotificationRemoveRequested(String key, int reason) { if (!mBubbleData.hasBubbleWithKey(key)) { return false; } NotificationEntry entry = mBubbleData.getBubbleWithKey(key).entry; final boolean isClearAll = reason == REASON_CANCEL_ALL; final boolean isUserDimiss = reason == REASON_CANCEL; final boolean isAppCancel = reason == REASON_APP_CANCEL || reason == REASON_APP_CANCEL_ALL; // Need to check for !appCancel here because the notification may have // previously been dismissed & entry.isRowDismissed would still be true boolean userRemovedNotif = (entry.isRowDismissed() && !isAppCancel) || isClearAll || isUserDimiss; // The bubble notification sticks around in the data as long as the bubble is // not dismissed and the app hasn't cancelled the notification. boolean bubbleExtended = entry.isBubble() && !entry.isBubbleDismissed() && userRemovedNotif; if (bubbleExtended) { entry.setShowInShadeWhenBubble(false); if (mStackView != null) { mStackView.updateDotVisibility(entry.key); } mNotificationEntryManager.updateNotifications(); return true; } else if (!userRemovedNotif && !entry.isBubbleDismissed()) { // This wasn't a user removal so we should remove the bubble as well mBubbleData.notificationEntryRemoved(entry, DISMISS_NOTIF_CANCEL); return false; } return false; } }; @SuppressWarnings("FieldCanBeLocal") private final NotificationEntryListener mEntryListener = new NotificationEntryListener() { @Override Loading @@ -396,7 +441,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi return; } if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) { // TODO: handle group summaries? updateShowInShadeForSuppressNotification(entry); } } Loading Loading @@ -426,23 +470,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi updateBubble(entry); } } @Override public void onEntryRemoved(NotificationEntry entry, @Nullable NotificationVisibility visibility, boolean removedByUser) { if (!areBubblesEnabled(mContext)) { return; } entry.setShowInShadeWhenBubble(false); if (mStackView != null) { mStackView.updateDotVisibility(entry.key); } if (!removedByUser) { // This was a cancel so we should remove the bubble removeBubble(entry.key, DISMISS_NOTIF_CANCEL); } } }; @SuppressWarnings("FieldCanBeLocal") Loading @@ -455,13 +482,15 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } @Override public void onBubbleRemoved(Bubble bubble, int reason) { public void onBubbleRemoved(Bubble bubble, @DismissReason int reason) { if (mStackView != null) { mStackView.removeBubble(bubble); } if (!bubble.entry.showInShadeWhenBubble()) { // The notification is gone & bubble is gone, time to actually remove it mNotificationEntryManager.performRemoveNotification(bubble.entry.notification); if (!mBubbleData.hasBubbleWithKey(bubble.getKey()) && !bubble.entry.showInShadeWhenBubble()) { // The bubble is gone & the notification is gone, time to actually remove it mNotificationEntryManager.performRemoveNotification(bubble.entry.notification, 0 /* reason */); } else { // The notification is still in the shade but we've removed the bubble so // lets make sure NoMan knows it's not a bubble anymore Loading packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java +10 −5 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ public class NotificationListener extends NotificationListenerWithPlugins { // Remove existing notification to avoid stale data. if (isUpdate) { mEntryManager.removeNotification(key, rankingMap); mEntryManager.removeNotification(key, rankingMap, 0 /* reason */); } else { mEntryManager.getNotificationData() .updateRanking(rankingMap); Loading @@ -121,17 +121,22 @@ public class NotificationListener extends NotificationListenerWithPlugins { } @Override public void onNotificationRemoved(StatusBarNotification sbn, final RankingMap rankingMap) { if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn); public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap, int reason) { if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn + " reason: " + reason); if (sbn != null && !onPluginNotificationRemoved(sbn, rankingMap)) { final String key = sbn.getKey(); Dependency.get(Dependency.MAIN_HANDLER).post(() -> { mEntryManager.removeNotification(key, rankingMap); mEntryManager.removeNotification(key, rankingMap, reason); }); } } @Override public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) { onNotificationRemoved(sbn, rankingMap, 0 /* reason */); } @Override public void onNotificationRankingUpdate(final RankingMap rankingMap) { if (DEBUG) Log.d(TAG, "onRankingUpdate"); Loading packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoveInterceptor.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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; import android.service.notification.NotificationListenerService; /** * Interface for anything that may need to prevent notifications from being removed. This is * similar to a {@link NotificationLifetimeExtender} in the sense that it extends the life of * a notification by preventing the removal, however, unlike the extender, the remove interceptor * gets first pick at intercepting any type of removal -- the life time extender is unable to * extend the life of a user dismissed or force removed notification. */ public interface NotificationRemoveInterceptor { /** * Called when a notification has been removed. * * @param key the entry key of the notification being removed. * @param removeReason why the notification is being removed, e.g. * {@link NotificationListenerService#REASON_CANCEL} or 0 if unknown. * * @return true if the removal should be ignored, false otherwise. */ boolean onNotificationRemoveRequested(String key, int removeReason); } packages/SystemUI/src/com/android/systemui/statusbar/NotificationUpdateHandler.java +3 −1 Original line number Diff line number Diff line Loading @@ -37,8 +37,10 @@ public interface NotificationUpdateHandler { * * @param key Key identifying the notification to remove * @param ranking RankingMap to update with * @param reason why the notification is being removed, e.g. * {@link NotificationListenerService#REASON_CANCEL}. */ void removeNotification(String key, NotificationListenerService.RankingMap ranking); void removeNotification(String key, NotificationListenerService.RankingMap ranking, int reason); /** * Update a given notification and the current notification ranking map. Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +39 −9 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ */ package com.android.systemui.statusbar.notification; import static android.service.notification.NotificationListenerService.REASON_CANCEL; import static android.service.notification.NotificationListenerService.REASON_ERROR; import android.annotation.Nullable; import android.app.Notification; import android.content.Context; Loading @@ -30,6 +33,7 @@ import com.android.systemui.Dumpable; import com.android.systemui.statusbar.NotificationLifetimeExtender; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationRemoveInterceptor; import com.android.systemui.statusbar.NotificationUiAdjustment; import com.android.systemui.statusbar.NotificationUpdateHandler; import com.android.systemui.statusbar.notification.collection.NotificationData; Loading Loading @@ -82,6 +86,7 @@ public class NotificationEntryManager implements final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders = new ArrayList<>(); private final List<NotificationEntryListener> mNotificationEntryListeners = new ArrayList<>(); private NotificationRemoveInterceptor mRemoveInterceptor; @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { Loading Loading @@ -115,6 +120,11 @@ public class NotificationEntryManager implements mNotificationEntryListeners.add(listener); } /** Sets the {@link NotificationRemoveInterceptor}. */ public void setNotificationRemoveInterceptor(NotificationRemoveInterceptor interceptor) { mRemoveInterceptor = interceptor; } /** * Our dependencies can have cyclic references, so some need to be lazy */ Loading Loading @@ -146,7 +156,7 @@ public class NotificationEntryManager implements /** Adds a {@link NotificationLifetimeExtender}. */ public void addNotificationLifetimeExtender(NotificationLifetimeExtender extender) { mNotificationLifetimeExtenders.add(extender); extender.setCallback(key -> removeNotification(key, mLatestRankingMap)); extender.setCallback(key -> removeNotification(key, mLatestRankingMap, 0)); } public NotificationData getNotificationData() { Loading @@ -158,10 +168,18 @@ public class NotificationEntryManager implements updateNotifications(); } public void performRemoveNotification(StatusBarNotification n) { /** * 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()); removeNotificationInternal( n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */); n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */, reason); } private NotificationVisibility obtainVisibility(String key) { Loading Loading @@ -193,7 +211,8 @@ public class NotificationEntryManager implements @Override public void handleInflationException(StatusBarNotification n, Exception e) { removeNotificationInternal( n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */); n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */, REASON_ERROR); for (NotificationEntryListener listener : mNotificationEntryListeners) { listener.onInflationError(n, e); } Loading Loading @@ -228,9 +247,10 @@ public class NotificationEntryManager implements } @Override public void removeNotification(String key, NotificationListenerService.RankingMap ranking) { public void removeNotification(String key, NotificationListenerService.RankingMap ranking, int reason) { removeNotificationInternal(key, ranking, obtainVisibility(key), false /* forceRemove */, false /* removedByUser */); false /* removedByUser */, reason); } private void removeNotificationInternal( Loading @@ -238,7 +258,15 @@ public class NotificationEntryManager implements @Nullable NotificationListenerService.RankingMap ranking, @Nullable NotificationVisibility visibility, boolean forceRemove, boolean removedByUser) { boolean removedByUser, int reason) { if (mRemoveInterceptor != null && mRemoveInterceptor.onNotificationRemoveRequested(key, reason)) { // Remove intercepted; skip return; } final NotificationEntry entry = mNotificationData.get(key); abortExistingInflation(key); Loading Loading @@ -342,7 +370,8 @@ public class NotificationEntryManager implements Dependency.get(LeakDetector.class).trackInstance(entry); // Construct the expanded view. requireBinder().inflateViews(entry, () -> performRemoveNotification(notification)); requireBinder().inflateViews(entry, () -> performRemoveNotification(notification, REASON_CANCEL)); abortExistingInflation(key); Loading Loading @@ -383,7 +412,8 @@ public class NotificationEntryManager implements listener.onPreEntryUpdated(entry); } requireBinder().inflateViews(entry, () -> performRemoveNotification(notification)); requireBinder().inflateViews(entry, () -> performRemoveNotification(notification, REASON_CANCEL)); updateNotifications(); if (DEBUG) { Loading Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +52 −23 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.systemui.bubbles; 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_CANCEL; import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.View.INVISIBLE; Loading Loading @@ -53,13 +57,13 @@ import androidx.annotation.MainThread; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.statusbar.NotificationRemoveInterceptor; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider; Loading Loading @@ -210,6 +214,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); mNotificationEntryManager.addNotificationEntryListener(mEntryListener); mNotificationEntryManager.setNotificationRemoveInterceptor(mRemoveInterceptor); mStatusBarWindowController = statusBarWindowController; mStatusBarStateListener = new StatusBarStateListener(); Loading Loading @@ -388,6 +393,46 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } @SuppressWarnings("FieldCanBeLocal") private final NotificationRemoveInterceptor mRemoveInterceptor = new NotificationRemoveInterceptor() { @Override public boolean onNotificationRemoveRequested(String key, int reason) { if (!mBubbleData.hasBubbleWithKey(key)) { return false; } NotificationEntry entry = mBubbleData.getBubbleWithKey(key).entry; final boolean isClearAll = reason == REASON_CANCEL_ALL; final boolean isUserDimiss = reason == REASON_CANCEL; final boolean isAppCancel = reason == REASON_APP_CANCEL || reason == REASON_APP_CANCEL_ALL; // Need to check for !appCancel here because the notification may have // previously been dismissed & entry.isRowDismissed would still be true boolean userRemovedNotif = (entry.isRowDismissed() && !isAppCancel) || isClearAll || isUserDimiss; // The bubble notification sticks around in the data as long as the bubble is // not dismissed and the app hasn't cancelled the notification. boolean bubbleExtended = entry.isBubble() && !entry.isBubbleDismissed() && userRemovedNotif; if (bubbleExtended) { entry.setShowInShadeWhenBubble(false); if (mStackView != null) { mStackView.updateDotVisibility(entry.key); } mNotificationEntryManager.updateNotifications(); return true; } else if (!userRemovedNotif && !entry.isBubbleDismissed()) { // This wasn't a user removal so we should remove the bubble as well mBubbleData.notificationEntryRemoved(entry, DISMISS_NOTIF_CANCEL); return false; } return false; } }; @SuppressWarnings("FieldCanBeLocal") private final NotificationEntryListener mEntryListener = new NotificationEntryListener() { @Override Loading @@ -396,7 +441,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi return; } if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) { // TODO: handle group summaries? updateShowInShadeForSuppressNotification(entry); } } Loading Loading @@ -426,23 +470,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi updateBubble(entry); } } @Override public void onEntryRemoved(NotificationEntry entry, @Nullable NotificationVisibility visibility, boolean removedByUser) { if (!areBubblesEnabled(mContext)) { return; } entry.setShowInShadeWhenBubble(false); if (mStackView != null) { mStackView.updateDotVisibility(entry.key); } if (!removedByUser) { // This was a cancel so we should remove the bubble removeBubble(entry.key, DISMISS_NOTIF_CANCEL); } } }; @SuppressWarnings("FieldCanBeLocal") Loading @@ -455,13 +482,15 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } @Override public void onBubbleRemoved(Bubble bubble, int reason) { public void onBubbleRemoved(Bubble bubble, @DismissReason int reason) { if (mStackView != null) { mStackView.removeBubble(bubble); } if (!bubble.entry.showInShadeWhenBubble()) { // The notification is gone & bubble is gone, time to actually remove it mNotificationEntryManager.performRemoveNotification(bubble.entry.notification); if (!mBubbleData.hasBubbleWithKey(bubble.getKey()) && !bubble.entry.showInShadeWhenBubble()) { // The bubble is gone & the notification is gone, time to actually remove it mNotificationEntryManager.performRemoveNotification(bubble.entry.notification, 0 /* reason */); } else { // The notification is still in the shade but we've removed the bubble so // lets make sure NoMan knows it's not a bubble anymore Loading
packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java +10 −5 Original line number Diff line number Diff line Loading @@ -104,7 +104,7 @@ public class NotificationListener extends NotificationListenerWithPlugins { // Remove existing notification to avoid stale data. if (isUpdate) { mEntryManager.removeNotification(key, rankingMap); mEntryManager.removeNotification(key, rankingMap, 0 /* reason */); } else { mEntryManager.getNotificationData() .updateRanking(rankingMap); Loading @@ -121,17 +121,22 @@ public class NotificationListener extends NotificationListenerWithPlugins { } @Override public void onNotificationRemoved(StatusBarNotification sbn, final RankingMap rankingMap) { if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn); public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap, int reason) { if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn + " reason: " + reason); if (sbn != null && !onPluginNotificationRemoved(sbn, rankingMap)) { final String key = sbn.getKey(); Dependency.get(Dependency.MAIN_HANDLER).post(() -> { mEntryManager.removeNotification(key, rankingMap); mEntryManager.removeNotification(key, rankingMap, reason); }); } } @Override public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) { onNotificationRemoved(sbn, rankingMap, 0 /* reason */); } @Override public void onNotificationRankingUpdate(final RankingMap rankingMap) { if (DEBUG) Log.d(TAG, "onRankingUpdate"); Loading
packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoveInterceptor.java 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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; import android.service.notification.NotificationListenerService; /** * Interface for anything that may need to prevent notifications from being removed. This is * similar to a {@link NotificationLifetimeExtender} in the sense that it extends the life of * a notification by preventing the removal, however, unlike the extender, the remove interceptor * gets first pick at intercepting any type of removal -- the life time extender is unable to * extend the life of a user dismissed or force removed notification. */ public interface NotificationRemoveInterceptor { /** * Called when a notification has been removed. * * @param key the entry key of the notification being removed. * @param removeReason why the notification is being removed, e.g. * {@link NotificationListenerService#REASON_CANCEL} or 0 if unknown. * * @return true if the removal should be ignored, false otherwise. */ boolean onNotificationRemoveRequested(String key, int removeReason); }
packages/SystemUI/src/com/android/systemui/statusbar/NotificationUpdateHandler.java +3 −1 Original line number Diff line number Diff line Loading @@ -37,8 +37,10 @@ public interface NotificationUpdateHandler { * * @param key Key identifying the notification to remove * @param ranking RankingMap to update with * @param reason why the notification is being removed, e.g. * {@link NotificationListenerService#REASON_CANCEL}. */ void removeNotification(String key, NotificationListenerService.RankingMap ranking); void removeNotification(String key, NotificationListenerService.RankingMap ranking, int reason); /** * Update a given notification and the current notification ranking map. Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +39 −9 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ */ package com.android.systemui.statusbar.notification; import static android.service.notification.NotificationListenerService.REASON_CANCEL; import static android.service.notification.NotificationListenerService.REASON_ERROR; import android.annotation.Nullable; import android.app.Notification; import android.content.Context; Loading @@ -30,6 +33,7 @@ import com.android.systemui.Dumpable; import com.android.systemui.statusbar.NotificationLifetimeExtender; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationRemoveInterceptor; import com.android.systemui.statusbar.NotificationUiAdjustment; import com.android.systemui.statusbar.NotificationUpdateHandler; import com.android.systemui.statusbar.notification.collection.NotificationData; Loading Loading @@ -82,6 +86,7 @@ public class NotificationEntryManager implements final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders = new ArrayList<>(); private final List<NotificationEntryListener> mNotificationEntryListeners = new ArrayList<>(); private NotificationRemoveInterceptor mRemoveInterceptor; @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { Loading Loading @@ -115,6 +120,11 @@ public class NotificationEntryManager implements mNotificationEntryListeners.add(listener); } /** Sets the {@link NotificationRemoveInterceptor}. */ public void setNotificationRemoveInterceptor(NotificationRemoveInterceptor interceptor) { mRemoveInterceptor = interceptor; } /** * Our dependencies can have cyclic references, so some need to be lazy */ Loading Loading @@ -146,7 +156,7 @@ public class NotificationEntryManager implements /** Adds a {@link NotificationLifetimeExtender}. */ public void addNotificationLifetimeExtender(NotificationLifetimeExtender extender) { mNotificationLifetimeExtenders.add(extender); extender.setCallback(key -> removeNotification(key, mLatestRankingMap)); extender.setCallback(key -> removeNotification(key, mLatestRankingMap, 0)); } public NotificationData getNotificationData() { Loading @@ -158,10 +168,18 @@ public class NotificationEntryManager implements updateNotifications(); } public void performRemoveNotification(StatusBarNotification n) { /** * 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()); removeNotificationInternal( n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */); n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */, reason); } private NotificationVisibility obtainVisibility(String key) { Loading Loading @@ -193,7 +211,8 @@ public class NotificationEntryManager implements @Override public void handleInflationException(StatusBarNotification n, Exception e) { removeNotificationInternal( n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */); n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */, REASON_ERROR); for (NotificationEntryListener listener : mNotificationEntryListeners) { listener.onInflationError(n, e); } Loading Loading @@ -228,9 +247,10 @@ public class NotificationEntryManager implements } @Override public void removeNotification(String key, NotificationListenerService.RankingMap ranking) { public void removeNotification(String key, NotificationListenerService.RankingMap ranking, int reason) { removeNotificationInternal(key, ranking, obtainVisibility(key), false /* forceRemove */, false /* removedByUser */); false /* removedByUser */, reason); } private void removeNotificationInternal( Loading @@ -238,7 +258,15 @@ public class NotificationEntryManager implements @Nullable NotificationListenerService.RankingMap ranking, @Nullable NotificationVisibility visibility, boolean forceRemove, boolean removedByUser) { boolean removedByUser, int reason) { if (mRemoveInterceptor != null && mRemoveInterceptor.onNotificationRemoveRequested(key, reason)) { // Remove intercepted; skip return; } final NotificationEntry entry = mNotificationData.get(key); abortExistingInflation(key); Loading Loading @@ -342,7 +370,8 @@ public class NotificationEntryManager implements Dependency.get(LeakDetector.class).trackInstance(entry); // Construct the expanded view. requireBinder().inflateViews(entry, () -> performRemoveNotification(notification)); requireBinder().inflateViews(entry, () -> performRemoveNotification(notification, REASON_CANCEL)); abortExistingInflation(key); Loading Loading @@ -383,7 +412,8 @@ public class NotificationEntryManager implements listener.onPreEntryUpdated(entry); } requireBinder().inflateViews(entry, () -> performRemoveNotification(notification)); requireBinder().inflateViews(entry, () -> performRemoveNotification(notification, REASON_CANCEL)); updateNotifications(); if (DEBUG) { Loading