Loading packages/SystemUI/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,9 @@ <!-- Minimum display time for a heads up notification, in milliseconds. --> <integer name="heads_up_notification_minimum_time">2000</integer> <!-- Display time for a sticky heads up notification, in milliseconds. --> <integer name="sticky_heads_up_notification_time">60000</integer> <!-- Whether to hide the notification header when the HUN is expanded. --> <bool name="heads_up_notification_hides_header">false</bool> Loading packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java +36 −14 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ public abstract class AlertingNotificationManager { } protected int mMinimumDisplayTime; protected int mStickyDisplayTime; protected int mAutoDismissNotificationDecay; @VisibleForTesting public Handler mHandler; Loading Loading @@ -198,7 +199,7 @@ public abstract class AlertingNotificationManager { if (entry != null && entry.isExpandAnimationRunning()) { return; } entry.demoteStickyHun(); mAlertEntries.remove(key); onAlertEntryRemoved(alertEntry); entry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); Loading Loading @@ -255,6 +256,15 @@ public abstract class AlertingNotificationManager { return 0; } @VisibleForTesting public long getCalculatedEarliestRemovalTime(String key) { AlertEntry alerting = mAlertEntries.get(key); if (alerting != null) { return alerting.mEarliestRemovaltime; } return 0; } protected class AlertEntry implements Comparable<AlertEntry> { @Nullable public NotificationEntry mEntry; public long mPostTime; Loading @@ -275,6 +285,11 @@ public abstract class AlertingNotificationManager { updateEntry(true /* updatePostTime */); } @VisibleForTesting long getEarliestRemovaltime() { return mEarliestRemovaltime; } /** * Updates an entry's removal time. * @param updatePostTime whether or not to refresh the post time Loading @@ -282,18 +297,22 @@ public abstract class AlertingNotificationManager { public void updateEntry(boolean updatePostTime) { mLogger.logUpdateEntry(mEntry, updatePostTime); long currentTime = mClock.currentTimeMillis(); mEarliestRemovaltime = currentTime + mMinimumDisplayTime; final long now = mClock.currentTimeMillis(); mEarliestRemovaltime = isSticky() ? mEntry.mCreationElapsedRealTime + mStickyDisplayTime : now + mMinimumDisplayTime; if (updatePostTime) { mPostTime = Math.max(mPostTime, currentTime); mPostTime = Math.max(mPostTime, now); } removeAutoRemovalCallbacks(); if (!isSticky()) { long finishTime = calculateFinishTime(); long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime); mHandler.postDelayed(mRemoveAlertRunnable, removeDelay); } final long finishTime = calculateFinishTime(); final long timeRemaining = isSticky() ? finishTime - mClock.currentTimeMillis() : Math.max(finishTime - now, mMinimumDisplayTime); mHandler.postDelayed(mRemoveAlertRunnable, timeRemaining); } /** Loading @@ -302,11 +321,13 @@ public abstract class AlertingNotificationManager { * @return true if the notification is sticky */ public boolean isSticky() { return false; // This implementation is overridden by HeadsUpManager HeadsUpEntry #isSticky // but we keep this here for use by unit tests. return mEntry.isStickyAndNotDemoted(); } /** * Whether the notification has been on screen long enough and can be removed. * Whether the notification has befen on screen long enough and can be removed. * @return true if the notification has been on screen long enough */ public boolean wasShownLongEnough() { Loading Loading @@ -355,11 +376,12 @@ public abstract class AlertingNotificationManager { } /** * Calculate when the notification should auto-dismiss itself. * @return the finish time * @return When the notification should auto-dismiss itself, based on * {@link SystemClock#elapsedRealTime()} */ protected long calculateFinishTime() { return mPostTime + mAutoDismissNotificationDecay; // Overridden by HeadsUpManager HeadsUpEntry #calculateFinishTime return 0; } } Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +43 −0 Original line number Diff line number Diff line Loading @@ -180,6 +180,44 @@ public final class NotificationEntry extends ListEntry { */ private boolean mBlockable; /** * The {@link SystemClock#elapsedRealtime()} when this notification entry was created. */ public long mCreationElapsedRealTime; /** * Whether this notification has ever been a non-sticky HUN. */ private boolean mIsDemoted = false; /** * True if both * 1) app provided full screen intent but does not have the permission to send it * 2) this notification has never been demoted before */ public boolean isStickyAndNotDemoted() { final boolean fsiRequestedButDenied = (getSbn().getNotification().flags & Notification.FLAG_FSI_REQUESTED_BUT_DENIED) != 0; if (!fsiRequestedButDenied && !mIsDemoted) { demoteStickyHun(); } return fsiRequestedButDenied && !mIsDemoted; } @VisibleForTesting public boolean isDemoted() { return mIsDemoted; } /** * Make sticky HUN not sticky. */ public void demoteStickyHun() { mIsDemoted = true; } /** * @param sbn the StatusBarNotification from system server * @param ranking also from system server Loading @@ -197,8 +235,13 @@ public final class NotificationEntry extends ListEntry { mKey = sbn.getKey(); setSbn(sbn); setRanking(ranking); mCreationElapsedRealTime = SystemClock.elapsedRealtime(); } @VisibleForTesting public void setCreationElapsedRealTime(long time) { mCreationElapsedRealTime = time; } @Override public NotificationEntry getRepresentativeEntry() { return this; Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java +4 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,10 @@ public interface NotificationInterruptStateProvider { * the full screen intent should or shouldn't launch. */ enum FullScreenIntentDecision { /** * Full screen intents are disabled. */ NO_FSI_SHOW_STICKY_HUN(false), /** * Full screen intents are disabled. */ Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java +8 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.hardware.display.AmbientDisplayConfiguration; import android.os.Handler; import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemProperties; import android.provider.Settings; import android.service.dreams.IDreamManager; import android.service.notification.StatusBarNotification; Loading Loading @@ -246,7 +247,11 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter if (mFlags.disableFsi()) { return FullScreenIntentDecision.NO_FSI_DISABLED; } if (entry.getSbn().getNotification().fullScreenIntent == null) { if (entry.isStickyAndNotDemoted()) { return FullScreenIntentDecision.NO_FSI_SHOW_STICKY_HUN; } return FullScreenIntentDecision.NO_FULL_SCREEN_INTENT; } Loading Loading @@ -335,6 +340,9 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter final int uid = entry.getSbn().getUid(); final String packageName = entry.getSbn().getPackageName(); switch (decision) { case NO_FSI_SHOW_STICKY_HUN: mLogger.logNoFullscreen(entry, "Permission denied, show sticky HUN"); return; case NO_FSI_DISABLED: mLogger.logNoFullscreen(entry, "Disabled"); return; Loading Loading
packages/SystemUI/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,9 @@ <!-- Minimum display time for a heads up notification, in milliseconds. --> <integer name="heads_up_notification_minimum_time">2000</integer> <!-- Display time for a sticky heads up notification, in milliseconds. --> <integer name="sticky_heads_up_notification_time">60000</integer> <!-- Whether to hide the notification header when the HUN is expanded. --> <bool name="heads_up_notification_hides_header">false</bool> Loading
packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java +36 −14 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ public abstract class AlertingNotificationManager { } protected int mMinimumDisplayTime; protected int mStickyDisplayTime; protected int mAutoDismissNotificationDecay; @VisibleForTesting public Handler mHandler; Loading Loading @@ -198,7 +199,7 @@ public abstract class AlertingNotificationManager { if (entry != null && entry.isExpandAnimationRunning()) { return; } entry.demoteStickyHun(); mAlertEntries.remove(key); onAlertEntryRemoved(alertEntry); entry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); Loading Loading @@ -255,6 +256,15 @@ public abstract class AlertingNotificationManager { return 0; } @VisibleForTesting public long getCalculatedEarliestRemovalTime(String key) { AlertEntry alerting = mAlertEntries.get(key); if (alerting != null) { return alerting.mEarliestRemovaltime; } return 0; } protected class AlertEntry implements Comparable<AlertEntry> { @Nullable public NotificationEntry mEntry; public long mPostTime; Loading @@ -275,6 +285,11 @@ public abstract class AlertingNotificationManager { updateEntry(true /* updatePostTime */); } @VisibleForTesting long getEarliestRemovaltime() { return mEarliestRemovaltime; } /** * Updates an entry's removal time. * @param updatePostTime whether or not to refresh the post time Loading @@ -282,18 +297,22 @@ public abstract class AlertingNotificationManager { public void updateEntry(boolean updatePostTime) { mLogger.logUpdateEntry(mEntry, updatePostTime); long currentTime = mClock.currentTimeMillis(); mEarliestRemovaltime = currentTime + mMinimumDisplayTime; final long now = mClock.currentTimeMillis(); mEarliestRemovaltime = isSticky() ? mEntry.mCreationElapsedRealTime + mStickyDisplayTime : now + mMinimumDisplayTime; if (updatePostTime) { mPostTime = Math.max(mPostTime, currentTime); mPostTime = Math.max(mPostTime, now); } removeAutoRemovalCallbacks(); if (!isSticky()) { long finishTime = calculateFinishTime(); long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime); mHandler.postDelayed(mRemoveAlertRunnable, removeDelay); } final long finishTime = calculateFinishTime(); final long timeRemaining = isSticky() ? finishTime - mClock.currentTimeMillis() : Math.max(finishTime - now, mMinimumDisplayTime); mHandler.postDelayed(mRemoveAlertRunnable, timeRemaining); } /** Loading @@ -302,11 +321,13 @@ public abstract class AlertingNotificationManager { * @return true if the notification is sticky */ public boolean isSticky() { return false; // This implementation is overridden by HeadsUpManager HeadsUpEntry #isSticky // but we keep this here for use by unit tests. return mEntry.isStickyAndNotDemoted(); } /** * Whether the notification has been on screen long enough and can be removed. * Whether the notification has befen on screen long enough and can be removed. * @return true if the notification has been on screen long enough */ public boolean wasShownLongEnough() { Loading Loading @@ -355,11 +376,12 @@ public abstract class AlertingNotificationManager { } /** * Calculate when the notification should auto-dismiss itself. * @return the finish time * @return When the notification should auto-dismiss itself, based on * {@link SystemClock#elapsedRealTime()} */ protected long calculateFinishTime() { return mPostTime + mAutoDismissNotificationDecay; // Overridden by HeadsUpManager HeadsUpEntry #calculateFinishTime return 0; } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +43 −0 Original line number Diff line number Diff line Loading @@ -180,6 +180,44 @@ public final class NotificationEntry extends ListEntry { */ private boolean mBlockable; /** * The {@link SystemClock#elapsedRealtime()} when this notification entry was created. */ public long mCreationElapsedRealTime; /** * Whether this notification has ever been a non-sticky HUN. */ private boolean mIsDemoted = false; /** * True if both * 1) app provided full screen intent but does not have the permission to send it * 2) this notification has never been demoted before */ public boolean isStickyAndNotDemoted() { final boolean fsiRequestedButDenied = (getSbn().getNotification().flags & Notification.FLAG_FSI_REQUESTED_BUT_DENIED) != 0; if (!fsiRequestedButDenied && !mIsDemoted) { demoteStickyHun(); } return fsiRequestedButDenied && !mIsDemoted; } @VisibleForTesting public boolean isDemoted() { return mIsDemoted; } /** * Make sticky HUN not sticky. */ public void demoteStickyHun() { mIsDemoted = true; } /** * @param sbn the StatusBarNotification from system server * @param ranking also from system server Loading @@ -197,8 +235,13 @@ public final class NotificationEntry extends ListEntry { mKey = sbn.getKey(); setSbn(sbn); setRanking(ranking); mCreationElapsedRealTime = SystemClock.elapsedRealtime(); } @VisibleForTesting public void setCreationElapsedRealTime(long time) { mCreationElapsedRealTime = time; } @Override public NotificationEntry getRepresentativeEntry() { return this; Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java +4 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,10 @@ public interface NotificationInterruptStateProvider { * the full screen intent should or shouldn't launch. */ enum FullScreenIntentDecision { /** * Full screen intents are disabled. */ NO_FSI_SHOW_STICKY_HUN(false), /** * Full screen intents are disabled. */ Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java +8 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.hardware.display.AmbientDisplayConfiguration; import android.os.Handler; import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemProperties; import android.provider.Settings; import android.service.dreams.IDreamManager; import android.service.notification.StatusBarNotification; Loading Loading @@ -246,7 +247,11 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter if (mFlags.disableFsi()) { return FullScreenIntentDecision.NO_FSI_DISABLED; } if (entry.getSbn().getNotification().fullScreenIntent == null) { if (entry.isStickyAndNotDemoted()) { return FullScreenIntentDecision.NO_FSI_SHOW_STICKY_HUN; } return FullScreenIntentDecision.NO_FULL_SCREEN_INTENT; } Loading Loading @@ -335,6 +340,9 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter final int uid = entry.getSbn().getUid(); final String packageName = entry.getSbn().getPackageName(); switch (decision) { case NO_FSI_SHOW_STICKY_HUN: mLogger.logNoFullscreen(entry, "Permission denied, show sticky HUN"); return; case NO_FSI_DISABLED: mLogger.logNoFullscreen(entry, "Disabled"); return; Loading