1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.systemui.statusbar.phone;
16 
17 import static com.android.systemui.statusbar.phone.StatusBar.CLOSE_PANEL_WHEN_EMPTIED;
18 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
19 import static com.android.systemui.statusbar.phone.StatusBar.MULTIUSER_DEBUG;
20 
21 import android.app.KeyguardManager;
22 import android.content.Context;
23 import android.os.RemoteException;
24 import android.os.ServiceManager;
25 import android.os.SystemClock;
26 import android.service.notification.StatusBarNotification;
27 import android.service.vr.IVrManager;
28 import android.service.vr.IVrStateCallbacks;
29 import android.util.Log;
30 import android.util.Slog;
31 import android.view.View;
32 import android.view.accessibility.AccessibilityManager;
33 import android.widget.TextView;
34 
35 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
36 import com.android.internal.statusbar.IStatusBarService;
37 import com.android.internal.widget.MessagingGroup;
38 import com.android.internal.widget.MessagingMessage;
39 import com.android.keyguard.KeyguardUpdateMonitor;
40 import com.android.systemui.Dependency;
41 import com.android.systemui.ForegroundServiceNotificationListener;
42 import com.android.systemui.InitController;
43 import com.android.systemui.R;
44 import com.android.systemui.flags.FeatureFlags;
45 import com.android.systemui.plugins.ActivityStarter;
46 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
47 import com.android.systemui.statusbar.CommandQueue;
48 import com.android.systemui.statusbar.KeyguardIndicationController;
49 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
50 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
51 import com.android.systemui.statusbar.NotificationMediaManager;
52 import com.android.systemui.statusbar.NotificationPresenter;
53 import com.android.systemui.statusbar.NotificationRemoteInputManager;
54 import com.android.systemui.statusbar.NotificationShadeWindowController;
55 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
56 import com.android.systemui.statusbar.StatusBarState;
57 import com.android.systemui.statusbar.SysuiStatusBarStateController;
58 import com.android.systemui.statusbar.notification.AboveShelfObserver;
59 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
60 import com.android.systemui.statusbar.notification.NotificationEntryManager;
61 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
62 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
63 import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
64 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
65 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
66 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
67 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
68 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
69 import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
70 import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
71 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
72 import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
73 import com.android.systemui.statusbar.policy.ConfigurationController;
74 import com.android.systemui.statusbar.policy.KeyguardStateController;
75 
76 import java.util.List;
77 
78 public class StatusBarNotificationPresenter implements NotificationPresenter,
79         ConfigurationController.ConfigurationListener,
80         NotificationRowBinderImpl.BindRowCallback,
81         CommandQueue.Callbacks {
82     private static final String TAG = "StatusBarNotificationPresenter";
83 
84     private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
85     private final KeyguardStateController mKeyguardStateController;
86     private final NotificationViewHierarchyManager mViewHierarchyManager;
87     private final NotificationLockscreenUserManager mLockscreenUserManager;
88     private final SysuiStatusBarStateController mStatusBarStateController;
89     private final NotifShadeEventSource mNotifShadeEventSource;
90     private final NotificationEntryManager mEntryManager;
91     private final NotificationMediaManager mMediaManager;
92     private final NotificationGutsManager mGutsManager;
93     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
94     private final LockscreenGestureLogger mLockscreenGestureLogger;
95 
96     private final NotificationPanelViewController mNotificationPanel;
97     private final HeadsUpManagerPhone mHeadsUpManager;
98     private final AboveShelfObserver mAboveShelfObserver;
99     private final DozeScrimController mDozeScrimController;
100     private final ScrimController mScrimController;
101     private final KeyguardIndicationController mKeyguardIndicationController;
102     private final FeatureFlags mFeatureFlags;
103     private final StatusBar mStatusBar;
104     private final ShadeController mShadeController;
105     private final LockscreenShadeTransitionController mShadeTransitionController;
106     private final CommandQueue mCommandQueue;
107 
108     private final AccessibilityManager mAccessibilityManager;
109     private final KeyguardManager mKeyguardManager;
110     private final NotificationShadeWindowController mNotificationShadeWindowController;
111     private final IStatusBarService mBarService;
112     private final DynamicPrivacyController mDynamicPrivacyController;
113     private boolean mReinflateNotificationsOnUserSwitched;
114     private boolean mDispatchUiModeChangeOnUserSwitched;
115     private TextView mNotificationPanelDebugText;
116 
117     protected boolean mVrMode;
118 
StatusBarNotificationPresenter(Context context, NotificationPanelViewController panel, HeadsUpManagerPhone headsUp, NotificationShadeWindowView statusBarWindow, NotificationStackScrollLayoutController stackScrollerController, DozeScrimController dozeScrimController, ScrimController scrimController, NotificationShadeWindowController notificationShadeWindowController, DynamicPrivacyController dynamicPrivacyController, KeyguardStateController keyguardStateController, KeyguardIndicationController keyguardIndicationController, FeatureFlags featureFlags, StatusBar statusBar, ShadeController shadeController, LockscreenShadeTransitionController shadeTransitionController, CommandQueue commandQueue, NotificationViewHierarchyManager notificationViewHierarchyManager, NotificationLockscreenUserManager lockscreenUserManager, SysuiStatusBarStateController sysuiStatusBarStateController, NotifShadeEventSource notifShadeEventSource, NotificationEntryManager notificationEntryManager, NotificationMediaManager notificationMediaManager, NotificationGutsManager notificationGutsManager, KeyguardUpdateMonitor keyguardUpdateMonitor, LockscreenGestureLogger lockscreenGestureLogger, InitController initController, NotificationInterruptStateProvider notificationInterruptStateProvider, NotificationRemoteInputManager remoteInputManager, ConfigurationController configurationController)119     public StatusBarNotificationPresenter(Context context,
120             NotificationPanelViewController panel,
121             HeadsUpManagerPhone headsUp,
122             NotificationShadeWindowView statusBarWindow,
123             NotificationStackScrollLayoutController stackScrollerController,
124             DozeScrimController dozeScrimController,
125             ScrimController scrimController,
126             NotificationShadeWindowController notificationShadeWindowController,
127             DynamicPrivacyController dynamicPrivacyController,
128             KeyguardStateController keyguardStateController,
129             KeyguardIndicationController keyguardIndicationController,
130             FeatureFlags featureFlags,
131             StatusBar statusBar,
132             ShadeController shadeController,
133             LockscreenShadeTransitionController shadeTransitionController,
134             CommandQueue commandQueue,
135             NotificationViewHierarchyManager notificationViewHierarchyManager,
136             NotificationLockscreenUserManager lockscreenUserManager,
137             SysuiStatusBarStateController sysuiStatusBarStateController,
138             NotifShadeEventSource notifShadeEventSource,
139             NotificationEntryManager notificationEntryManager,
140             NotificationMediaManager notificationMediaManager,
141             NotificationGutsManager notificationGutsManager,
142             KeyguardUpdateMonitor keyguardUpdateMonitor,
143             LockscreenGestureLogger lockscreenGestureLogger,
144             InitController initController,
145             NotificationInterruptStateProvider notificationInterruptStateProvider,
146             NotificationRemoteInputManager remoteInputManager,
147             ConfigurationController configurationController) {
148         mKeyguardStateController = keyguardStateController;
149         mNotificationPanel = panel;
150         mHeadsUpManager = headsUp;
151         mDynamicPrivacyController = dynamicPrivacyController;
152         mKeyguardIndicationController = keyguardIndicationController;
153         mFeatureFlags = featureFlags;
154         // TODO: use KeyguardStateController#isOccluded to remove this dependency
155         mStatusBar = statusBar;
156         mShadeController = shadeController;
157         mShadeTransitionController = shadeTransitionController;
158         mCommandQueue = commandQueue;
159         mViewHierarchyManager = notificationViewHierarchyManager;
160         mLockscreenUserManager = lockscreenUserManager;
161         mStatusBarStateController = sysuiStatusBarStateController;
162         mNotifShadeEventSource = notifShadeEventSource;
163         mEntryManager = notificationEntryManager;
164         mMediaManager = notificationMediaManager;
165         mGutsManager = notificationGutsManager;
166         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
167         mLockscreenGestureLogger = lockscreenGestureLogger;
168         mAboveShelfObserver = new AboveShelfObserver(stackScrollerController.getView());
169         mNotificationShadeWindowController = notificationShadeWindowController;
170         mAboveShelfObserver.setListener(statusBarWindow.findViewById(
171                 R.id.notification_container_parent));
172         mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
173         mDozeScrimController = dozeScrimController;
174         mScrimController = scrimController;
175         mKeyguardManager = context.getSystemService(KeyguardManager.class);
176         mBarService = IStatusBarService.Stub.asInterface(
177                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
178 
179         IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
180                 Context.VR_SERVICE));
181         if (vrManager != null) {
182             try {
183                 vrManager.registerListener(mVrStateCallbacks);
184             } catch (RemoteException e) {
185                 Slog.e(TAG, "Failed to register VR mode state listener: " + e);
186             }
187         }
188         remoteInputManager.setUpWithCallback(
189                 Dependency.get(NotificationRemoteInputManager.Callback.class),
190                 mNotificationPanel.createRemoteInputDelegate());
191 
192         initController.addPostInitTask(() -> {
193             mKeyguardIndicationController.init();
194             mViewHierarchyManager.setUpWithPresenter(this,
195                     stackScrollerController.getNotificationListContainer());
196             mNotifShadeEventSource.setShadeEmptiedCallback(this::maybeClosePanelForShadeEmptied);
197             mNotifShadeEventSource.setNotifRemovedByUserCallback(this::maybeEndAmbientPulse);
198             if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
199                 mEntryManager.setUpWithPresenter(this);
200                 mEntryManager.addNotificationLifetimeExtender(mHeadsUpManager);
201                 mEntryManager.addNotificationLifetimeExtender(mGutsManager);
202                 mEntryManager.addNotificationLifetimeExtenders(
203                         remoteInputManager.getLifetimeExtenders());
204             }
205             notificationInterruptStateProvider.addSuppressor(mInterruptSuppressor);
206             mLockscreenUserManager.setUpWithPresenter(this);
207             mMediaManager.setUpWithPresenter(this);
208             mGutsManager.setUpWithPresenter(this,
209                     stackScrollerController.getNotificationListContainer(), mCheckSaveListener,
210                     mOnSettingsClickListener);
211             // ForegroundServiceNotificationListener adds its listener in its constructor
212             // but we need to request it here in order for it to be instantiated.
213             // TODO: figure out how to do this correctly once Dependency.get() is gone.
214             Dependency.get(ForegroundServiceNotificationListener.class);
215 
216             onUserSwitched(mLockscreenUserManager.getCurrentUserId());
217         });
218         configurationController.addCallback(this);
219     }
220 
221     /** Called when the shade has been emptied to attempt to close the shade */
maybeClosePanelForShadeEmptied()222     private void maybeClosePanelForShadeEmptied() {
223         if (CLOSE_PANEL_WHEN_EMPTIED
224                 && !mNotificationPanel.isTracking()
225                 && !mNotificationPanel.isQsExpanded()
226                 && mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED
227                 && !isCollapsing()) {
228             mStatusBarStateController.setState(StatusBarState.KEYGUARD);
229         }
230     }
231 
232     @Override
onDensityOrFontScaleChanged()233     public void onDensityOrFontScaleChanged() {
234         // TODO(b/145659174): Remove legacy pipeline code
235         if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
236         MessagingMessage.dropCache();
237         MessagingGroup.dropCache();
238         if (!mKeyguardUpdateMonitor.isSwitchingUser()) {
239             updateNotificationsOnDensityOrFontScaleChanged();
240         } else {
241             mReinflateNotificationsOnUserSwitched = true;
242         }
243     }
244 
245     @Override
onUiModeChanged()246     public void onUiModeChanged() {
247         // TODO(b/145659174): Remove legacy pipeline code
248         if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
249         if (!mKeyguardUpdateMonitor.isSwitchingUser()) {
250             updateNotificationsOnUiModeChanged();
251         } else {
252             mDispatchUiModeChangeOnUserSwitched = true;
253         }
254     }
255 
256     @Override
onThemeChanged()257     public void onThemeChanged() {
258         onDensityOrFontScaleChanged();
259     }
260 
updateNotificationsOnUiModeChanged()261     private void updateNotificationsOnUiModeChanged() {
262         // TODO(b/145659174): Remove legacy pipeline code
263         if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
264         List<NotificationEntry> userNotifications =
265                 mEntryManager.getActiveNotificationsForCurrentUser();
266         for (int i = 0; i < userNotifications.size(); i++) {
267             NotificationEntry entry = userNotifications.get(i);
268             ExpandableNotificationRow row = entry.getRow();
269             if (row != null) {
270                 row.onUiModeChanged();
271             }
272         }
273     }
274 
updateNotificationsOnDensityOrFontScaleChanged()275     private void updateNotificationsOnDensityOrFontScaleChanged() {
276         // TODO(b/145659174): Remove legacy pipeline code
277         if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
278         List<NotificationEntry> userNotifications =
279                 mEntryManager.getActiveNotificationsForCurrentUser();
280         for (int i = 0; i < userNotifications.size(); i++) {
281             NotificationEntry entry = userNotifications.get(i);
282             entry.onDensityOrFontScaleChanged();
283             boolean exposedGuts = entry.areGutsExposed();
284             if (exposedGuts) {
285                 mGutsManager.onDensityOrFontScaleChanged(entry);
286             }
287         }
288     }
289 
290 
291     @Override
isCollapsing()292     public boolean isCollapsing() {
293         return mNotificationPanel.isCollapsing()
294                 || mNotificationShadeWindowController.isLaunchingActivity();
295     }
296 
maybeEndAmbientPulse()297     private void maybeEndAmbientPulse() {
298         if (mNotificationPanel.hasPulsingNotifications() &&
299                 !mHeadsUpManager.hasNotifications()) {
300             // We were showing a pulse for a notification, but no notifications are pulsing anymore.
301             // Finish the pulse.
302             mDozeScrimController.pulseOutNow();
303         }
304     }
305 
306     @Override
updateNotificationViews(final String reason)307     public void updateNotificationViews(final String reason) {
308         // The function updateRowStates depends on both of these being non-null, so check them here.
309         // We may be called before they are set from DeviceProvisionedController's callback.
310         if (mScrimController == null) return;
311 
312         // Do not modify the notifications during collapse.
313         if (isCollapsing()) {
314             mShadeController.addPostCollapseAction(() -> updateNotificationViews(reason));
315             return;
316         }
317         mViewHierarchyManager.updateNotificationViews();
318         mNotificationPanel.updateNotificationViews(reason);
319     }
320 
321     @Override
onUserSwitched(int newUserId)322     public void onUserSwitched(int newUserId) {
323         // Begin old BaseStatusBar.userSwitched
324         mHeadsUpManager.setUser(newUserId);
325         // End old BaseStatusBar.userSwitched
326         if (MULTIUSER_DEBUG) mNotificationPanel.setHeaderDebugInfo("USER " + newUserId);
327         mCommandQueue.animateCollapsePanels();
328         if (mReinflateNotificationsOnUserSwitched) {
329             updateNotificationsOnDensityOrFontScaleChanged();
330             mReinflateNotificationsOnUserSwitched = false;
331         }
332         if (mDispatchUiModeChangeOnUserSwitched) {
333             updateNotificationsOnUiModeChanged();
334             mDispatchUiModeChangeOnUserSwitched = false;
335         }
336         updateNotificationViews("user switched");
337         mMediaManager.clearCurrentMediaNotification();
338         mStatusBar.setLockscreenUser(newUserId);
339         updateMediaMetaData(true, false);
340     }
341 
342     @Override
onBindRow(ExpandableNotificationRow row)343     public void onBindRow(ExpandableNotificationRow row) {
344         row.setAboveShelfChangedListener(mAboveShelfObserver);
345         row.setSecureStateProvider(mKeyguardStateController::canDismissLockScreen);
346     }
347 
348     @Override
isPresenterFullyCollapsed()349     public boolean isPresenterFullyCollapsed() {
350         return mNotificationPanel.isFullyCollapsed();
351     }
352 
353     @Override
onActivated(ActivatableNotificationView view)354     public void onActivated(ActivatableNotificationView view) {
355         onActivated();
356         if (view != null) mNotificationPanel.setActivatedChild(view);
357     }
358 
onActivated()359     public void onActivated() {
360         mLockscreenGestureLogger.write(
361                 MetricsEvent.ACTION_LS_NOTE,
362                 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
363         mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_NOTIFICATION_FALSE_TOUCH);
364         ActivatableNotificationView previousView = mNotificationPanel.getActivatedChild();
365         if (previousView != null) {
366             previousView.makeInactive(true /* animate */);
367         }
368     }
369 
370     @Override
onActivationReset(ActivatableNotificationView view)371     public void onActivationReset(ActivatableNotificationView view) {
372         if (view == mNotificationPanel.getActivatedChild()) {
373             mNotificationPanel.setActivatedChild(null);
374             mKeyguardIndicationController.hideTransientIndication();
375         }
376     }
377 
378     @Override
updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation)379     public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
380         mMediaManager.updateMediaMetaData(metaDataChanged, allowEnterAnimation);
381     }
382 
383     @Override
onUpdateRowStates()384     public void onUpdateRowStates() {
385         mNotificationPanel.onUpdateRowStates();
386     }
387 
388     @Override
onExpandClicked(NotificationEntry clickedEntry, View clickedView, boolean nowExpanded)389     public void onExpandClicked(NotificationEntry clickedEntry, View clickedView,
390             boolean nowExpanded) {
391         mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
392         mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), clickedView, "NOTIFICATION_CLICK");
393         if (nowExpanded) {
394             if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
395                 mShadeTransitionController.goToLockedShade(clickedEntry.getRow());
396             } else if (clickedEntry.isSensitive()
397                     && mDynamicPrivacyController.isInLockedDownShade()) {
398                 mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
399                 mActivityStarter.dismissKeyguardThenExecute(() -> false /* dismissAction */
400                         , null /* cancelRunnable */, false /* afterKeyguardGone */);
401             }
402         }
403     }
404 
405     @Override
isDeviceInVrMode()406     public boolean isDeviceInVrMode() {
407         return mVrMode;
408     }
409 
onLockedNotificationImportanceChange(OnDismissAction dismissAction)410     private void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {
411         mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
412         mActivityStarter.dismissKeyguardThenExecute(dismissAction, null,
413                 true /* afterKeyguardGone */);
414     }
415 
416     private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
417         @Override
418         public void onVrStateChanged(boolean enabled) {
419             mVrMode = enabled;
420         }
421     };
422 
423     private final CheckSaveListener mCheckSaveListener = new CheckSaveListener() {
424         @Override
425         public void checkSave(Runnable saveImportance, StatusBarNotification sbn) {
426             // If the user has security enabled, show challenge if the setting is changed.
427             if (mLockscreenUserManager.isLockscreenPublicMode(sbn.getUser().getIdentifier())
428                     && mKeyguardManager.isKeyguardLocked()) {
429                 onLockedNotificationImportanceChange(() -> {
430                     saveImportance.run();
431                     return true;
432                 });
433             } else {
434                 saveImportance.run();
435             }
436         }
437     };
438 
439     private final OnSettingsClickListener mOnSettingsClickListener = new OnSettingsClickListener() {
440         @Override
441         public void onSettingsClick(String key) {
442             try {
443                 mBarService.onNotificationSettingsViewed(key);
444             } catch (RemoteException e) {
445                 // if we're here we're dead
446             }
447         }
448     };
449 
450     private final NotificationInterruptSuppressor mInterruptSuppressor =
451             new NotificationInterruptSuppressor() {
452         @Override
453         public String getName() {
454             return TAG;
455         }
456 
457         @Override
458         public boolean suppressAwakeHeadsUp(NotificationEntry entry) {
459             final StatusBarNotification sbn = entry.getSbn();
460             if (mStatusBar.isOccluded()) {
461                 boolean devicePublic = mLockscreenUserManager
462                         .isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId());
463                 boolean userPublic = devicePublic
464                         || mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId());
465                 boolean needsRedaction = mLockscreenUserManager.needsRedaction(entry);
466                 if (userPublic && needsRedaction) {
467                     // TODO(b/135046837): we can probably relax this with dynamic privacy
468                     return true;
469                 }
470             }
471 
472             if (!mCommandQueue.panelsEnabled()) {
473                 if (DEBUG) {
474                     Log.d(TAG, "No heads up: disabled panel : " + sbn.getKey());
475                 }
476                 return true;
477             }
478 
479             if (sbn.getNotification().fullScreenIntent != null) {
480                 // we don't allow head-up on the lockscreen (unless there's a
481                 // "showWhenLocked" activity currently showing)  if
482                 // the potential HUN has a fullscreen intent
483                 if (mKeyguardStateController.isShowing() && !mStatusBar.isOccluded()) {
484                     if (DEBUG) {
485                         Log.d(TAG, "No heads up: entry has fullscreen intent on lockscreen "
486                                 + sbn.getKey());
487                     }
488                     return true;
489                 }
490 
491                 if (mAccessibilityManager.isTouchExplorationEnabled()) {
492                     if (DEBUG) {
493                         Log.d(TAG, "No heads up: accessible fullscreen: " + sbn.getKey());
494                     }
495                     return true;
496                 }
497             }
498             return false;
499         }
500 
501         @Override
502         public boolean suppressAwakeInterruptions(NotificationEntry entry) {
503             return isDeviceInVrMode();
504         }
505 
506         @Override
507         public boolean suppressInterruptions(NotificationEntry entry) {
508             return mStatusBar.areNotificationAlertsDisabled();
509         }
510     };
511 }
512