summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt3
-rw-r--r--core/api/system-current.txt1
-rw-r--r--core/java/android/content/pm/PackageManager.java11
-rw-r--r--core/java/android/view/CrossWindowBlurListeners.java137
-rw-r--r--core/java/android/view/ICrossWindowBlurEnabledListener.aidl29
-rw-r--r--core/java/android/view/IWindowManager.aidl19
-rw-r--r--core/java/android/view/Window.java8
-rw-r--r--core/java/android/view/WindowManager.java71
-rw-r--r--core/java/android/view/WindowManagerImpl.java16
-rw-r--r--core/java/com/android/internal/policy/DecorView.java81
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java11
-rw-r--r--core/java/com/android/server/SystemConfig.java7
-rw-r--r--services/core/java/com/android/server/wm/BlurController.java76
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java16
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java9
15 files changed, 444 insertions, 51 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index cb7fc24e3977..ed357d7a3228 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -50154,9 +50154,12 @@ package android.view {
}
public interface WindowManager extends android.view.ViewManager {
+ method public default void addCrossWindowBlurEnabledListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
method @NonNull public default android.view.WindowMetrics getCurrentWindowMetrics();
method @Deprecated public android.view.Display getDefaultDisplay();
method @NonNull public default android.view.WindowMetrics getMaximumWindowMetrics();
+ method public default boolean isCrossWindowBlurEnabled();
+ method public default void removeCrossWindowBlurEnabledListener(@NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void removeViewImmediate(android.view.View);
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index c62b808b00b4..c9f8da2b350e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -2555,7 +2555,6 @@ package android.content.pm {
field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";
field public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";
field public static final String FEATURE_CONTEXT_HUB = "android.hardware.context_hub";
- field public static final String FEATURE_CROSS_LAYER_BLUR = "android.software.cross_layer_blur";
field @Deprecated public static final String FEATURE_INCREMENTAL_DELIVERY = "android.software.incremental_delivery";
field public static final String FEATURE_INCREMENTAL_DELIVERY_VERSION = "android.software.incremental_delivery_version";
field public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle";
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ca882417394e..993f09e83ebd 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3656,17 +3656,6 @@ public abstract class PackageManager {
public static final String FEATURE_APP_ENUMERATION = "android.software.app_enumeration";
/**
- * Feature for {@link android.view.WindowManager.LayoutParams.backgroundBlurRedius} and
- * {@link android.graphics.drawable.BackgroundBlurDrawable}: the device supports cross-layer
- * blurring.
- *
- * @hide
- */
- @SystemApi
- @SdkConstant(SdkConstantType.FEATURE)
- public static final String FEATURE_CROSS_LAYER_BLUR = "android.software.cross_layer_blur";
-
- /**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has
* a Keystore implementation that can only enforce limited use key in hardware with max usage
* count equals to 1.
diff --git a/core/java/android/view/CrossWindowBlurListeners.java b/core/java/android/view/CrossWindowBlurListeners.java
new file mode 100644
index 000000000000..5a1b850133cb
--- /dev/null
+++ b/core/java/android/view/CrossWindowBlurListeners.java
@@ -0,0 +1,137 @@
+/**
+ * Copyright (C) 2021 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 android.view;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.util.function.Consumer;
+
+/**
+ * Class that holds all registered {@link CrossWindowBlurEnabledListener}s. It listens
+ * for updates from the WindowManagerService and updates all registered listeners.
+ * @hide
+ */
+public final class CrossWindowBlurListeners {
+ private static final String TAG = "CrossWindowBlurListeners";
+
+ // property for background blur support in surface flinger
+ private static final String BLUR_PROPERTY = "ro.surface_flinger.supports_background_blur";
+ public static final boolean CROSS_WINDOW_BLUR_SUPPORTED =
+ SystemProperties.get(BLUR_PROPERTY, "default").equals("1");
+
+ private static volatile CrossWindowBlurListeners sInstance;
+ private static final Object sLock = new Object();
+
+ private final BlurEnabledListenerInternal mListenerInternal = new BlurEnabledListenerInternal();
+ private final ArraySet<Consumer<Boolean>> mListeners = new ArraySet();
+ private final Handler mMainHandler = new Handler(Looper.getMainLooper());
+ private boolean mInternalListenerAttached = false;
+ private boolean mCrossWindowBlurEnabled;
+
+ private CrossWindowBlurListeners() {}
+
+ /**
+ * Returns a CrossWindowBlurListeners instance
+ */
+ public static CrossWindowBlurListeners getInstance() {
+ CrossWindowBlurListeners instance = sInstance;
+ if (instance == null) {
+
+ synchronized (sLock) {
+ instance = sInstance;
+ if (instance == null) {
+ instance = new CrossWindowBlurListeners();
+ sInstance = instance;
+ }
+ }
+ }
+ return instance;
+ }
+
+ boolean isCrossWindowBlurEnabled() {
+ synchronized (sLock) {
+ attachInternalListenerIfNeededLocked();
+ return mCrossWindowBlurEnabled;
+ }
+ }
+
+ void addListener(Consumer<Boolean> listener) {
+ if (listener == null) return;
+
+ synchronized (sLock) {
+ attachInternalListenerIfNeededLocked();
+
+ mListeners.add(listener);
+ notifyListenerOnMain(listener, mCrossWindowBlurEnabled);
+ }
+ }
+
+
+ void removeListener(Consumer<Boolean> listener) {
+ if (listener == null) return;
+
+ synchronized (sLock) {
+ mListeners.remove(listener);
+
+ if (mInternalListenerAttached && mListeners.size() == 0) {
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .unregisterCrossWindowBlurEnabledListener(mListenerInternal);
+ mInternalListenerAttached = false;
+ } catch (RemoteException e) {
+ Log.d(TAG, "Could not unregister ICrossWindowBlurEnabledListener");
+ }
+ }
+ }
+ }
+
+ private void attachInternalListenerIfNeededLocked() {
+ if (!mInternalListenerAttached) {
+ try {
+ mCrossWindowBlurEnabled = WindowManagerGlobal.getWindowManagerService()
+ .registerCrossWindowBlurEnabledListener(mListenerInternal);
+ mInternalListenerAttached = true;
+ } catch (RemoteException e) {
+ Log.d(TAG, "Could not register ICrossWindowBlurEnabledListener");
+ }
+ }
+ }
+
+ private void notifyListenerOnMain(Consumer<Boolean> listener, boolean enabled) {
+ mMainHandler.post(() -> {
+ listener.accept(enabled);
+ });
+ }
+
+ private final class BlurEnabledListenerInternal extends ICrossWindowBlurEnabledListener.Stub {
+ @Override
+ public void onCrossWindowBlurEnabledChanged(boolean enabled) {
+ synchronized (sLock) {
+ mCrossWindowBlurEnabled = enabled;
+
+ for (int i = 0; i < mListeners.size(); i++) {
+ notifyListenerOnMain(mListeners.valueAt(i), enabled);
+ }
+ }
+ }
+ }
+}
diff --git a/core/java/android/view/ICrossWindowBlurEnabledListener.aidl b/core/java/android/view/ICrossWindowBlurEnabledListener.aidl
new file mode 100644
index 000000000000..69286e20fe17
--- /dev/null
+++ b/core/java/android/view/ICrossWindowBlurEnabledListener.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 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 android.view;
+
+/**
+ * Listener to be invoked when cross-window blur is enabled or disabled.
+ * {@hide}
+ */
+oneway interface ICrossWindowBlurEnabledListener {
+ /**
+ * Method that will be invoked when cross-window blur is enabled or disabled.
+ * @param enabled True if cross-window blur is enabled.
+ */
+ void onCrossWindowBlurEnabledChanged(boolean enabled);
+}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index afdf798d03ce..54778007c6ff 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -35,6 +35,7 @@ import android.os.ParcelFileDescriptor;
import android.view.DisplayCutout;
import android.view.IApplicationToken;
import android.view.IAppTransitionAnimationSpecsFuture;
+import android.view.ICrossWindowBlurEnabledListener;
import android.view.IDisplayWindowInsetsController;
import android.view.IDisplayWindowListener;
import android.view.IDisplayFoldListener;
@@ -730,7 +731,7 @@ interface IWindowManager
void showGlobalActions();
/**
- * Sets layer tracing flags for SurfaceFlingerTrace.
+ * Sets layer tracing flags for SurfaceFlingerTrace.
*
* @param flags see definition in SurfaceTracing.cpp
*/
@@ -799,4 +800,20 @@ interface IWindowManager
* @param clientToken the window context's token
*/
void unregisterWindowContextListener(IBinder clientToken);
+
+ /**
+ * Registers a listener, which is to be called whenever cross-window blur is enabled/disabled.
+ *
+ * @param listener the listener to be registered
+ * @return true if cross-window blur is currently enabled; false otherwise
+ */
+ boolean registerCrossWindowBlurEnabledListener(ICrossWindowBlurEnabledListener listener);
+
+ /**
+ * Unregisters a listener which was registered with
+ * {@link #registerCrossWindowBlurEnabledListener()}.
+ *
+ * @param listener the listener to be unregistered
+ */
+ void unregisterCrossWindowBlurEnabledListener(ICrossWindowBlurEnabledListener listener);
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 1e5d7e0c9d2d..db7dcc1965aa 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1720,10 +1720,18 @@ public abstract class Window {
* which blurs the whole screen behind the window. Background blur blurs the screen behind
* only within the bounds of the window.
*
+ * Some devices might not support cross-window blur due to GPU limitations. It can also be
+ * disabled at runtime, e.g. during battery saving mode, when multimedia tunneling is used or
+ * when minimal post processing is requested. In such situations, no blur will be computed or
+ * drawn, resulting in a transparent window background. To avoid this, the app might want to
+ * change its theme to one that does not use blurs. To listen for cross-window blur
+ * enabled/disabled events, use {@link WindowManager#addCrossWindowBlurEnabledListener}.
+ *
* @param blurRadius The blur radius to use for window background blur in pixels
*
* @see android.R.styleable#Window_windowBackgroundBlurRadius
* @see WindowManager.LayoutParams#setBlurBehindRadius
+ * @see WindowManager#addCrossWindowBlurEnabledListener
*/
public void setBackgroundBlurRadius(int blurRadius) {}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 2889e11e6f1f..2053826d91a9 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -121,6 +121,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.function.Consumer;
/**
* The interface that apps use to talk to the window manager.
@@ -809,6 +810,64 @@ public interface WindowManager extends ViewManager {
return DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
}
+ /**
+ * Returns whether cross-window blur is currently enabled. This affects both window blur behind
+ * (see {@link LayoutParams#setBlurBehindRadius}) and window background blur (see
+ * {@link Window#setBackgroundBlurRadius}).
+ *
+ * Cross-window blur might not be supported by some devices due to GPU limitations. It can also
+ * be disabled at runtime, e.g. during battery saving mode, when multimedia tunneling is used or
+ * when minimal post processing is requested. In such situations, no blur will be computed or
+ * drawn, so the blur target area will not be blurred. To handle this, the app might want to
+ * change its theme to one that does not use blurs. To listen for cross-window blur
+ * enabled/disabled events, use {@link #addCrossWindowBlurEnabledListener}.
+ *
+ * @see #addCrossWindowBlurEnabledListener
+ * @see LayoutParams#setBlurBehindRadius
+ * @see Window#setBackgroundBlurRadius
+ */
+ default boolean isCrossWindowBlurEnabled() {
+ return false;
+ }
+
+ /**
+ * Adds a listener, which will be called when cross-window blurs are enabled/disabled at
+ * runtime. This affects both window blur behind (see {@link LayoutParams#setBlurBehindRadius})
+ * and window background blur (see {@link Window#setBackgroundBlurRadius}).
+ *
+ * Cross-window blur might not be supported by some devices due to GPU limitations. It can also
+ * be disabled at runtime, e.g. during battery saving mode, when multimedia tunneling is used or
+ * when minimal post processing is requested. In such situations, no blur will be computed or
+ * drawn, so the blur target area will not be blurred. To handle this, the app might want to
+ * change its theme to one that does not use blurs.
+ *
+ * The listener will be called on the main thread.
+ *
+ * If the listener is added successfully, it will be called immediately with the current
+ * cross-window blur enabled state.
+ *
+ *
+ * @param listener the listener to be added. It will be called back with a boolean parameter,
+ * which is true if cross-window blur is enabled and false if it is disabled
+ *
+ * @see #removeCrossWindowBlurEnabledListener
+ * @see #isCrossWindowBlurEnabled
+ * @see LayoutParams#setBlurBehindRadius
+ * @see Window#setBackgroundBlurRadius
+ */
+ default void addCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) {
+ }
+
+ /**
+ * Removes a listener, previously added with {@link #addCrossWindowBlurEnabledListener}
+ *
+ * @param listener the listener to be removed
+ *
+ * @see #addCrossWindowBlurEnabledListener
+ */
+ default void removeCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) {
+ }
+
public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
/**
* X position for this window. With the default gravity it is ignored.
@@ -3537,7 +3596,8 @@ public interface WindowManager extends ViewManager {
/**
* Blurs the screen behind the window. The effect is similar to that of {@link #dimAmount},
- * but instead of dimmed, the content behind the window will be blurred.
+ * but instead of dimmed, the content behind the window will be blurred (or combined with
+ * the dim amount, if such is specified).
*
* 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
@@ -3550,10 +3610,19 @@ public interface WindowManager extends ViewManager {
*
* Requires {@link #FLAG_BLUR_BEHIND} to be set.
*
+ * Cross-window blur might not be supported by some devices due to GPU limitations. It can
+ * also be disabled at runtime, e.g. during battery saving mode, when multimedia tunneling
+ * is used or when minimal post processing is requested. In such situations, no blur will
+ * be computed or drawn, resulting in there being no depth separation between the window
+ * and the content behind it. To avoid this, the app might want to use more
+ * {@link #dimAmount} on its window. To listen for cross-window blur enabled/disabled
+ * events, use {@link #addCrossWindowBlurEnabledListener}.
+ *
* @param blurBehindRadius The blur radius to use for blur behind in pixels
*
* @see #FLAG_BLUR_BEHIND
* @see #getBlurBehindRadius
+ * @see WindowManager#addCrossWindowBlurEnabledListener
* @see Window#setBackgroundBlurRadius
*/
public void setBlurBehindRadius(@IntRange(from = 0) int blurBehindRadius) {
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 23842b3a41ac..b39870738d68 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -40,6 +40,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.IResultReceiver;
import java.util.List;
+import java.util.function.Consumer;
/**
* Provides low-level communication with the system window manager for
@@ -301,4 +302,19 @@ public final class WindowManagerImpl implements WindowManager {
throw e.rethrowFromSystemServer();
}
}
+
+ @Override
+ public boolean isCrossWindowBlurEnabled() {
+ return CrossWindowBlurListeners.getInstance().isCrossWindowBlurEnabled();
+ }
+
+ @Override
+ public void addCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) {
+ CrossWindowBlurListeners.getInstance().addListener(listener);
+ }
+
+ @Override
+ public void removeCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) {
+ CrossWindowBlurListeners.getInstance().removeListener(listener);
+ }
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 9840013935f8..9a91d2028953 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -124,6 +124,7 @@ import com.android.internal.widget.DecorCaptionView;
import com.android.internal.widget.FloatingToolbar;
import java.util.List;
+import java.util.function.Consumer;
/** @hide */
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
@@ -282,14 +283,19 @@ 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 int mOriginalBackgroundBlurRadius = 0;
+ private int mBackgroundBlurRadius = 0;
+ private int mLastBackgroundBlurRadius = 0;
+ private boolean mCrossWindowBlurEnabled;
private final ViewTreeObserver.OnPreDrawListener mBackgroundBlurOnPreDrawListener = () -> {
- updateBackgroundBlur();
+ updateBackgroundBlurCorners();
return true;
};
+ private Consumer<Boolean> mCrossWindowBlurEnabledListener;
DecorView(Context context, int featureId, PhoneWindow window,
WindowManager.LayoutParams params) {
@@ -1272,23 +1278,17 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
if (mBackgroundInsets.equals(mLastBackgroundInsets)
- && mWindow.mBackgroundBlurRadius == mLastBackgroundBlurRadius
+ && mBackgroundBlurRadius == mLastBackgroundBlurRadius
&& mLastOriginalBackgroundDrawable == mOriginalBackgroundDrawable) {
return;
}
Drawable destDrawable = mOriginalBackgroundDrawable;
- if (mWindow.mBackgroundBlurRadius > 0 && getViewRootImpl() != null
- && mWindow.isTranslucent()) {
- if (mBackgroundBlurDrawable == null) {
- mBackgroundBlurDrawable = getViewRootImpl().createBackgroundBlurDrawable();
- }
+ if (mBackgroundBlurRadius > 0) {
destDrawable = new LayerDrawable(new Drawable[] {mBackgroundBlurDrawable,
mOriginalBackgroundDrawable});
- mLastBackgroundBlurRadius = mWindow.mBackgroundBlurRadius;
}
-
if (destDrawable != null && !mBackgroundInsets.equals(Insets.NONE)) {
destDrawable = new InsetDrawable(destDrawable,
mBackgroundInsets.left, mBackgroundInsets.top,
@@ -1309,23 +1309,60 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
super.setBackgroundDrawable(destDrawable);
mLastBackgroundInsets = mBackgroundInsets;
+ mLastBackgroundBlurRadius = mBackgroundBlurRadius;
mLastOriginalBackgroundDrawable = mOriginalBackgroundDrawable;
}
- private void updateBackgroundBlur() {
+ private void updateBackgroundBlurCorners() {
if (mBackgroundBlurDrawable == null) return;
+ float cornerRadius = 0;
// 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);
+ if (mBackgroundBlurRadius != 0 && mOriginalBackgroundDrawable != null) {
+ final Outline outline = new Outline();
+ mOriginalBackgroundDrawable.getOutline(outline);
+ cornerRadius = outline.mMode == Outline.MODE_ROUND_RECT ? outline.getRadius() : 0;
+ }
+ mBackgroundBlurDrawable.setCornerRadius(cornerRadius);
+ }
+
+ private void updateBackgroundBlurRadius() {
+ if (getViewRootImpl() == null) return;
+
+ mBackgroundBlurRadius = mCrossWindowBlurEnabled && mWindow.isTranslucent()
+ ? mOriginalBackgroundBlurRadius : 0;
+ if (mBackgroundBlurDrawable == null && mBackgroundBlurRadius > 0) {
+ mBackgroundBlurDrawable = getViewRootImpl().createBackgroundBlurDrawable();
+ }
+
+ if (mBackgroundBlurDrawable != null) {
+ mBackgroundBlurDrawable.setBlurRadius(mBackgroundBlurRadius);
+ updateBackgroundDrawable();
+ }
+ }
+
+ void setBackgroundBlurRadius(int blurRadius) {
+ mOriginalBackgroundBlurRadius = blurRadius;
+ if (blurRadius > 0) {
+ if (mCrossWindowBlurEnabledListener == null) {
+ mCrossWindowBlurEnabledListener = enabled -> {
+ mCrossWindowBlurEnabled = enabled;
+ updateBackgroundBlurRadius();
+ };
+ getContext().getSystemService(WindowManager.class)
+ .addCrossWindowBlurEnabledListener(mCrossWindowBlurEnabledListener);
+ getViewTreeObserver().addOnPreDrawListener(mBackgroundBlurOnPreDrawListener);
+ } else {
+ updateBackgroundBlurRadius();
}
+ } else if (mCrossWindowBlurEnabledListener != null) {
+ mCrossWindowBlurEnabledListener = null;
+ getContext().getSystemService(WindowManager.class)
+ .removeCrossWindowBlurEnabledListener(mCrossWindowBlurEnabledListener);
+ getViewTreeObserver().removeOnPreDrawListener(mBackgroundBlurOnPreDrawListener);
+ updateBackgroundBlurRadius();
}
- mBackgroundBlurDrawable.setBlurRadius(mWindow.mBackgroundBlurRadius);
}
@Override
@@ -1758,9 +1795,6 @@ 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
@@ -1782,6 +1816,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
// renderer about it.
mBackdropFrameRenderer.onConfigurationChange();
}
+
+ updateBackgroundBlurRadius();
+
mWindow.onViewRootImplSet(getViewRootImpl());
}
@@ -1794,8 +1831,6 @@ 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 eb9c3a98994e..6049486b380c 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -75,6 +75,7 @@ import android.util.Pair;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
+import android.view.CrossWindowBlurListeners;
import android.view.Gravity;
import android.view.IRotationWatcher.Stub;
import android.view.IScrollCaptureCallbacks;
@@ -258,7 +259,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
Drawable mBackgroundDrawable = null;
Drawable mBackgroundFallbackDrawable = null;
- int mBackgroundBlurRadius = 0;
+ private int mBackgroundBlurRadius = 0;
private boolean mLoadElevation = true;
private float mElevation;
@@ -1527,9 +1528,11 @@ 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);
+ if (CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED) {
+ if (mBackgroundBlurRadius != Math.max(blurRadius, 0)) {
+ mBackgroundBlurRadius = Math.max(blurRadius, 0);
+ mDecor.setBackgroundBlurRadius(mBackgroundBlurRadius);
+ }
}
}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index b40ffb0136f2..58df2be2b944 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -95,9 +95,6 @@ public class SystemConfig {
// property for runtime configuration differentiation in vendor
private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku";
- // property for background blur support in surface flinger
- private static final String BLUR_PROPERTY = "ro.surface_flinger.supports_background_blur";
-
// Group-ids that are given to all packages as read from etc/permissions/*.xml.
int[] mGlobalGids = EmptyArray.INT;
@@ -1249,10 +1246,6 @@ public class SystemConfig {
addFeature(PackageManager.FEATURE_IPSEC_TUNNELS, 0);
}
- if (SystemProperties.get(BLUR_PROPERTY, "default").equals("1")) {
- addFeature(PackageManager.FEATURE_CROSS_LAYER_BLUR, 0);
- }
-
if (SensorPrivacyManager.USE_MICROPHONE_TOGGLE) {
addFeature(PackageManager.FEATURE_MICROPHONE_TOGGLE, 0);
}
diff --git a/services/core/java/com/android/server/wm/BlurController.java b/services/core/java/com/android/server/wm/BlurController.java
new file mode 100644
index 000000000000..13295e8aca02
--- /dev/null
+++ b/services/core/java/com/android/server/wm/BlurController.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 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.server.wm;
+
+import static android.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED;
+
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.view.ICrossWindowBlurEnabledListener;
+
+final class BlurController {
+
+ private final RemoteCallbackList<ICrossWindowBlurEnabledListener>
+ mBlurEnabledListeners = new RemoteCallbackList<>();
+ private final Object mLock = new Object();
+ boolean mBlurEnabled;
+
+ BlurController() {
+ mBlurEnabled = CROSS_WINDOW_BLUR_SUPPORTED;
+ }
+
+ boolean registerCrossWindowBlurEnabledListener(ICrossWindowBlurEnabledListener listener) {
+ if (listener == null) return false;
+ mBlurEnabledListeners.register(listener);
+ synchronized (mLock) {
+ return mBlurEnabled;
+ }
+ }
+
+ void unregisterCrossWindowBlurEnabledListener(ICrossWindowBlurEnabledListener listener) {
+ if (listener == null) return;
+ mBlurEnabledListeners.unregister(listener);
+ }
+
+ private void updateBlurEnabled() {
+ // TODO: add other factors disabling blurs
+ final boolean newEnabled = CROSS_WINDOW_BLUR_SUPPORTED;
+ synchronized (mLock) {
+ if (mBlurEnabled == newEnabled) {
+ return;
+ }
+ mBlurEnabled = newEnabled;
+ notifyBlurEnabledChanged(newEnabled);
+ }
+ }
+
+ private void notifyBlurEnabledChanged(boolean enabled) {
+ int i = mBlurEnabledListeners.beginBroadcast();
+ while (i > 0) {
+ i--;
+ ICrossWindowBlurEnabledListener listener =
+ mBlurEnabledListeners.getBroadcastItem(i);
+ try {
+ listener.onCrossWindowBlurEnabledChanged(enabled);
+ } catch (RemoteException e) {
+ }
+ }
+ mBlurEnabledListeners.finishBroadcast();
+ }
+
+
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index cca85b217a74..aec50f08e227 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -224,6 +224,7 @@ import android.view.Display;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IAppTransitionAnimationSpecsFuture;
+import android.view.ICrossWindowBlurEnabledListener;
import android.view.IDisplayFoldListener;
import android.view.IDisplayWindowInsetsController;
import android.view.IDisplayWindowListener;
@@ -756,6 +757,8 @@ public class WindowManagerService extends IWindowManager.Stub
final TaskSnapshotController mTaskSnapshotController;
+ final BlurController mBlurController = new BlurController();
+
boolean mIsTouchDevice;
boolean mIsFakeTouchDevice;
@@ -5689,6 +5692,18 @@ public class WindowManagerService extends IWindowManager.Stub
return mWindowTracing.isEnabled();
}
+ @Override
+ public boolean registerCrossWindowBlurEnabledListener(
+ ICrossWindowBlurEnabledListener listener) {
+ return mBlurController.registerCrossWindowBlurEnabledListener(listener);
+ }
+
+ @Override
+ public void unregisterCrossWindowBlurEnabledListener(
+ ICrossWindowBlurEnabledListener listener) {
+ mBlurController.unregisterCrossWindowBlurEnabledListener(listener);
+ }
+
// -------------------------------------------------------------
// Internals
// -------------------------------------------------------------
@@ -6428,6 +6443,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
});
pw.print(" mInTouchMode="); pw.println(mInTouchMode);
+ pw.print(" mBlurEnabled="); pw.println(mBlurController.mBlurEnabled);
pw.print(" mLastDisplayFreezeDuration=");
TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
if ( mLastFinishedFreezeSource != null) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ae7efcd34019..e9ce90bafafd 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5265,7 +5265,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (!mAnimatingExit && mAppDied) {
mIsDimming = true;
getDimmer().dimAbove(getSyncTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
- } else if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || (mAttrs.flags & FLAG_BLUR_BEHIND) != 0)
+ } else if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || shouldDrawBlurBehind())
&& isVisibleNow() && !mHidden) {
// Only show the Dimmer when the following is satisfied:
// 1. The window has the flag FLAG_DIM_BEHIND or blur behind is requested
@@ -5274,12 +5274,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// 4. The WS is not hidden.
mIsDimming = true;
final float dimAmount = (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? mAttrs.dimAmount : 0;
- final int blurRadius =
- (mAttrs.flags & FLAG_BLUR_BEHIND) != 0 ? mAttrs.getBlurBehindRadius() : 0;
+ final int blurRadius = shouldDrawBlurBehind() ? mAttrs.getBlurBehindRadius() : 0;
getDimmer().dimBelow(getSyncTransaction(), this, mAttrs.dimAmount, blurRadius);
}
}
+ private boolean shouldDrawBlurBehind() {
+ return (mAttrs.flags & FLAG_BLUR_BEHIND) != 0 && mWmService.mBlurController.mBlurEnabled;
+ }
+
/**
* Notifies SF about the priority of the window, if it changed. SF then uses this information
* to decide which window's desired rendering rate should have a priority when deciding about