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