diff options
| -rw-r--r-- | core/api/current.txt | 3 | ||||
| -rw-r--r-- | core/api/system-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageManager.java | 11 | ||||
| -rw-r--r-- | core/java/android/view/CrossWindowBlurListeners.java | 137 | ||||
| -rw-r--r-- | core/java/android/view/ICrossWindowBlurEnabledListener.aidl | 29 | ||||
| -rw-r--r-- | core/java/android/view/IWindowManager.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/view/Window.java | 8 | ||||
| -rw-r--r-- | core/java/android/view/WindowManager.java | 71 | ||||
| -rw-r--r-- | core/java/android/view/WindowManagerImpl.java | 16 | ||||
| -rw-r--r-- | core/java/com/android/internal/policy/DecorView.java | 81 | ||||
| -rw-r--r-- | core/java/com/android/internal/policy/PhoneWindow.java | 11 | ||||
| -rw-r--r-- | core/java/com/android/server/SystemConfig.java | 7 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/BlurController.java | 76 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 16 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowState.java | 9 |
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 |