diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml index 9716a00a7f72f..a91493003bb54 100644 --- a/packages/SystemUI/res/layout/super_status_bar.xml +++ b/packages/SystemUI/res/layout/super_status_bar.xml @@ -44,7 +44,7 @@ - - mManagedEntries = new ArraySet<>(); + private Handler mHandler = new Handler(Looper.getMainLooper()); + + public ForegroundServiceLifetimeExtender() { + } + + @Override + public void setCallback(@NonNull NotificationSafeToRemoveCallback callback) { + mNotificationSafeToRemoveCallback = callback; + } + + @Override + public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) { + if ((entry.notification.getNotification().flags + & Notification.FLAG_FOREGROUND_SERVICE) == 0) { + return false; + } + + long currentTime = System.currentTimeMillis(); + return currentTime - entry.notification.getPostTime() < MIN_FGS_TIME_MS; + } + + @Override + public boolean shouldExtendLifetimeForPendingNotification( + @NonNull NotificationEntry entry) { + return shouldExtendLifetime(entry); + } + + @Override + public void setShouldManageLifetime( + @NonNull NotificationEntry entry, boolean shouldManage) { + if (!shouldManage) { + mManagedEntries.remove(entry); + return; + } + + mManagedEntries.add(entry); + + Runnable r = () -> { + if (mManagedEntries.contains(entry)) { + mManagedEntries.remove(entry); + if (mNotificationSafeToRemoveCallback != null) { + mNotificationSafeToRemoveCallback.onSafeToRemove(entry.key); + } + } + }; + long delayAmt = MIN_FGS_TIME_MS + - (System.currentTimeMillis() - entry.notification.getPostTime()); + mHandler.postDelayed(r, delayAmt); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java index 96b62ac918ab4..0162deb55143f 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java @@ -66,6 +66,9 @@ public class ForegroundServiceNotificationListener { removeNotification(entry.notification); } }); + + notificationEntryManager.addNotificationLifetimeExtender( + new ForegroundServiceLifetimeExtender()); } /** diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index d151f7dc62bed..0899d955a1acc 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -123,12 +123,11 @@ public class SystemUIFactory { } public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront, - ScrimView scrimForBubble, LockscreenWallpaper lockscreenWallpaper, TriConsumer scrimStateListener, Consumer scrimVisibleListener, DozeParameters dozeParameters, AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) { - return new ScrimController(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener, + return new ScrimController(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener, dozeParameters, alarmManager, keyguardMonitor); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 3cc91de434385..5559d29a90506 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -316,9 +316,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (mStackView == null) { mStackView = new BubbleStackView(mContext, mBubbleData, mSurfaceSynchronizer); ViewGroup sbv = mStatusBarWindowController.getStatusBarView(); - int bubbleScrimIndex = sbv.indexOfChild(sbv.findViewById(R.id.scrim_for_bubble)); - int stackIndex = bubbleScrimIndex + 1; // Show stack above bubble scrim. - sbv.addView(mStackView, stackIndex, + // TODO(b/130237686): When you expand the shade on top of expanded bubble, there is no + // scrim between bubble and the shade + int bubblePosition = sbv.indexOfChild(sbv.findViewById(R.id.scrim_behind)) + 1; + sbv.addView(mStackView, bubblePosition, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)); if (mExpandListener != null) { mStackView.setExpandListener(mExpandListener); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java index 0f295ba75fe40..48e2923c97d99 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java @@ -26,6 +26,18 @@ public interface NotificationLifetimeExtender { */ boolean shouldExtendLifetime(@NonNull NotificationEntry entry); + /** + * It's possible that a notification was canceled before it ever became visible. This callback + * gives lifetime extenders a chance to make sure it shows up. For example if a foreground + * service is canceled too quickly but we still want to make sure a FGS notification shows. + * @param pendingEntry the canceled (but pending) entry + * @return true if the notification lifetime should be extended + */ + default boolean shouldExtendLifetimeForPendingNotification( + @NonNull NotificationEntry pendingEntry) { + return false; + } + /** * Sets whether or not the lifetime should be managed by the extender. In practice, if * shouldManage is true, this is where the extender starts managing the entry internally and is diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index f8fef7d4778c8..a37367e4bb255 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -281,11 +281,25 @@ public class NotificationEntryManager implements } final NotificationEntry entry = mNotificationData.get(key); - - abortExistingInflation(key); - boolean lifetimeExtended = false; + // Notification was canceled before it got inflated + if (entry == null) { + NotificationEntry pendingEntry = mPendingNotifications.get(key); + if (pendingEntry != null) { + for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) { + if (extender.shouldExtendLifetimeForPendingNotification(pendingEntry)) { + extendLifetime(pendingEntry, extender); + lifetimeExtended = true; + } + } + } + } + + if (!lifetimeExtended) { + abortExistingInflation(key); + } + if (entry != null) { // If a manager needs to keep the notification around for whatever reason, we // keep the notification diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java index ecfc45bb11829..06a2225ed0bf2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java @@ -604,7 +604,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange */ public void onScrimVisibilityChanged(@ScrimVisibility int scrimsVisible) { if (mWakeAndUnlockRunning - && scrimsVisible == ScrimController.TRANSPARENT) { + && scrimsVisible == ScrimController.VISIBILITY_FULLY_TRANSPARENT) { mWakeAndUnlockRunning = false; update(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index fd3c9526149dd..9019e9a3f44b7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -79,24 +79,23 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo /** * When both scrims have 0 alpha. */ - public static final int TRANSPARENT = 0; + public static final int VISIBILITY_FULLY_TRANSPARENT = 0; /** * When scrims aren't transparent (alpha 0) but also not opaque (alpha 1.) */ - public static final int SEMI_TRANSPARENT = 1; + public static final int VISIBILITY_SEMI_TRANSPARENT = 1; /** * When at least 1 scrim is fully opaque (alpha set to 1.) */ - public static final int OPAQUE = 2; + public static final int VISIBILITY_FULLY_OPAQUE = 2; - @IntDef(prefix = {"VISIBILITY_"}, value = { - TRANSPARENT, - SEMI_TRANSPARENT, - OPAQUE + @IntDef(prefix = { "VISIBILITY_" }, value = { + VISIBILITY_FULLY_TRANSPARENT, + VISIBILITY_SEMI_TRANSPARENT, + VISIBILITY_FULLY_OPAQUE }) @Retention(RetentionPolicy.SOURCE) - public @interface ScrimVisibility { - } + public @interface ScrimVisibility {} /** * Default alpha value for most scrims. @@ -124,11 +123,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private ScrimState mState = ScrimState.UNINITIALIZED; private final Context mContext; - - protected final ScrimView mScrimInFront; protected final ScrimView mScrimBehind; - protected final ScrimView mScrimForBubble; - + protected final ScrimView mScrimInFront; private final UnlockMethodCache mUnlockMethodCache; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final DozeParameters mDozeParameters; @@ -157,15 +153,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private Runnable mOnAnimationFinished; private boolean mDeferFinishedListener; private final Interpolator mInterpolator = new DecelerateInterpolator(); - - private float mInFrontAlpha = NOT_INITIALIZED; - private float mBehindAlpha = NOT_INITIALIZED; - private float mBubbleAlpha = NOT_INITIALIZED; - - private int mInFrontTint; - private int mBehindTint; - private int mBubbleTint; - + private float mCurrentInFrontAlpha = NOT_INITIALIZED; + private float mCurrentBehindAlpha = NOT_INITIALIZED; + private int mCurrentInFrontTint; + private int mCurrentBehindTint; private boolean mWallpaperVisibilityTimedOut; private int mScrimsVisibility; private final TriConsumer mScrimStateListener; @@ -184,17 +175,14 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private boolean mWakeLockHeld; private boolean mKeyguardOccluded; - public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, ScrimView scrimForBubble, + public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, TriConsumer scrimStateListener, Consumer scrimVisibleListener, DozeParameters dozeParameters, AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) { mScrimBehind = scrimBehind; mScrimInFront = scrimInFront; - mScrimForBubble = scrimForBubble; - mScrimStateListener = scrimStateListener; mScrimVisibleListener = scrimVisibleListener; - mContext = scrimBehind.getContext(); mUnlockMethodCache = UnlockMethodCache.getInstance(mContext); mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer(); @@ -225,13 +213,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo final ScrimState[] states = ScrimState.values(); for (int i = 0; i < states.length; i++) { - states[i].init(mScrimInFront, mScrimBehind, mScrimForBubble, mDozeParameters); + states[i].init(mScrimInFront, mScrimBehind, mDozeParameters); states[i].setScrimBehindAlphaKeyguard(mScrimBehindAlphaKeyguard); } mScrimBehind.setDefaultFocusHighlightEnabled(false); mScrimInFront.setDefaultFocusHighlightEnabled(false); - mScrimForBubble.setDefaultFocusHighlightEnabled(false); updateScrims(); } @@ -270,14 +257,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo mBlankScreen = state.getBlanksScreen(); mAnimateChange = state.getAnimateChange(); mAnimationDuration = state.getAnimationDuration(); - - mInFrontTint = state.getFrontTint(); - mBehindTint = state.getBehindTint(); - mBubbleTint = state.getBubbleTint(); - - mInFrontAlpha = state.getFrontAlpha(); - mBehindAlpha = state.getBehindAlpha(); - mBubbleAlpha = state.getBubbleAlpha(); + mCurrentInFrontTint = state.getFrontTint(); + mCurrentBehindTint = state.getBehindTint(); + mCurrentInFrontAlpha = state.getFrontAlpha(); + mCurrentBehindAlpha = state.getBehindAlpha(); applyExpansionToAlpha(); // Scrim might acquire focus when user is navigating with a D-pad or a keyboard. @@ -410,20 +393,21 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo if (mExpansionFraction != fraction) { mExpansionFraction = fraction; - boolean relevantState = (mState == ScrimState.UNLOCKED - || mState == ScrimState.KEYGUARD - || mState == ScrimState.PULSING - || mState == ScrimState.BUBBLE_EXPANDED); - if (!(relevantState && mExpansionAffectsAlpha)) { + final boolean keyguardOrUnlocked = mState == ScrimState.UNLOCKED + || mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING; + if (!keyguardOrUnlocked || !mExpansionAffectsAlpha) { return; } + applyExpansionToAlpha(); + if (mUpdatePending) { return; } + setOrAdaptCurrentAnimation(mScrimBehind); setOrAdaptCurrentAnimation(mScrimInFront); - setOrAdaptCurrentAnimation(mScrimForBubble); + dispatchScrimState(mScrimBehind.getViewAlpha()); // Reset wallpaper timeout if it's already timeout like expanding panel while PULSING @@ -437,10 +421,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo } private void setOrAdaptCurrentAnimation(View scrim) { - float alpha = getCurrentScrimAlpha(scrim); - if (isAnimating(scrim)) { - // Adapt current animation. + if (!isAnimating(scrim)) { + updateScrimColor(scrim, getCurrentScrimAlpha(scrim), getCurrentScrimTint(scrim)); + } else { ValueAnimator previousAnimator = (ValueAnimator) scrim.getTag(TAG_KEY_ANIM); + float alpha = getCurrentScrimAlpha(scrim); float previousEndValue = (Float) scrim.getTag(TAG_END_ALPHA); float previousStartValue = (Float) scrim.getTag(TAG_START_ALPHA); float relativeDiff = alpha - previousEndValue; @@ -448,9 +433,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo scrim.setTag(TAG_START_ALPHA, newStartValue); scrim.setTag(TAG_END_ALPHA, alpha); previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime()); - } else { - // Set animation. - updateScrimColor(scrim, alpha, getCurrentScrimTint(scrim)); } } @@ -459,27 +441,27 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo return; } - if (mState == ScrimState.UNLOCKED || mState == ScrimState.BUBBLE_EXPANDED) { + if (mState == ScrimState.UNLOCKED) { // Darken scrim as you pull down the shade when unlocked float behindFraction = getInterpolatedFraction(); behindFraction = (float) Math.pow(behindFraction, 0.8f); - mBehindAlpha = behindFraction * GRADIENT_SCRIM_ALPHA_BUSY; - mInFrontAlpha = 0; + mCurrentBehindAlpha = behindFraction * GRADIENT_SCRIM_ALPHA_BUSY; + mCurrentInFrontAlpha = 0; } else if (mState == ScrimState.KEYGUARD || mState == ScrimState.PULSING) { // Either darken of make the scrim transparent when you // pull down the shade float interpolatedFract = getInterpolatedFraction(); float alphaBehind = mState.getBehindAlpha(); if (mDarkenWhileDragging) { - mBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind, + mCurrentBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind, interpolatedFract); - mInFrontAlpha = mState.getFrontAlpha(); + mCurrentInFrontAlpha = mState.getFrontAlpha(); } else { - mBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind, + mCurrentBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind, interpolatedFract); - mInFrontAlpha = mState.getFrontAlpha(); + mCurrentInFrontAlpha = mState.getFrontAlpha(); } - mBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(), + mCurrentBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(), mState.getBehindTint(), interpolatedFract); } } @@ -504,8 +486,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo */ public void setAodFrontScrimAlpha(float alpha) { if (((mState == ScrimState.AOD && mDozeParameters.getAlwaysOn()) - || mState == ScrimState.PULSING) && mInFrontAlpha != alpha) { - mInFrontAlpha = alpha; + || mState == ScrimState.PULSING) && mCurrentInFrontAlpha != alpha) { + mCurrentInFrontAlpha = alpha; updateScrims(); } @@ -519,9 +501,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo */ public void prepareForGentleWakeUp() { if (mState == ScrimState.AOD && mDozeParameters.getAlwaysOn()) { - mInFrontAlpha = 1f; - mInFrontTint = Color.BLACK; - mBehindTint = Color.BLACK; + mCurrentInFrontAlpha = 1f; + mCurrentInFrontTint = Color.BLACK; + mCurrentBehindTint = Color.BLACK; mAnimateChange = false; updateScrims(); mAnimateChange = true; @@ -539,8 +521,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo if (mState == ScrimState.PULSING) { float newBehindAlpha = mState.getBehindAlpha(); - if (mBehindAlpha != newBehindAlpha) { - mBehindAlpha = newBehindAlpha; + if (mCurrentBehindAlpha != newBehindAlpha) { + mCurrentBehindAlpha = newBehindAlpha; updateScrims(); } } @@ -562,11 +544,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo // Only animate scrim color if the scrim view is actually visible boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0 && !mBlankScreen; boolean animateScrimBehind = mScrimBehind.getViewAlpha() != 0 && !mBlankScreen; - boolean animateScrimForBubble = mScrimForBubble.getViewAlpha() != 0 && !mBlankScreen; - mScrimInFront.setColors(mColors, animateScrimInFront); mScrimBehind.setColors(mColors, animateScrimBehind); - mScrimForBubble.setColors(mColors, animateScrimForBubble); // Calculate minimum scrim opacity for white or black text. int textColor = mColors.supportsDarkText() ? Color.BLACK : Color.WHITE; @@ -585,11 +564,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo boolean occludedKeyguard = (mState == ScrimState.PULSING || mState == ScrimState.AOD) && mKeyguardOccluded; if (aodWallpaperTimeout || occludedKeyguard) { - mBehindAlpha = 1; + mCurrentBehindAlpha = 1; } - setScrimAlpha(mScrimInFront, mInFrontAlpha); - setScrimAlpha(mScrimBehind, mBehindAlpha); - setScrimAlpha(mScrimForBubble, mBubbleAlpha); + + setScrimInFrontAlpha(mCurrentInFrontAlpha); + setScrimBehindAlpha(mCurrentBehindAlpha); + dispatchScrimsVisible(); } @@ -600,11 +580,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private void dispatchScrimsVisible() { final int currentScrimVisibility; if (mScrimInFront.getViewAlpha() == 1 || mScrimBehind.getViewAlpha() == 1) { - currentScrimVisibility = OPAQUE; + currentScrimVisibility = VISIBILITY_FULLY_OPAQUE; } else if (mScrimInFront.getViewAlpha() == 0 && mScrimBehind.getViewAlpha() == 0) { - currentScrimVisibility = TRANSPARENT; + currentScrimVisibility = VISIBILITY_FULLY_TRANSPARENT; } else { - currentScrimVisibility = SEMI_TRANSPARENT; + currentScrimVisibility = VISIBILITY_SEMI_TRANSPARENT; } if (mScrimsVisibility != currentScrimVisibility) { @@ -621,10 +601,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo return 0; } else { // woo, special effects - return (float) (1f - 0.5f * (1f - Math.cos(3.14159f * Math.pow(1f - frac, 2f)))); + return (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f)))); } } + private void setScrimBehindAlpha(float alpha) { + setScrimAlpha(mScrimBehind, alpha); + } + + private void setScrimInFrontAlpha(float alpha) { + setScrimAlpha(mScrimInFront, alpha); + } + private void setScrimAlpha(ScrimView scrim, float alpha) { if (alpha == 0f) { scrim.setClickable(false); @@ -635,26 +623,17 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo updateScrim(scrim, alpha); } - private String getScrimName(ScrimView scrim) { - if (scrim == mScrimInFront) { - return "front_scrim"; - } else if (scrim == mScrimBehind) { - return "back_scrim"; - } else if (scrim == mScrimForBubble) { - return "bubble_scrim"; - } - return "unknown_scrim"; - } - private void updateScrimColor(View scrim, float alpha, int tint) { alpha = Math.max(0, Math.min(1.0f, alpha)); if (scrim instanceof ScrimView) { ScrimView scrimView = (ScrimView) scrim; - Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_alpha", + Trace.traceCounter(Trace.TRACE_TAG_APP, + scrim == mScrimInFront ? "front_scrim_alpha" : "back_scrim_alpha", (int) (alpha * 255)); - Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_tint", + Trace.traceCounter(Trace.TRACE_TAG_APP, + scrim == mScrimInFront ? "front_scrim_tint" : "back_scrim_tint", Color.alpha(tint)); scrimView.setTint(tint); @@ -711,11 +690,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private float getCurrentScrimAlpha(View scrim) { if (scrim == mScrimInFront) { - return mInFrontAlpha; + return mCurrentInFrontAlpha; } else if (scrim == mScrimBehind) { - return mBehindAlpha; - } else if (scrim == mScrimForBubble) { - return mBubbleAlpha; + return mCurrentBehindAlpha; } else { throw new IllegalArgumentException("Unknown scrim view"); } @@ -723,11 +700,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private int getCurrentScrimTint(View scrim) { if (scrim == mScrimInFront) { - return mInFrontTint; + return mCurrentInFrontTint; } else if (scrim == mScrimBehind) { - return mBehindTint; - } else if (scrim == mScrimForBubble) { - return mBubbleTint; + return mCurrentBehindTint; } else { throw new IllegalArgumentException("Unknown scrim view"); } @@ -754,16 +729,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo } private void onFinished(Callback callback) { - if (!hasReachedFinalState(mScrimBehind) - || !hasReachedFinalState(mScrimInFront) - || !hasReachedFinalState(mScrimForBubble)) { - if (callback != null && callback != mCallback) { - // Since we only notify the callback that we're finished once everything has - // finished, we need to make sure that any changing callbacks are also invoked - callback.onFinished(); - } - return; - } if (mWakeLockHeld) { mWakeLock.release(TAG); mWakeLockHeld = false; @@ -780,20 +745,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo // When unlocking with fingerprint, we'll fade the scrims from black to transparent. // At the end of the animation we need to remove the tint. if (mState == ScrimState.UNLOCKED) { - mInFrontTint = Color.TRANSPARENT; - mBehindTint = Color.TRANSPARENT; - mBubbleTint = Color.TRANSPARENT; - updateScrimColor(mScrimInFront, mInFrontAlpha, mInFrontTint); - updateScrimColor(mScrimBehind, mBehindAlpha, mBehindTint); - updateScrimColor(mScrimForBubble, mBubbleAlpha, mBubbleTint); + mCurrentInFrontTint = Color.TRANSPARENT; + mCurrentBehindTint = Color.TRANSPARENT; } } - private boolean hasReachedFinalState(ScrimView scrim) { - return scrim.getViewAlpha() == getCurrentScrimAlpha(scrim) - && scrim.getTint() == getCurrentScrimTint(scrim); - } - private boolean isAnimating(View scrim) { return scrim.getTag(TAG_KEY_ANIM) != null; } @@ -895,7 +851,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo /** * Executes a callback after the frame has hit the display. - * * @param callback What to run. */ @VisibleForTesting @@ -939,35 +894,16 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(" ScrimController: "); - pw.print(" state: "); - pw.println(mState); + pw.print(" state: "); pw.println(mState); + pw.print(" frontScrim:"); pw.print(" viewAlpha="); pw.print(mScrimInFront.getViewAlpha()); + pw.print(" alpha="); pw.print(mCurrentInFrontAlpha); + pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimInFront.getTint())); - pw.print(" frontScrim:"); - pw.print(" viewAlpha="); - pw.print(mScrimInFront.getViewAlpha()); - pw.print(" alpha="); - pw.print(mInFrontAlpha); - pw.print(" tint=0x"); - pw.println(Integer.toHexString(mScrimInFront.getTint())); + pw.print(" backScrim:"); pw.print(" viewAlpha="); pw.print(mScrimBehind.getViewAlpha()); + pw.print(" alpha="); pw.print(mCurrentBehindAlpha); + pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimBehind.getTint())); - pw.print(" backScrim:"); - pw.print(" viewAlpha="); - pw.print(mScrimBehind.getViewAlpha()); - pw.print(" alpha="); - pw.print(mBehindAlpha); - pw.print(" tint=0x"); - pw.println(Integer.toHexString(mScrimBehind.getTint())); - - pw.print(" bubbleScrim:"); - pw.print(" viewAlpha="); - pw.print(mScrimForBubble.getViewAlpha()); - pw.print(" alpha="); - pw.print(mBubbleAlpha); - pw.print(" tint=0x"); - pw.println(Integer.toHexString(mScrimForBubble.getTint())); - - pw.print(" mTracking="); - pw.println(mTracking); + pw.print(" mTracking="); pw.println(mTracking); } public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) { @@ -1014,8 +950,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo // in this case, back-scrim needs to be re-evaluated if (mState == ScrimState.AOD || mState == ScrimState.PULSING) { float newBehindAlpha = mState.getBehindAlpha(); - if (mBehindAlpha != newBehindAlpha) { - mBehindAlpha = newBehindAlpha; + if (mCurrentBehindAlpha != newBehindAlpha) { + mCurrentBehindAlpha = newBehindAlpha; updateScrims(); } } @@ -1036,13 +972,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo public interface Callback { default void onStart() { } - default void onDisplayBlanked() { } - default void onFinished() { } - default void onCancelled() { } /** Returns whether to timeout wallpaper or not. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index 7463c7c232bdd..5fa861c8a2ac2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -36,6 +36,7 @@ public enum ScrimState { * On the lock screen. */ KEYGUARD(0) { + @Override public void prepare(ScrimState previousState) { mBlankScreen = false; @@ -52,13 +53,10 @@ public enum ScrimState { } else { mAnimationDuration = ScrimController.ANIMATION_DURATION; } - mFrontTint = Color.BLACK; - mBehindTint = Color.BLACK; - mBubbleTint = Color.TRANSPARENT; - - mFrontAlpha = 0; - mBehindAlpha = mScrimBehindAlphaKeyguard; - mBubbleAlpha = 0; + mCurrentInFrontTint = Color.BLACK; + mCurrentBehindTint = Color.BLACK; + mCurrentBehindAlpha = mScrimBehindAlphaKeyguard; + mCurrentInFrontAlpha = 0; } }, @@ -68,9 +66,8 @@ public enum ScrimState { BOUNCER(1) { @Override public void prepare(ScrimState previousState) { - mBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; - mFrontAlpha = 0f; - mBubbleAlpha = 0f; + mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; + mCurrentInFrontAlpha = 0f; } }, @@ -80,9 +77,8 @@ public enum ScrimState { BOUNCER_SCRIMMED(2) { @Override public void prepare(ScrimState previousState) { - mBehindAlpha = 0; - mBubbleAlpha = 0f; - mFrontAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; + mCurrentBehindAlpha = 0; + mCurrentInFrontAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; } }, @@ -92,9 +88,8 @@ public enum ScrimState { BRIGHTNESS_MIRROR(3) { @Override public void prepare(ScrimState previousState) { - mBehindAlpha = 0; - mFrontAlpha = 0; - mBubbleAlpha = 0; + mCurrentBehindAlpha = 0; + mCurrentInFrontAlpha = 0; } }, @@ -106,16 +101,9 @@ public enum ScrimState { public void prepare(ScrimState previousState) { final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn(); mBlankScreen = mDisplayRequiresBlanking; - - mFrontTint = Color.BLACK; - mFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f; - - mBehindTint = Color.BLACK; - mBehindAlpha = ScrimController.TRANSPARENT; - - mBubbleTint = Color.TRANSPARENT; - mBubbleAlpha = ScrimController.TRANSPARENT; - + mCurrentInFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f; + mCurrentInFrontTint = Color.BLACK; + mCurrentBehindTint = Color.BLACK; mAnimationDuration = ScrimController.ANIMATION_DURATION_LONG; // DisplayPowerManager may blank the screen for us, // in this case we just need to set our state. @@ -139,10 +127,9 @@ public enum ScrimState { PULSING(5) { @Override public void prepare(ScrimState previousState) { - mFrontAlpha = mAodFrontScrimAlpha; - mBubbleAlpha = 0f; - mBehindTint = Color.BLACK; - mFrontTint = Color.BLACK; + mCurrentInFrontAlpha = mAodFrontScrimAlpha; + mCurrentBehindTint = Color.BLACK; + mCurrentInFrontTint = Color.BLACK; mBlankScreen = mDisplayRequiresBlanking; mAnimationDuration = mWakeLockScreenSensorActive ? ScrimController.ANIMATION_DURATION_LONG : ScrimController.ANIMATION_DURATION; @@ -167,33 +154,26 @@ public enum ScrimState { UNLOCKED(6) { @Override public void prepare(ScrimState previousState) { - // State that UI will sync to. - mBehindAlpha = 0; - mFrontAlpha = 0; - mBubbleAlpha = 0; - + mCurrentBehindAlpha = 0; + mCurrentInFrontAlpha = 0; mAnimationDuration = mKeyguardFadingAway ? mKeyguardFadingAwayDuration : StatusBar.FADE_KEYGUARD_DURATION; mAnimateChange = !mLaunchingAffordanceWithPreview; - mFrontTint = Color.TRANSPARENT; - mBehindTint = Color.TRANSPARENT; - mBubbleTint = Color.TRANSPARENT; - mBlankScreen = false; - if (previousState == ScrimState.AOD) { - // Set all scrims black, before they fade transparent. - updateScrimColor(mScrimInFront, 1f /* alpha */, Color.BLACK /* tint */); - updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK /* tint */); - updateScrimColor(mScrimForBubble, 1f /* alpha */, Color.BLACK /* tint */); - + // Fade from black to transparent when coming directly from AOD + updateScrimColor(mScrimInFront, 1, Color.BLACK); + updateScrimColor(mScrimBehind, 1, Color.BLACK); // Scrims should still be black at the end of the transition. - mFrontTint = Color.BLACK; - mBehindTint = Color.BLACK; - mBubbleTint = Color.BLACK; + mCurrentInFrontTint = Color.BLACK; + mCurrentBehindTint = Color.BLACK; mBlankScreen = true; + } else { + mCurrentInFrontTint = Color.TRANSPARENT; + mCurrentBehindTint = Color.TRANSPARENT; + mBlankScreen = false; } } }, @@ -204,36 +184,25 @@ public enum ScrimState { BUBBLE_EXPANDED(7) { @Override public void prepare(ScrimState previousState) { - mFrontTint = Color.TRANSPARENT; - mBehindTint = Color.TRANSPARENT; - mBubbleTint = Color.TRANSPARENT; - - mFrontAlpha = ScrimController.TRANSPARENT; - mBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; - mBubbleAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; - + mCurrentInFrontTint = Color.TRANSPARENT; + mCurrentBehindTint = Color.TRANSPARENT; mAnimationDuration = ScrimController.ANIMATION_DURATION; + mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; mBlankScreen = false; } }; boolean mBlankScreen = false; long mAnimationDuration = ScrimController.ANIMATION_DURATION; - int mFrontTint = Color.TRANSPARENT; - int mBehindTint = Color.TRANSPARENT; - int mBubbleTint = Color.TRANSPARENT; - + int mCurrentInFrontTint = Color.TRANSPARENT; + int mCurrentBehindTint = Color.TRANSPARENT; boolean mAnimateChange = true; + float mCurrentInFrontAlpha; + float mCurrentBehindAlpha; float mAodFrontScrimAlpha; - float mFrontAlpha; - float mBehindAlpha; - float mBubbleAlpha; - float mScrimBehindAlphaKeyguard; ScrimView mScrimInFront; ScrimView mScrimBehind; - ScrimView mScrimForBubble; - DozeParameters mDozeParameters; boolean mDisplayRequiresBlanking; boolean mWallpaperSupportsAmbientMode; @@ -248,17 +217,13 @@ public enum ScrimState { mIndex = index; } - public void init(ScrimView scrimInFront, ScrimView scrimBehind, ScrimView scrimForBubble, - DozeParameters dozeParameters) { + public void init(ScrimView scrimInFront, ScrimView scrimBehind, DozeParameters dozeParameters) { mScrimInFront = scrimInFront; mScrimBehind = scrimBehind; - mScrimForBubble = scrimForBubble; - mDozeParameters = dozeParameters; mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking(); } - /** Prepare state for transition. */ public void prepare(ScrimState previousState) { } @@ -267,27 +232,19 @@ public enum ScrimState { } public float getFrontAlpha() { - return mFrontAlpha; + return mCurrentInFrontAlpha; } public float getBehindAlpha() { - return mBehindAlpha; - } - - public float getBubbleAlpha() { - return mBubbleAlpha; + return mCurrentBehindAlpha; } public int getFrontTint() { - return mFrontTint; + return mCurrentInFrontTint; } public int getBehindTint() { - return mBehindTint; - } - - public int getBubbleTint() { - return mBubbleTint; + return mCurrentBehindTint; } public long getAnimationDuration() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index fc20d83b9ddb7..559df18ef478a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -229,6 +229,7 @@ import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserInfoControllerImpl; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.statusbar.policy.ZenModeController; +import com.android.systemui.tuner.TunerService; import com.android.systemui.util.InjectionInflationController; import com.android.systemui.volume.VolumeComponent; @@ -811,7 +812,6 @@ public class StatusBar extends SystemUI implements DemoMode, // TODO: Deal with the ugliness that comes from having some of the statusbar broken out // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot. mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel); - mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller); mZenController.addCallback(this); NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller; @@ -932,10 +932,8 @@ public class StatusBar extends SystemUI implements DemoMode, ScrimView scrimBehind = mStatusBarWindow.findViewById(R.id.scrim_behind); ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front); - ScrimView scrimForBubble = mStatusBarWindow.findViewById(R.id.scrim_for_bubble); - mScrimController = SystemUIFactory.getInstance().createScrimController( - scrimBehind, scrimInFront, scrimForBubble, mLockscreenWallpaper, + scrimBehind, scrimInFront, mLockscreenWallpaper, (state, alpha, color) -> mLightBarController.setScrimState(state, alpha, color), scrimsVisible -> { if (mStatusBarWindowController != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java index a870590c08ac7..069219802cc3d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java @@ -224,7 +224,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter, mVisualStabilityManager.setUpWithPresenter(this); mGutsManager.setUpWithPresenter(this, notifListContainer, mCheckSaveListener, mOnSettingsClickListener); - // ForegroundServiceControllerListener adds its listener in its constructor + // ForegroundServiceNotificationListener adds its listener in its constructor // but we need to request it here in order for it to be instantiated. // TODO: figure out how to do this correctly once Dependency.get() is gone. Dependency.get(ForegroundServiceNotificationListener.class); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java index d3ae5cf35b0cc..946fe0b3a2f85 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java @@ -222,7 +222,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat } final boolean scrimsOccludingWallpaper = - state.scrimsVisibility == ScrimController.OPAQUE; + state.scrimsVisibility == ScrimController.VISIBILITY_FULLY_OPAQUE; final boolean keyguardOrAod = state.keyguardShowing || (state.dozing && mDozeParameters.getAlwaysOn()); if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) { @@ -308,7 +308,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded() || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing || state.headsUpShowing || state.bubblesShowing - || state.scrimsVisibility != ScrimController.TRANSPARENT); + || state.scrimsVisibility != ScrimController.VISIBILITY_FULLY_TRANSPARENT); } private void applyFitsSystemWindows(State state) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceLifetimeExtenderTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceLifetimeExtenderTest.java new file mode 100644 index 0000000000000..b1dabdda2241b --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceLifetimeExtenderTest.java @@ -0,0 +1,82 @@ +/* + * 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; + +import static com.android.systemui.ForegroundServiceLifetimeExtender.MIN_FGS_TIME_MS; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.app.Notification; +import android.service.notification.StatusBarNotification; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.systemui.statusbar.notification.collection.NotificationEntry; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class ForegroundServiceLifetimeExtenderTest extends SysuiTestCase { + private ForegroundServiceLifetimeExtender mExtender = new ForegroundServiceLifetimeExtender(); + private StatusBarNotification mSbn; + private NotificationEntry mEntry; + private Notification mNotif; + + @Before + public void setup() { + mNotif = new Notification.Builder(mContext, "") + .setSmallIcon(R.drawable.ic_person) + .setContentTitle("Title") + .setContentText("Text") + .build(); + + mSbn = mock(StatusBarNotification.class); + when(mSbn.getNotification()).thenReturn(mNotif); + + mEntry = new NotificationEntry(mSbn); + } + + @Test + public void testShouldExtendLifetime_should_foreground() { + // Extend the lifetime of a FGS notification iff it has not been visible + // for the minimum time + mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE; + when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis()); + assertTrue(mExtender.shouldExtendLifetime(mEntry)); + } + + @Test + public void testShouldExtendLifetime_shouldNot_foreground() { + mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE; + when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis() - MIN_FGS_TIME_MS - 1); + assertFalse(mExtender.shouldExtendLifetime(mEntry)); + } + + @Test + public void testShouldExtendLifetime_shouldNot_notForeground() { + mNotif.flags = 0; + when(mSbn.getPostTime()).thenReturn(System.currentTimeMillis() - MIN_FGS_TIME_MS - 1); + assertFalse(mExtender.shouldExtendLifetime(mEntry)); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index d4ad4b6d4f166..205312ca508ff 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -16,9 +16,9 @@ package com.android.systemui.statusbar.phone; -import static com.android.systemui.statusbar.phone.ScrimController.OPAQUE; -import static com.android.systemui.statusbar.phone.ScrimController.SEMI_TRANSPARENT; -import static com.android.systemui.statusbar.phone.ScrimController.TRANSPARENT; +import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_FULLY_OPAQUE; +import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_FULLY_TRANSPARENT; +import static com.android.systemui.statusbar.phone.ScrimController.VISIBILITY_SEMI_TRANSPARENT; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -69,7 +69,6 @@ public class ScrimControllerTest extends SysuiTestCase { private SynchronousScrimController mScrimController; private ScrimView mScrimBehind; private ScrimView mScrimInFront; - private ScrimView mScrimForBubble; private ScrimState mScrimState; private float mScrimBehindAlpha; private GradientColors mScrimInFrontColor; @@ -85,7 +84,6 @@ public class ScrimControllerTest extends SysuiTestCase { public void setup() { mScrimBehind = spy(new ScrimView(getContext())); mScrimInFront = new ScrimView(getContext()); - mScrimForBubble = new ScrimView(getContext()); mWakeLock = mock(WakeLock.class); mAlarmManager = mock(AlarmManager.class); mAlwaysOnEnabled = true; @@ -94,7 +92,6 @@ public class ScrimControllerTest extends SysuiTestCase { when(mDozeParamenters.getAlwaysOn()).thenAnswer(invocation -> mAlwaysOnEnabled); when(mDozeParamenters.getDisplayNeedsBlanking()).thenReturn(true); mScrimController = new SynchronousScrimController(mScrimBehind, mScrimInFront, - mScrimForBubble, (scrimState, scrimBehindAlpha, scrimInFrontColor) -> { mScrimState = scrimState; mScrimBehindAlpha = scrimBehindAlpha; @@ -117,28 +114,21 @@ public class ScrimControllerTest extends SysuiTestCase { public void transitionToKeyguard() { mScrimController.transitionTo(ScrimState.KEYGUARD); mScrimController.finishAnimationsImmediately(); - - assertScrimAlpha(TRANSPARENT /* front */, - SEMI_TRANSPARENT /* back */, - TRANSPARENT /* bubble */); - - assertScrimTint(true /* front */, - true /* behind */, - false /* bubble */); + // Front scrim should be transparent + // Back scrim should be visible without tint + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); + assertScrimTint(mScrimBehind, true /* tinted */); } @Test public void transitionToAod_withRegularWallpaper() { mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - - assertScrimAlpha(TRANSPARENT /* front */, - OPAQUE /* back */, - TRANSPARENT /* bubble */); - - assertScrimTint(true /* front */, - true /* behind */, - false /* bubble */); + // Front scrim should be transparent + // Back scrim should be visible with tint + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + assertScrimTint(mScrimBehind, true /* tinted */); + assertScrimTint(mScrimInFront, true /* tinted */); } @Test @@ -146,18 +136,14 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setWallpaperSupportsAmbientMode(true); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - - assertScrimAlpha(TRANSPARENT /* front */, - TRANSPARENT /* back */, - TRANSPARENT /* bubble */); + // Front scrim should be transparent + // Back scrim should be transparent + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); // Pulsing notification should conserve AOD wallpaper. mScrimController.transitionTo(ScrimState.PULSING); mScrimController.finishAnimationsImmediately(); - - assertScrimAlpha(TRANSPARENT /* front */, - TRANSPARENT /* back */, - TRANSPARENT /* bubble */); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); } @Test @@ -166,14 +152,11 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setWallpaperSupportsAmbientMode(true); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - - assertScrimAlpha(TRANSPARENT /* front */, - OPAQUE /* back */, - TRANSPARENT /* bubble */); - - assertScrimTint(true /* front */, - true /* behind */, - false /* bubble */); + // Front scrim should be transparent + // Back scrim should be visible with tint + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + assertScrimTint(mScrimBehind, true /* tinted */); + assertScrimTint(mScrimInFront, true /* tinted */); } @Test @@ -183,14 +166,11 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.finishAnimationsImmediately(); mScrimController.setHasBackdrop(true); mScrimController.finishAnimationsImmediately(); - - assertScrimAlpha(TRANSPARENT /* front */, - OPAQUE /* back */, - TRANSPARENT /* bubble */); - - assertScrimTint(true /* front */, - true /* behind */, - false /* bubble */); + // Front scrim should be transparent + // Back scrim should be visible with tint + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + assertScrimTint(mScrimBehind, true /* tinted */); + assertScrimTint(mScrimInFront, true /* tinted */); } @Test @@ -199,32 +179,27 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.transitionTo(ScrimState.KEYGUARD); mScrimController.setAodFrontScrimAlpha(0.5f); mScrimController.finishAnimationsImmediately(); - - assertScrimAlpha(TRANSPARENT /* front */, - SEMI_TRANSPARENT /* back */, - TRANSPARENT /* bubble */); + // Front scrim should be transparent + // Back scrim should be visible without tint + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); // ... but that it does take effect once we enter the AOD state. mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - assertScrimAlpha(SEMI_TRANSPARENT /* front */, - OPAQUE /* back */, - TRANSPARENT /* bubble */); + // Front scrim should be semi-transparent + // Back scrim should be visible + assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); // ... and that if we set it while we're in AOD, it does take immediate effect. mScrimController.setAodFrontScrimAlpha(1f); - assertScrimAlpha(OPAQUE /* front */, - OPAQUE /* back */, - TRANSPARENT /* bubble */); + assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE); // ... and make sure we recall the previous front scrim alpha even if we transition away // for a bit. mScrimController.transitionTo(ScrimState.UNLOCKED); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - assertScrimAlpha(OPAQUE /* front */, - OPAQUE /* back */, - TRANSPARENT /* bubble */); + assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE); // ... and alpha updates should be completely ignored if always_on is off. // Passing it forward would mess up the wake-up transition. @@ -248,36 +223,27 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setWallpaperSupportsAmbientMode(false); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - assertScrimAlpha(TRANSPARENT /* front */, - OPAQUE /* back */, - TRANSPARENT /* bubble */); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); mScrimController.transitionTo(ScrimState.PULSING); mScrimController.finishAnimationsImmediately(); // Front scrim should be transparent, but tinted // Back scrim should be semi-transparent so the user can see the wallpaper // Pulse callback should have been invoked - assertScrimAlpha(TRANSPARENT /* front */, - OPAQUE /* back */, - TRANSPARENT /* bubble */); - - assertScrimTint(true /* front */, - true /* behind */, - false /* bubble */); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + assertScrimTint(mScrimBehind, true /* tinted */); // ... and when ambient goes dark, front scrim should be semi-transparent mScrimController.setAodFrontScrimAlpha(0.5f); mScrimController.finishAnimationsImmediately(); // Front scrim should be semi-transparent - assertScrimAlpha(SEMI_TRANSPARENT /* front */, - OPAQUE /* back */, - TRANSPARENT /* bubble */); + assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT /* front */, + VISIBILITY_FULLY_OPAQUE /* back */); mScrimController.setWakeLockScreenSensorActive(true); mScrimController.finishAnimationsImmediately(); - assertScrimAlpha(SEMI_TRANSPARENT /* front */, - SEMI_TRANSPARENT /* back */, - TRANSPARENT /* bubble */); + assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT /* front */, + VISIBILITY_SEMI_TRANSPARENT /* back */); // Reset value since enums are static. mScrimController.setAodFrontScrimAlpha(0f); @@ -289,13 +255,8 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.finishAnimationsImmediately(); // Front scrim should be transparent // Back scrim should be visible without tint - assertScrimAlpha(TRANSPARENT /* front */, - SEMI_TRANSPARENT /* back */, - TRANSPARENT /* bubble */); - - assertScrimTint(false /* front */, - false /* behind */, - false /* bubble */); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); + assertScrimTint(mScrimBehind, false /* tinted */); } @Test @@ -304,12 +265,8 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.finishAnimationsImmediately(); // Front scrim should be transparent // Back scrim should be visible without tint - assertScrimAlpha(SEMI_TRANSPARENT /* front */, - TRANSPARENT /* back */, - TRANSPARENT /* bubble */); - assertScrimTint(false /* front */, - false /* behind */, - false /* bubble */); + assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); + assertScrimTint(mScrimBehind, false /* tinted */); } @Test @@ -317,19 +274,15 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setPanelExpansion(0f); mScrimController.transitionTo(ScrimState.UNLOCKED); mScrimController.finishAnimationsImmediately(); - assertScrimAlpha(TRANSPARENT /* front */, - TRANSPARENT /* back */, - TRANSPARENT /* bubble */); - - assertScrimTint(false /* front */, - false /* behind */, - false /* bubble */); + // Front scrim should be transparent + // Back scrim should be transparent + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); + assertScrimTint(mScrimBehind, false /* tinted */); + assertScrimTint(mScrimInFront, false /* tinted */); // Back scrim should be visible after start dragging mScrimController.setPanelExpansion(0.5f); - assertScrimAlpha(TRANSPARENT /* front */, - SEMI_TRANSPARENT /* back */, - TRANSPARENT /* bubble */); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); } @Test @@ -337,19 +290,12 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED); mScrimController.finishAnimationsImmediately(); - assertScrimTint(false /* front */, - false /* behind */, - false /* bubble */); - // Front scrim should be transparent - Assert.assertEquals(ScrimController.TRANSPARENT, + Assert.assertEquals(ScrimController.VISIBILITY_FULLY_TRANSPARENT, mScrimInFront.getViewAlpha(), 0.0f); // Back scrim should be visible Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mScrimBehind.getViewAlpha(), 0.0f); - // Bubble scrim should be visible - Assert.assertEquals(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, - mScrimBehind.getViewAlpha(), 0.0f); } @Test @@ -418,23 +364,16 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setPanelExpansion(0f); mScrimController.finishAnimationsImmediately(); mScrimController.transitionTo(ScrimState.UNLOCKED); - - // Immediately tinted black after the transition starts - assertScrimTint(true /* front */, - true /* behind */, - true /* bubble */); - + // Immediately tinted after the transition starts + assertScrimTint(mScrimInFront, true /* tinted */); + assertScrimTint(mScrimBehind, true /* tinted */); mScrimController.finishAnimationsImmediately(); - - // All scrims should be transparent at the end of fade transition. - assertScrimAlpha(TRANSPARENT /* front */, - TRANSPARENT /* behind */, - TRANSPARENT /* bubble */); - - // Make sure at the very end of the animation, we're reset to transparent - assertScrimTint(false /* front */, - false /* behind */, - false /* bubble */); + // Front scrim should be transparent + // Back scrim should be transparent + // Neither scrims should be tinted anymore after the animation. + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); + assertScrimTint(mScrimInFront, false /* tinted */); + assertScrimTint(mScrimBehind, false /* tinted */); } @Test @@ -449,11 +388,9 @@ public class ScrimControllerTest extends SysuiTestCase { // Front scrim should be black in the middle of the transition Assert.assertTrue("Scrim should be visible during transition. Alpha: " + mScrimInFront.getViewAlpha(), mScrimInFront.getViewAlpha() > 0); - assertScrimTint(true /* front */, - true /* behind */, - true /* bubble */); + assertScrimTint(mScrimInFront, true /* tinted */); Assert.assertSame("Scrim should be visible during transition.", - mScrimVisibility, OPAQUE); + mScrimVisibility, VISIBILITY_FULLY_OPAQUE); } }); mScrimController.finishAnimationsImmediately(); @@ -661,15 +598,11 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setKeyguardOccluded(true); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - assertScrimAlpha(TRANSPARENT /* front */, - OPAQUE /* behind */, - TRANSPARENT /* bubble */); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); mScrimController.transitionTo(ScrimState.PULSING); mScrimController.finishAnimationsImmediately(); - assertScrimAlpha(TRANSPARENT /* front */, - OPAQUE /* behind */, - TRANSPARENT /* bubble */); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); } @Test @@ -677,15 +610,11 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.setWallpaperSupportsAmbientMode(true); mScrimController.transitionTo(ScrimState.AOD); mScrimController.finishAnimationsImmediately(); - assertScrimAlpha(TRANSPARENT /* front */, - TRANSPARENT /* behind */, - TRANSPARENT /* bubble */); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); mScrimController.setKeyguardOccluded(true); mScrimController.finishAnimationsImmediately(); - assertScrimAlpha(TRANSPARENT /* front */, - OPAQUE /* behind */, - TRANSPARENT /* bubble */); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); } @Test @@ -724,68 +653,33 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimInFront.getDefaultFocusHighlightEnabled()); Assert.assertFalse("Scrim shouldn't have focus highlight", mScrimBehind.getDefaultFocusHighlightEnabled()); - Assert.assertFalse("Scrim shouldn't have focus highlight", - mScrimForBubble.getDefaultFocusHighlightEnabled()); } - private void assertScrimTint(boolean front, boolean behind, boolean bubble) { + private void assertScrimTint(ScrimView scrimView, boolean tinted) { + final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT; + final String name = scrimView == mScrimInFront ? "front" : "back"; Assert.assertEquals("Tint test failed at state " + mScrimController.getState() - + " with scrim: " + getScrimName(mScrimInFront) + " and tint: " - + Integer.toHexString(mScrimInFront.getTint()), - front, mScrimInFront.getTint() != Color.TRANSPARENT); - - Assert.assertEquals("Tint test failed at state " + mScrimController.getState() - + " with scrim: " + getScrimName(mScrimBehind) + " and tint: " - + Integer.toHexString(mScrimBehind.getTint()), - behind, mScrimBehind.getTint() != Color.TRANSPARENT); - - Assert.assertEquals("Tint test failed at state " + mScrimController.getState() - + " with scrim: " + getScrimName(mScrimForBubble) + " and tint: " - + Integer.toHexString(mScrimForBubble.getTint()), - bubble, mScrimForBubble.getTint() != Color.TRANSPARENT); + +" with scrim: " + name + " and tint: " + Integer.toHexString(scrimView.getTint()), + tinted, viewIsTinted); } - private String getScrimName(ScrimView scrim) { - if (scrim == mScrimInFront) { - return "front"; - } else if (scrim == mScrimBehind) { - return "back"; - } else if (scrim == mScrimForBubble) { - return "bubble"; - } - return "unknown_scrim"; - } + private void assertScrimVisibility(int inFront, int behind) { + boolean inFrontVisible = inFront != ScrimController.VISIBILITY_FULLY_TRANSPARENT; + boolean behindVisible = behind != ScrimController.VISIBILITY_FULLY_TRANSPARENT; + Assert.assertEquals("Unexpected front scrim visibility. Alpha is " + + mScrimInFront.getViewAlpha(), inFrontVisible, mScrimInFront.getViewAlpha() > 0); + Assert.assertEquals("Unexpected back scrim visibility. Alpha is " + + mScrimBehind.getViewAlpha(), behindVisible, mScrimBehind.getViewAlpha() > 0); - private void assertScrimAlpha(int front, int behind, int bubble) { - // Check single scrim visibility. - Assert.assertEquals("Unexpected front scrim alpha: " - + mScrimInFront.getViewAlpha(), - front != TRANSPARENT /* expected */, - mScrimInFront.getViewAlpha() > TRANSPARENT /* actual */); - - Assert.assertEquals("Unexpected back scrim alpha: " - + mScrimBehind.getViewAlpha(), - behind != TRANSPARENT /* expected */, - mScrimBehind.getViewAlpha() > TRANSPARENT /* actual */); - - Assert.assertEquals( - "Unexpected bubble scrim alpha: " - + mScrimForBubble.getViewAlpha(), /* message */ - bubble != TRANSPARENT /* expected */, - mScrimForBubble.getViewAlpha() > TRANSPARENT /* actual */); - - // Check combined scrim visibility. final int visibility; - if (front == OPAQUE || behind == OPAQUE || bubble == OPAQUE) { - visibility = OPAQUE; - } else if (front > TRANSPARENT || behind > TRANSPARENT || bubble > TRANSPARENT) { - visibility = SEMI_TRANSPARENT; + if (inFront == VISIBILITY_FULLY_OPAQUE || behind == VISIBILITY_FULLY_OPAQUE) { + visibility = VISIBILITY_FULLY_OPAQUE; + } else if (inFront > VISIBILITY_FULLY_TRANSPARENT || behind > VISIBILITY_FULLY_TRANSPARENT) { + visibility = VISIBILITY_SEMI_TRANSPARENT; } else { - visibility = TRANSPARENT; + visibility = VISIBILITY_FULLY_TRANSPARENT; } - Assert.assertEquals("Invalid visibility.", - visibility /* expected */, - mScrimVisibility); + Assert.assertEquals("Invalid visibility.", visibility, mScrimVisibility); } /** @@ -797,12 +691,11 @@ public class ScrimControllerTest extends SysuiTestCase { boolean mOnPreDrawCalled; SynchronousScrimController(ScrimView scrimBehind, ScrimView scrimInFront, - ScrimView scrimForBubble, TriConsumer scrimStateListener, Consumer scrimVisibleListener, DozeParameters dozeParameters, AlarmManager alarmManager, KeyguardMonitor keyguardMonitor) { - super(scrimBehind, scrimInFront, scrimForBubble, scrimStateListener, - scrimVisibleListener, dozeParameters, alarmManager, keyguardMonitor); + super(scrimBehind, scrimInFront, scrimStateListener, scrimVisibleListener, + dozeParameters, alarmManager, keyguardMonitor); } @Override @@ -813,14 +706,13 @@ public class ScrimControllerTest extends SysuiTestCase { void finishAnimationsImmediately() { boolean[] animationFinished = {false}; - setOnAnimationFinished(() -> animationFinished[0] = true); + setOnAnimationFinished(()-> animationFinished[0] = true); // Execute code that will trigger animations. onPreDraw(); // Force finish all animations. mLooper.processAllMessages(); endAnimation(mScrimBehind, TAG_KEY_ANIM); endAnimation(mScrimInFront, TAG_KEY_ANIM); - endAnimation(mScrimForBubble, TAG_KEY_ANIM); if (!animationFinished[0]) { throw new IllegalStateException("Animation never finished"); @@ -858,7 +750,6 @@ public class ScrimControllerTest extends SysuiTestCase { /** * Do not wait for a frame since we're in a test environment. - * * @param callback What to execute. */ @Override diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto index fbf6ca52f11c6..353a18756ca2b 100644 --- a/proto/src/wifi.proto +++ b/proto/src/wifi.proto @@ -1798,12 +1798,12 @@ message ExperimentValues { optional int32 data_stall_duration_ms = 5; // Threshold of Tx throughput below which to trigger a data stall - // measured in Kbps - optional int32 data_stall_tx_tput_thr_kbps = 6; + // measured in Mbps + optional int32 data_stall_tx_tput_thr_mbps = 6; // Threshold of Rx throughput below which to trigger a data stall - // measured in Kbps - optional int32 data_stall_rx_tput_thr_kbps = 7; + // measured in Mbps + optional int32 data_stall_rx_tput_thr_mbps = 7; // Threshold of Tx packet error rate above which to trigger a data stall // in percentage diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 655b9ac10b844..6f45825e81fe3 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1463,7 +1463,7 @@ public class NotificationManagerService extends SystemService { } else { // Secure => Global Settings.Secure.putInt(resolver, - Settings.Secure.NOTIFICATION_BADGING, + Settings.Secure.NOTIFICATION_BUBBLES, globalSettingValue); } } @@ -5356,8 +5356,16 @@ public class NotificationManagerService extends SystemService { } synchronized (mNotificationLock) { - // Look for the notification, searching both the posted and enqueued lists. - NotificationRecord r = findNotificationLocked(mPkg, mTag, mId, mUserId); + // If the notification is currently enqueued, repost this runnable so it has a + // chance to notify listeners + if ((findNotificationByListLocked(mEnqueuedNotifications, mPkg, mTag, mId, mUserId)) + != null) { + mHandler.post(this); + return; + } + // Look for the notification in the posted list, since we already checked enqueued. + NotificationRecord r = + findNotificationByListLocked(mNotificationList, mPkg, mTag, mId, mUserId); if (r != null) { // The notification was found, check if it should be removed. diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index e75f545eafaa5..0329e2c5ed45b 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -491,6 +491,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements params.installFlags &= ~PackageManager.INSTALL_FROM_ADB; params.installFlags &= ~PackageManager.INSTALL_ALL_USERS; + params.installFlags &= ~PackageManager.INSTALL_ALLOW_TEST; params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; if ((params.installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0 && !mPm.isCallerVerifier(callingUid)) { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 389b68a7d4b79..b5542afed46d4 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -1016,6 +1016,20 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(0, mService.getNotificationRecordCount()); } + @Test + public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag() + throws Exception { + final StatusBarNotification sbn = generateNotificationRecord(null).sbn; + sbn.getNotification().flags = + Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; + mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId()); + waitForIdle(); + verify(mListeners, times(1)).notifyPostedLocked(any(), any()); + verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any()); + } + @Test public void testUserInitiatedClearAll_noLeak() throws Exception { final NotificationRecord n = generateNotificationRecord(