Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java 0 → 100644 +446 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.notification; import static com.android.systemui.statusbar.StatusBarState.SHADE; import android.app.NotificationManager; import android.content.Context; import android.database.ContentObserver; import android.hardware.display.AmbientDisplayConfiguration; import android.os.Build; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.service.notification.StatusBarNotification; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dependency; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.HeadsUpManager; import javax.inject.Inject; import javax.inject.Singleton; /** * Provides heads-up and pulsing state for notification entries. */ @Singleton public class NotificationInterruptionStateProvider { private static final String TAG = "InterruptionStateProvider"; private static final boolean DEBUG = false; private static final boolean DEBUG_HEADS_UP = Build.IS_DEBUGGABLE; private static final boolean ENABLE_HEADS_UP = true; private static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up"; private final StatusBarStateController mStatusBarStateController; private final NotificationFilter mNotificationFilter; private final AmbientDisplayConfiguration mAmbientDisplayConfiguration; private final Context mContext; private final PowerManager mPowerManager; private final IDreamManager mDreamManager; private final BatteryController mBatteryController; private NotificationPresenter mPresenter; private HeadsUpManager mHeadsUpManager; private HeadsUpSuppressor mHeadsUpSuppressor; private ContentObserver mHeadsUpObserver; @VisibleForTesting protected boolean mUseHeadsUp = false; private boolean mDisableNotificationAlerts; @Inject public NotificationInterruptionStateProvider(Context context, NotificationFilter filter, StatusBarStateController stateController, BatteryController batteryController) { this(context, (PowerManager) context.getSystemService(Context.POWER_SERVICE), IDreamManager.Stub.asInterface( ServiceManager.checkService(DreamService.DREAM_SERVICE)), new AmbientDisplayConfiguration(context), filter, batteryController, stateController); } @VisibleForTesting protected NotificationInterruptionStateProvider( Context context, PowerManager powerManager, IDreamManager dreamManager, AmbientDisplayConfiguration ambientDisplayConfiguration, NotificationFilter notificationFilter, BatteryController batteryController, StatusBarStateController statusBarStateController) { mContext = context; mPowerManager = powerManager; mDreamManager = dreamManager; mBatteryController = batteryController; mAmbientDisplayConfiguration = ambientDisplayConfiguration; mNotificationFilter = notificationFilter; mStatusBarStateController = statusBarStateController; } /** Sets up late-binding dependencies for this component. */ public void setUpWithPresenter( NotificationPresenter notificationPresenter, HeadsUpManager headsUpManager, HeadsUpSuppressor headsUpSuppressor) { setUpWithPresenter(notificationPresenter, headsUpManager, headsUpSuppressor, new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) { @Override public void onChange(boolean selfChange) { boolean wasUsing = mUseHeadsUp; mUseHeadsUp = ENABLE_HEADS_UP && !mDisableNotificationAlerts && Settings.Global.HEADS_UP_OFF != Settings.Global.getInt( mContext.getContentResolver(), Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, Settings.Global.HEADS_UP_OFF); Log.d(TAG, "heads up is " + (mUseHeadsUp ? "enabled" : "disabled")); if (wasUsing != mUseHeadsUp) { if (!mUseHeadsUp) { Log.d(TAG, "dismissing any existing heads up notification on disable" + " event"); mHeadsUpManager.releaseAllImmediately(); } } } }); } /** Sets up late-binding dependencies for this component. */ public void setUpWithPresenter( NotificationPresenter notificationPresenter, HeadsUpManager headsUpManager, HeadsUpSuppressor headsUpSuppressor, ContentObserver observer) { mPresenter = notificationPresenter; mHeadsUpManager = headsUpManager; mHeadsUpSuppressor = headsUpSuppressor; mHeadsUpObserver = observer; if (ENABLE_HEADS_UP) { mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED), true, mHeadsUpObserver); mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true, mHeadsUpObserver); } mHeadsUpObserver.onChange(true); // set up } /** * Whether the notification should appear as a bubble with a fly-out on top of the screen. * * @param entry the entry to check * @return true if the entry should bubble up, false otherwise */ public boolean shouldBubbleUp(NotificationEntry entry) { final StatusBarNotification sbn = entry.getSbn(); if (!canAlertCommon(entry)) { return false; } if (!canAlertAwakeCommon(entry)) { return false; } if (!entry.canBubble()) { if (DEBUG) { Log.d(TAG, "No bubble up: not allowed to bubble: " + sbn.getKey()); } return false; } if (!entry.isBubble()) { if (DEBUG) { Log.d(TAG, "No bubble up: notification " + sbn.getKey() + " is bubble? " + entry.isBubble()); } return false; } if (entry.getBubbleMetadata() == null || (entry.getBubbleMetadata().getShortcutId() == null && entry.getBubbleMetadata().getBubbleIntent() == null)) { if (DEBUG) { Log.d(TAG, "No bubble up: notification: " + sbn.getKey() + " doesn't have valid metadata"); } return false; } return true; } /** * Whether the notification should peek in from the top and alert the user. * * @param entry the entry to check * @return true if the entry should heads up, false otherwise */ public boolean shouldHeadsUp(NotificationEntry entry) { if (mStatusBarStateController.isDozing()) { return shouldHeadsUpWhenDozing(entry); } else { return shouldHeadsUpWhenAwake(entry); } } private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) { StatusBarNotification sbn = entry.getSbn(); if (!mUseHeadsUp) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: no huns"); } return false; } if (!canAlertCommon(entry)) { return false; } if (!canAlertAwakeCommon(entry)) { return false; } boolean inShade = mStatusBarStateController.getState() == SHADE; if (entry.isBubble() && inShade) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: in unlocked shade where notification is shown as a " + "bubble: " + sbn.getKey()); } return false; } if (entry.shouldSuppressPeek()) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: suppressed by DND: " + sbn.getKey()); } return false; } if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: unimportant notification: " + sbn.getKey()); } return false; } boolean isDreaming = false; try { isDreaming = mDreamManager.isDreaming(); } catch (RemoteException e) { Log.e(TAG, "Failed to query dream manager.", e); } boolean inUse = mPowerManager.isScreenOn() && !isDreaming; if (!inUse) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: not in use: " + sbn.getKey()); } return false; } if (!mHeadsUpSuppressor.canHeadsUp(entry, sbn)) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: aborted by suppressor: " + sbn.getKey()); } return false; } return true; } /** * Whether or not the notification should "pulse" on the user's display when the phone is * dozing. This displays the ambient view of the notification. * * @param entry the entry to check * @return true if the entry should ambient pulse, false otherwise */ private boolean shouldHeadsUpWhenDozing(NotificationEntry entry) { StatusBarNotification sbn = entry.getSbn(); if (!mAmbientDisplayConfiguration.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No pulsing: disabled by setting: " + sbn.getKey()); } return false; } if (mBatteryController.isAodPowerSave()) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No pulsing: disabled by battery saver: " + sbn.getKey()); } return false; } if (!canAlertCommon(entry)) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No pulsing: notification shouldn't alert: " + sbn.getKey()); } return false; } if (entry.shouldSuppressAmbient()) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No pulsing: ambient effect suppressed: " + sbn.getKey()); } return false; } if (entry.getImportance() < NotificationManager.IMPORTANCE_DEFAULT) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No pulsing: not important enough: " + sbn.getKey()); } return false; } return true; } /** * Common checks between regular & AOD heads up and bubbles. * * @param entry the entry to check * @return true if these checks pass, false if the notification should not alert */ @VisibleForTesting public boolean canAlertCommon(NotificationEntry entry) { StatusBarNotification sbn = entry.getSbn(); if (mNotificationFilter.shouldFilterOut(entry)) { if (DEBUG || DEBUG_HEADS_UP) { Log.d(TAG, "No alerting: filtered notification: " + sbn.getKey()); } return false; } // Don't alert notifications that are suppressed due to group alert behavior if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) { if (DEBUG || DEBUG_HEADS_UP) { Log.d(TAG, "No alerting: suppressed due to group alert behavior"); } return false; } return true; } /** * Common checks between alerts that occur while the device is awake (heads up & bubbles). * * @param entry the entry to check * @return true if these checks pass, false if the notification should not alert */ @VisibleForTesting public boolean canAlertAwakeCommon(NotificationEntry entry) { StatusBarNotification sbn = entry.getSbn(); if (mPresenter.isDeviceInVrMode()) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No alerting: no huns or vr mode"); } return false; } if (isSnoozedPackage(sbn)) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No alerting: snoozed package: " + sbn.getKey()); } return false; } if (entry.hasJustLaunchedFullScreenIntent()) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No alerting: recent fullscreen: " + sbn.getKey()); } return false; } return true; } private boolean isSnoozedPackage(StatusBarNotification sbn) { return mHeadsUpManager.isSnoozed(sbn.getPackageName()); } /** Sets whether to disable all alerts. */ public void setDisableNotificationAlerts(boolean disableNotificationAlerts) { mDisableNotificationAlerts = disableNotificationAlerts; mHeadsUpObserver.onChange(true); } /** Whether all alerts are disabled. */ @VisibleForTesting public boolean areNotificationAlertsDisabled() { return mDisableNotificationAlerts; } /** Whether HUNs should be used. */ @VisibleForTesting public boolean getUseHeadsUp() { return mUseHeadsUp; } protected NotificationPresenter getPresenter() { return mPresenter; } /** * When an entry was added, should we launch its fullscreen intent? Examples are Alarms or * incoming calls. * * @param entry the entry that was added * @return {@code true} if we should launch the full screen intent */ public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) { return entry.getSbn().getNotification().fullScreenIntent != null && (!shouldHeadsUp(entry) || mStatusBarStateController.getState() == StatusBarState.KEYGUARD); } /** A component which can suppress heads-up notifications due to the overall state of the UI. */ public interface HeadsUpSuppressor { /** * Returns false if the provided notification is ineligible for heads-up according to this * component. * * @param entry entry of the notification that might be heads upped * @param sbn notification that might be heads upped * @return false if the notification can not be heads upped */ boolean canHeadsUp(NotificationEntry entry, StatusBarNotification sbn); } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java 0 → 100644 +446 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.notification; import static com.android.systemui.statusbar.StatusBarState.SHADE; import android.app.NotificationManager; import android.content.Context; import android.database.ContentObserver; import android.hardware.display.AmbientDisplayConfiguration; import android.os.Build; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.service.notification.StatusBarNotification; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dependency; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.HeadsUpManager; import javax.inject.Inject; import javax.inject.Singleton; /** * Provides heads-up and pulsing state for notification entries. */ @Singleton public class NotificationInterruptionStateProvider { private static final String TAG = "InterruptionStateProvider"; private static final boolean DEBUG = false; private static final boolean DEBUG_HEADS_UP = Build.IS_DEBUGGABLE; private static final boolean ENABLE_HEADS_UP = true; private static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up"; private final StatusBarStateController mStatusBarStateController; private final NotificationFilter mNotificationFilter; private final AmbientDisplayConfiguration mAmbientDisplayConfiguration; private final Context mContext; private final PowerManager mPowerManager; private final IDreamManager mDreamManager; private final BatteryController mBatteryController; private NotificationPresenter mPresenter; private HeadsUpManager mHeadsUpManager; private HeadsUpSuppressor mHeadsUpSuppressor; private ContentObserver mHeadsUpObserver; @VisibleForTesting protected boolean mUseHeadsUp = false; private boolean mDisableNotificationAlerts; @Inject public NotificationInterruptionStateProvider(Context context, NotificationFilter filter, StatusBarStateController stateController, BatteryController batteryController) { this(context, (PowerManager) context.getSystemService(Context.POWER_SERVICE), IDreamManager.Stub.asInterface( ServiceManager.checkService(DreamService.DREAM_SERVICE)), new AmbientDisplayConfiguration(context), filter, batteryController, stateController); } @VisibleForTesting protected NotificationInterruptionStateProvider( Context context, PowerManager powerManager, IDreamManager dreamManager, AmbientDisplayConfiguration ambientDisplayConfiguration, NotificationFilter notificationFilter, BatteryController batteryController, StatusBarStateController statusBarStateController) { mContext = context; mPowerManager = powerManager; mDreamManager = dreamManager; mBatteryController = batteryController; mAmbientDisplayConfiguration = ambientDisplayConfiguration; mNotificationFilter = notificationFilter; mStatusBarStateController = statusBarStateController; } /** Sets up late-binding dependencies for this component. */ public void setUpWithPresenter( NotificationPresenter notificationPresenter, HeadsUpManager headsUpManager, HeadsUpSuppressor headsUpSuppressor) { setUpWithPresenter(notificationPresenter, headsUpManager, headsUpSuppressor, new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) { @Override public void onChange(boolean selfChange) { boolean wasUsing = mUseHeadsUp; mUseHeadsUp = ENABLE_HEADS_UP && !mDisableNotificationAlerts && Settings.Global.HEADS_UP_OFF != Settings.Global.getInt( mContext.getContentResolver(), Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, Settings.Global.HEADS_UP_OFF); Log.d(TAG, "heads up is " + (mUseHeadsUp ? "enabled" : "disabled")); if (wasUsing != mUseHeadsUp) { if (!mUseHeadsUp) { Log.d(TAG, "dismissing any existing heads up notification on disable" + " event"); mHeadsUpManager.releaseAllImmediately(); } } } }); } /** Sets up late-binding dependencies for this component. */ public void setUpWithPresenter( NotificationPresenter notificationPresenter, HeadsUpManager headsUpManager, HeadsUpSuppressor headsUpSuppressor, ContentObserver observer) { mPresenter = notificationPresenter; mHeadsUpManager = headsUpManager; mHeadsUpSuppressor = headsUpSuppressor; mHeadsUpObserver = observer; if (ENABLE_HEADS_UP) { mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED), true, mHeadsUpObserver); mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true, mHeadsUpObserver); } mHeadsUpObserver.onChange(true); // set up } /** * Whether the notification should appear as a bubble with a fly-out on top of the screen. * * @param entry the entry to check * @return true if the entry should bubble up, false otherwise */ public boolean shouldBubbleUp(NotificationEntry entry) { final StatusBarNotification sbn = entry.getSbn(); if (!canAlertCommon(entry)) { return false; } if (!canAlertAwakeCommon(entry)) { return false; } if (!entry.canBubble()) { if (DEBUG) { Log.d(TAG, "No bubble up: not allowed to bubble: " + sbn.getKey()); } return false; } if (!entry.isBubble()) { if (DEBUG) { Log.d(TAG, "No bubble up: notification " + sbn.getKey() + " is bubble? " + entry.isBubble()); } return false; } if (entry.getBubbleMetadata() == null || (entry.getBubbleMetadata().getShortcutId() == null && entry.getBubbleMetadata().getBubbleIntent() == null)) { if (DEBUG) { Log.d(TAG, "No bubble up: notification: " + sbn.getKey() + " doesn't have valid metadata"); } return false; } return true; } /** * Whether the notification should peek in from the top and alert the user. * * @param entry the entry to check * @return true if the entry should heads up, false otherwise */ public boolean shouldHeadsUp(NotificationEntry entry) { if (mStatusBarStateController.isDozing()) { return shouldHeadsUpWhenDozing(entry); } else { return shouldHeadsUpWhenAwake(entry); } } private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) { StatusBarNotification sbn = entry.getSbn(); if (!mUseHeadsUp) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: no huns"); } return false; } if (!canAlertCommon(entry)) { return false; } if (!canAlertAwakeCommon(entry)) { return false; } boolean inShade = mStatusBarStateController.getState() == SHADE; if (entry.isBubble() && inShade) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: in unlocked shade where notification is shown as a " + "bubble: " + sbn.getKey()); } return false; } if (entry.shouldSuppressPeek()) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: suppressed by DND: " + sbn.getKey()); } return false; } if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: unimportant notification: " + sbn.getKey()); } return false; } boolean isDreaming = false; try { isDreaming = mDreamManager.isDreaming(); } catch (RemoteException e) { Log.e(TAG, "Failed to query dream manager.", e); } boolean inUse = mPowerManager.isScreenOn() && !isDreaming; if (!inUse) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: not in use: " + sbn.getKey()); } return false; } if (!mHeadsUpSuppressor.canHeadsUp(entry, sbn)) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No heads up: aborted by suppressor: " + sbn.getKey()); } return false; } return true; } /** * Whether or not the notification should "pulse" on the user's display when the phone is * dozing. This displays the ambient view of the notification. * * @param entry the entry to check * @return true if the entry should ambient pulse, false otherwise */ private boolean shouldHeadsUpWhenDozing(NotificationEntry entry) { StatusBarNotification sbn = entry.getSbn(); if (!mAmbientDisplayConfiguration.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No pulsing: disabled by setting: " + sbn.getKey()); } return false; } if (mBatteryController.isAodPowerSave()) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No pulsing: disabled by battery saver: " + sbn.getKey()); } return false; } if (!canAlertCommon(entry)) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No pulsing: notification shouldn't alert: " + sbn.getKey()); } return false; } if (entry.shouldSuppressAmbient()) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No pulsing: ambient effect suppressed: " + sbn.getKey()); } return false; } if (entry.getImportance() < NotificationManager.IMPORTANCE_DEFAULT) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No pulsing: not important enough: " + sbn.getKey()); } return false; } return true; } /** * Common checks between regular & AOD heads up and bubbles. * * @param entry the entry to check * @return true if these checks pass, false if the notification should not alert */ @VisibleForTesting public boolean canAlertCommon(NotificationEntry entry) { StatusBarNotification sbn = entry.getSbn(); if (mNotificationFilter.shouldFilterOut(entry)) { if (DEBUG || DEBUG_HEADS_UP) { Log.d(TAG, "No alerting: filtered notification: " + sbn.getKey()); } return false; } // Don't alert notifications that are suppressed due to group alert behavior if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) { if (DEBUG || DEBUG_HEADS_UP) { Log.d(TAG, "No alerting: suppressed due to group alert behavior"); } return false; } return true; } /** * Common checks between alerts that occur while the device is awake (heads up & bubbles). * * @param entry the entry to check * @return true if these checks pass, false if the notification should not alert */ @VisibleForTesting public boolean canAlertAwakeCommon(NotificationEntry entry) { StatusBarNotification sbn = entry.getSbn(); if (mPresenter.isDeviceInVrMode()) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No alerting: no huns or vr mode"); } return false; } if (isSnoozedPackage(sbn)) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No alerting: snoozed package: " + sbn.getKey()); } return false; } if (entry.hasJustLaunchedFullScreenIntent()) { if (DEBUG_HEADS_UP) { Log.d(TAG, "No alerting: recent fullscreen: " + sbn.getKey()); } return false; } return true; } private boolean isSnoozedPackage(StatusBarNotification sbn) { return mHeadsUpManager.isSnoozed(sbn.getPackageName()); } /** Sets whether to disable all alerts. */ public void setDisableNotificationAlerts(boolean disableNotificationAlerts) { mDisableNotificationAlerts = disableNotificationAlerts; mHeadsUpObserver.onChange(true); } /** Whether all alerts are disabled. */ @VisibleForTesting public boolean areNotificationAlertsDisabled() { return mDisableNotificationAlerts; } /** Whether HUNs should be used. */ @VisibleForTesting public boolean getUseHeadsUp() { return mUseHeadsUp; } protected NotificationPresenter getPresenter() { return mPresenter; } /** * When an entry was added, should we launch its fullscreen intent? Examples are Alarms or * incoming calls. * * @param entry the entry that was added * @return {@code true} if we should launch the full screen intent */ public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) { return entry.getSbn().getNotification().fullScreenIntent != null && (!shouldHeadsUp(entry) || mStatusBarStateController.getState() == StatusBarState.KEYGUARD); } /** A component which can suppress heads-up notifications due to the overall state of the UI. */ public interface HeadsUpSuppressor { /** * Returns false if the provided notification is ineligible for heads-up according to this * component. * * @param entry entry of the notification that might be heads upped * @param sbn notification that might be heads upped * @return false if the notification can not be heads upped */ boolean canHeadsUp(NotificationEntry entry, StatusBarNotification sbn); } }