diff options
Diffstat (limited to 'core/java/android')
| -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 |
7 files changed, 278 insertions, 13 deletions
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); + } } |
