diff options
| -rw-r--r-- | core/api/current.txt | 2 | ||||
| -rw-r--r-- | core/java/android/view/Window.java | 24 | ||||
| -rw-r--r-- | core/java/com/android/internal/policy/DecorView.java | 55 | ||||
| -rw-r--r-- | core/java/com/android/internal/policy/PhoneWindow.java | 14 | ||||
| -rw-r--r-- | core/res/res/values/attrs.xml | 7 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 1 |
6 files changed, 96 insertions, 7 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index c72608f89fac..2ba2bb2903a1 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -1614,6 +1614,7 @@ package android { field public static final int windowAllowReturnTransitionOverlap = 16843835; // 0x101043b field public static final int windowAnimationStyle = 16842926; // 0x10100ae field public static final int windowBackground = 16842836; // 0x1010054 + field public static final int windowBackgroundBlurRadius = 16844331; // 0x101062b field public static final int windowBackgroundFallback = 16844035; // 0x1010503 field public static final int windowBlurBehindEnabled = 16844316; // 0x101061c field public static final int windowBlurBehindRadius = 16844315; // 0x101061b @@ -49353,6 +49354,7 @@ package android.view { method public void setAllowEnterTransitionOverlap(boolean); method public void setAllowReturnTransitionOverlap(boolean); method public void setAttributes(android.view.WindowManager.LayoutParams); + method public void setBackgroundBlurRadius(int); method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable); method public void setBackgroundDrawableResource(@DrawableRes int); method public void setCallback(android.view.Window.Callback); diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index af18293398da..4ecdd78f5a42 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -1703,6 +1703,30 @@ public abstract class Window { public abstract void setBackgroundDrawable(Drawable drawable); /** + * Blurs the screen behind the window within the bounds of the window. + * + * The density of the blur is set by the blur radius. The radius defines the size + * of the neighbouring area, from which pixels will be averaged to form the final + * color for each pixel. The operation approximates a Gaussian blur. + * A radius of 0 means no blur. The higher the radius, the denser the blur. + * + * The window background drawable is drawn on top of the blurred region. The blur + * region bounds and rounded corners will mimic those of the background drawable. + * + * For the blur region to be visible, the window has to be translucent. See + * {@link android.R.styleable#Window_windowIsTranslucent}. + * + * Note the difference with {@link android.view.WindowManager.LayoutParams#blurBehindRadius}, + * which blurs the whole screen behind the window. Background blur blurs the screen behind + * only within the bounds of the window. + * + * @param blurRadius The blur radius to use for window background blur in pixels + * + * @see android.R.styleable#Window_windowBackgroundBlurRadius + */ + public void setBackgroundBlurRadius(int blurRadius) {} + + /** * Set the value for a drawable feature of this window, from a resource * identifier. You must have called requestFeature(featureId) before * calling this function. diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index adebde016bb3..9840013935f8 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -110,6 +110,7 @@ import android.widget.FrameLayout; import android.widget.PopupWindow; import com.android.internal.R; +import com.android.internal.graphics.drawable.BackgroundBlurDrawable; import com.android.internal.policy.PhoneWindow.PanelFeatureState; import com.android.internal.policy.PhoneWindow.PhoneWindowMenuCallback; import com.android.internal.view.FloatingActionMode; @@ -255,6 +256,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private Drawable mOriginalBackgroundDrawable; private Drawable mLastOriginalBackgroundDrawable; private Drawable mResizingBackgroundDrawable; + private BackgroundBlurDrawable mBackgroundBlurDrawable; /** * Temporary holder for a window background when it is set before {@link #mWindow} is @@ -280,9 +282,14 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private final Paint mLegacyNavigationBarBackgroundPaint = new Paint(); private Insets mBackgroundInsets = Insets.NONE; private Insets mLastBackgroundInsets = Insets.NONE; + private int mLastBackgroundBlurRadius = 0; private boolean mDrawLegacyNavigationBarBackground; private PendingInsetsController mPendingInsetsController = new PendingInsetsController(); + private final ViewTreeObserver.OnPreDrawListener mBackgroundBlurOnPreDrawListener = () -> { + updateBackgroundBlur(); + return true; + }; DecorView(Context context, int featureId, PhoneWindow window, WindowManager.LayoutParams params) { @@ -1263,18 +1270,27 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind if (mBackgroundInsets == null) { mBackgroundInsets = Insets.NONE; } + if (mBackgroundInsets.equals(mLastBackgroundInsets) + && mWindow.mBackgroundBlurRadius == mLastBackgroundBlurRadius && mLastOriginalBackgroundDrawable == mOriginalBackgroundDrawable) { return; } - if (mOriginalBackgroundDrawable == null || mBackgroundInsets.equals(Insets.NONE)) { - // Call super since we are intercepting setBackground on this class. - super.setBackgroundDrawable(mOriginalBackgroundDrawable); - } else { + Drawable destDrawable = mOriginalBackgroundDrawable; + if (mWindow.mBackgroundBlurRadius > 0 && getViewRootImpl() != null + && mWindow.isTranslucent()) { + if (mBackgroundBlurDrawable == null) { + mBackgroundBlurDrawable = getViewRootImpl().createBackgroundBlurDrawable(); + } + destDrawable = new LayerDrawable(new Drawable[] {mBackgroundBlurDrawable, + mOriginalBackgroundDrawable}); + mLastBackgroundBlurRadius = mWindow.mBackgroundBlurRadius; + } - // Call super since we are intercepting setBackground on this class. - super.setBackgroundDrawable(new InsetDrawable(mOriginalBackgroundDrawable, + + if (destDrawable != null && !mBackgroundInsets.equals(Insets.NONE)) { + destDrawable = new InsetDrawable(destDrawable, mBackgroundInsets.left, mBackgroundInsets.top, mBackgroundInsets.right, mBackgroundInsets.bottom) { @@ -1286,12 +1302,32 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind public boolean getPadding(Rect padding) { return getDrawable().getPadding(padding); } - }); + }; } + + // Call super since we are intercepting setBackground on this class. + super.setBackgroundDrawable(destDrawable); + mLastBackgroundInsets = mBackgroundInsets; mLastOriginalBackgroundDrawable = mOriginalBackgroundDrawable; } + private void updateBackgroundBlur() { + if (mBackgroundBlurDrawable == null) return; + + // If the blur radius is 0, the blur region won't be sent to surface flinger, so we don't + // need to calculate the corner radius. + if (mWindow.mBackgroundBlurRadius > 0) { + if (mOriginalBackgroundDrawable != null) { + final Outline outline = new Outline(); + mOriginalBackgroundDrawable.getOutline(outline); + mBackgroundBlurDrawable.setCornerRadius(outline.mMode == Outline.MODE_ROUND_RECT + ? outline.getRadius() : 0); + } + } + mBackgroundBlurDrawable.setBlurRadius(mWindow.mBackgroundBlurRadius); + } + @Override public Drawable getBackground() { return mOriginalBackgroundDrawable; @@ -1722,6 +1758,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind cb.onAttachedToWindow(); } + getViewTreeObserver().addOnPreDrawListener(mBackgroundBlurOnPreDrawListener); + updateBackgroundDrawable(); + if (mFeatureId == -1) { /* * The main window has been attached, try to restore any panels @@ -1755,6 +1794,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind cb.onDetachedFromWindow(); } + getViewTreeObserver().removeOnPreDrawListener(mBackgroundBlurOnPreDrawListener); + if (mWindow.mDecorContentParent != null) { mWindow.mDecorContentParent.dismissPopups(); } diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 5df175e8aee5..d06413c3ca15 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -258,6 +258,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { Drawable mBackgroundDrawable = null; Drawable mBackgroundFallbackDrawable = null; + int mBackgroundBlurRadius = 0; + private boolean mLoadElevation = true; private float mElevation; @@ -1523,6 +1525,15 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } @Override + public final void setBackgroundBlurRadius(int blurRadius) { + super.setBackgroundBlurRadius(blurRadius); + if (getContext().getPackageManager().hasSystemFeature( + PackageManager.FEATURE_CROSS_LAYER_BLUR)) { + mBackgroundBlurRadius = Math.max(blurRadius, 0); + } + } + + @Override public final void setFeatureDrawableResource(int featureId, int resId) { if (resId != 0) { DrawableFeatureState st = getDrawableState(featureId, true); @@ -2549,6 +2560,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { android.R.styleable.Window_windowBlurBehindRadius, 0); } + setBackgroundBlurRadius(a.getDimensionPixelSize( + R.styleable.Window_windowBackgroundBlurRadius, 0)); + if (params.windowAnimations == 0) { params.windowAnimations = a.getResourceId( diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index aeb4fc468fe4..823e10edaad5 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -362,6 +362,12 @@ surface when the app has not drawn any content into this area. One example is when the user is resizing a window of an activity in multi-window mode. --> <attr name="windowBackgroundFallback" format="reference|color" /> + <!-- Blur the screen behind the window with the bounds of the window. + The radius defines the size of the neighbouring area, from which pixels will be + averaged to form the final color for each pixel in the region. + A radius of 0 means no blur. The higher the radius, the denser the blur. + Corresponds to {@link android.view.Window#setBackgroundBlurRadius}. --> + <attr name="windowBackgroundBlurRadius" format="dimension" /> <!-- Drawable to use as a frame around the window. --> <attr name="windowFrame" format="reference" /> <!-- Flag indicating whether there should be no title on this window. --> @@ -1966,6 +1972,7 @@ <declare-styleable name="Window"> <attr name="windowBackground" /> <attr name="windowBackgroundFallback" /> + <attr name="windowBackgroundBlurRadius" /> <attr name="windowContentOverlay" /> <attr name="windowFrame" /> <attr name="windowNoTitle" /> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 068987ec8afe..3c97aec5d55d 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3065,6 +3065,7 @@ <public name="clipToOutline" /> <public name="edgeEffectType" /> <public name="knownCerts" /> + <public name="windowBackgroundBlurRadius"/> </public-group> <public-group type="drawable" first-id="0x010800b5"> |