diff options
| author | 2020-01-25 00:44:04 +0000 | |
|---|---|---|
| committer | 2020-01-25 00:44:04 +0000 | |
| commit | f85c92f4f6628d7c074f6b81b500f39c1c845a42 (patch) | |
| tree | cc26fedd9f84ea9cb836c45b1fe2857f91e23e3b | |
| parent | 8127bfcc4355156e60f041cd2ddc913085fd6e51 (diff) | |
| parent | f6ef1c7071f3ca7250cc6d9078155b9d6b1d9fa8 (diff) | |
Merge "Switch to compositor shadows for PiP and Freeform windows (disabled by default)"
9 files changed, 156 insertions, 10 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 21d99fcf8231..c16e77ee117f 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9362,6 +9362,16 @@ public final class Settings { public static final String DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM = "enable_sizecompat_freeform"; + /** + * If true, shadows drawn around the window will be rendered by the system compositor. If + * false, shadows will be drawn by the client by setting an elevation on the root view and + * the contents will be inset by the surface insets. + * (0 = false, 1 = true) + * @hide + */ + public static final String DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR = + "render_shadows_in_compositor"; + /** * Whether user has enabled development settings. */ diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 8412b846b2a6..adb403681b36 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -95,8 +95,6 @@ import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowCallbacks; import android.view.WindowInsets; -import android.view.WindowInsets.Side; -import android.view.WindowInsets.Type; import android.view.WindowInsetsController; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; @@ -131,9 +129,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private static final boolean SWEEP_OPEN_MENU = false; // The height of a window which has focus in DIP. - private final static int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20; + public static final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20; // The height of a window which has not in DIP. - private final static int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5; + public static final int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5; private static final int SCRIM_LIGHT = 0xe6ffffff; // 90% white @@ -1629,7 +1627,9 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind int opacity = PixelFormat.OPAQUE; final WindowConfiguration winConfig = getResources().getConfiguration().windowConfiguration; - if (winConfig.hasWindowShadow()) { + // If we draw shadows in the compositor we don't need to force the surface to be + // translucent. + if (winConfig.hasWindowShadow() && !mWindow.mRenderShadowsInCompositor) { // If the window has a shadow, it must be translucent. opacity = PixelFormat.TRANSLUCENT; } else{ @@ -2414,6 +2414,10 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind } private void updateElevation() { + // If rendering shadows in the compositor, don't set an elevation on the view + if (mWindow.mRenderShadowsInCompositor) { + return; + } float elevation = 0; final boolean wasAdjustedForStack = mElevationAdjustedForStack; // Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null) diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 95558c31e671..f13a638f7844 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -17,6 +17,7 @@ package com.android.internal.policy; import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES; +import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR; import static android.view.View.SYSTEM_UI_LAYOUT_FLAGS; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; @@ -134,6 +135,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private final static String TAG = "PhoneWindow"; + /* If true, shadows drawn around the window will be rendered by the system compositor. If + * false, shadows will be drawn by the client by setting an elevation on the root view and + * the contents will be inset by the shadow radius. */ + public final boolean mRenderShadowsInCompositor; + private static final boolean DEBUG = false; private final static int DEFAULT_BACKGROUND_FADE_DURATION_MS = 300; @@ -327,6 +333,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { public PhoneWindow(Context context) { super(context); mLayoutInflater = LayoutInflater.from(context); + mRenderShadowsInCompositor = Settings.Global.getInt(context.getContentResolver(), + DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, 0) != 0; } /** diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index fa2e36538dc3..5721055fa506 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -224,6 +224,7 @@ public class SettingsBackupTest { Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, Settings.Global.DEVELOPMENT_FORCE_RTL, Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM, + Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, Settings.Global.DEVICE_DEMO_MODE, Settings.Global.DEVICE_IDLE_CONSTANTS, Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS, diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 3ff824374aac..10f59a423805 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -43,7 +43,7 @@ <item name="android:windowIsTranslucent">true</item> <item name="android:windowNoTitle">true</item> <item name="android:windowContentOverlay">@null</item> - <item name="android:windowBackground">@null</item> + <item name="android:windowBackground">@android:color/transparent</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:statusBarColor">@*android:color/transparent</item> <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item> diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 6556f6bb6bea..663423f8728b 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -3990,6 +3990,10 @@ class ActivityStack extends Task implements BoundsAnimationTarget { * Used to make room for shadows in the pinned windowing mode. */ int getStackOutset() { + // If we are drawing shadows on the task then don't outset the stack. + if (mWmService.mRenderShadowsInCompositor) { + return 0; + } DisplayContent displayContent = getDisplayContent(); if (inPinnedWindowingMode() && displayContent != null) { final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics(); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 825f93cde52b..36bee87a4ed3 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3116,6 +3116,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } + onWindowFocusChanged(oldFocus, newFocus); + int focusChanged = getDisplayPolicy().focusChangedLw(oldFocus, newFocus); if (imWindowChanged && oldFocus != mInputMethodWindow) { @@ -3158,6 +3160,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return true; } + private static void onWindowFocusChanged(WindowState oldFocus, WindowState newFocus) { + final Task focusedTask = newFocus != null ? newFocus.getTask() : null; + final Task unfocusedTask = oldFocus != null ? oldFocus.getTask() : null; + if (focusedTask == unfocusedTask) { + return; + } + if (focusedTask != null) { + focusedTask.onWindowFocusChanged(true /* hasFocus */); + } + if (unfocusedTask != null) { + unfocusedTask.onWindowFocusChanged(false /* hasFocus */); + } + } + /** * Set the new focused app to this display. * diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 5ecbec4c1180..19461c52bd9e 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -22,6 +22,7 @@ import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM; import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP; import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; @@ -58,6 +59,8 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.SurfaceControl.METADATA_TASK_ID; +import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP; +import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP; import static com.android.server.am.TaskRecordProto.ACTIVITIES; import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE; import static com.android.server.am.TaskRecordProto.FULLSCREEN; @@ -98,6 +101,7 @@ import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.WindowManagerService.dipToPixel; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM; import static java.lang.Integer.MAX_VALUE; @@ -209,6 +213,8 @@ class Task extends WindowContainer<WindowContainer> { static final int PERSIST_TASK_VERSION = 1; static final int INVALID_MIN_SIZE = -1; + private float mShadowRadius = 0; + private final Rect mLastSurfaceCrop = new Rect(); /** * The modes to control how the stack is moved to the front when calling {@link Task#reparent}. @@ -1868,6 +1874,7 @@ class Task extends WindowContainer<WindowContainer> { super.onConfigurationChanged(newParentConfig); if (wasInMultiWindowMode != inMultiWindowMode()) { mStackSupervisor.scheduleUpdateMultiWindowMode(this); + updateShadowsRadius(isFocused(), getPendingTransaction()); } // If the configuration supports persistent bounds (eg. Freeform), keep track of the @@ -2526,18 +2533,36 @@ class Task extends WindowContainer<WindowContainer> { ? getStack().getDisplayContent() : null; if (displayContent != null) { rotation = displayContent.getDisplayInfo().rotation; - } else if (bounds == null) { - return super.setBounds(bounds); } final int boundsChange = super.setBounds(bounds); - mRotation = rotation; - updateSurfacePosition(); return boundsChange; } + private void updateSurfaceCrop() { + // Only update the crop if we are drawing shadows on the task. + if (mSurfaceControl == null || !mWmService.mRenderShadowsInCompositor) { + return; + } + + if (inSplitScreenWindowingMode()) { + // inherit crop from parent + mTmpRect.setEmpty(); + } else { + getBounds(mTmpRect); + } + + mTmpRect.offsetTo(0, 0); + if (mLastSurfaceCrop.equals(mTmpRect)) { + return; + } + + getPendingTransaction().setWindowCrop(mSurfaceControl, mTmpRect); + mLastSurfaceCrop.set(mTmpRect); + } + @Override public boolean onDescendantOrientationChanged(IBinder freezeDisplayToken, ConfigurationContainer requestingContainer) { @@ -3126,6 +3151,9 @@ class Task extends WindowContainer<WindowContainer> { } else { mTmpDimBoundsRect.offsetTo(0, 0); } + + updateSurfaceCrop(); + if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) { scheduleAnimation(); } @@ -3925,4 +3953,58 @@ class Task extends WindowContainer<WindowContainer> { setTaskOrganizer(org); } } + + /** + * @return true if the task is currently focused. + */ + private boolean isFocused() { + if (mDisplayContent == null || mDisplayContent.mCurrentFocus == null) { + return false; + } + return mDisplayContent.mCurrentFocus.getTask() == this; + } + + /** + * @return the desired shadow radius in pixels for the current task. + */ + private float getShadowRadius(boolean taskIsFocused) { + if (mDisplayContent == null) { + return 0; + } + + if (inPinnedWindowingMode()) { + return dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP, + mDisplayContent.getDisplayMetrics()); + } + if (inFreeformWindowingMode()) { + final int elevation = taskIsFocused + ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP; + return dipToPixel(elevation, mDisplayContent.getDisplayMetrics()); + } + + // For all other windowing modes, do not draw a shadow. + return 0; + } + + /** + * Update the length of the shadow if needed based on windowing mode and task focus state. + */ + private void updateShadowsRadius(boolean taskIsFocused, + SurfaceControl.Transaction pendingTransaction) { + if (!mWmService.mRenderShadowsInCompositor) return; + + final float newShadowRadius = getShadowRadius(taskIsFocused); + if (mShadowRadius != newShadowRadius) { + mShadowRadius = newShadowRadius; + pendingTransaction.setShadowRadius(getSurfaceControl(), mShadowRadius); + } + } + + /** + * Called on the task of a window which gained or lost focus. + * @param hasFocus + */ + void onWindowFocusChanged(boolean hasFocus) { + updateShadowsRadius(hasFocus, getPendingTransaction()); + } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 27de95a84ab6..1360711ec97e 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -39,6 +39,7 @@ import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDO import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM; import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS; import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES; +import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.DOCKED_INVALID; @@ -421,6 +422,11 @@ public class WindowManagerService extends IWindowManager.Stub int mVr2dDisplayId = INVALID_DISPLAY; boolean mVrModeEnabled = false; + /* If true, shadows drawn around the window will be rendered by the system compositor. If + * false, shadows will be drawn by the client by setting an elevation on the root view and + * the contents will be inset by the shadow radius. */ + boolean mRenderShadowsInCompositor = false; + /** * Tracks a map of input tokens to info that is used to decide whether to intercept * a key event. @@ -722,6 +728,8 @@ public class WindowManagerService extends IWindowManager.Stub DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES); private final Uri mSizeCompatFreeformUri = Settings.Global.getUriFor( DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM); + private final Uri mRenderShadowsInCompositorUri = Settings.Global.getUriFor( + DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR); public SettingsObserver() { super(new Handler()); @@ -744,6 +752,8 @@ public class WindowManagerService extends IWindowManager.Stub resolver.registerContentObserver(mForceResizableUri, false, this, UserHandle.USER_ALL); resolver.registerContentObserver(mSizeCompatFreeformUri, false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(mRenderShadowsInCompositorUri, false, this, + UserHandle.USER_ALL); } @Override @@ -782,6 +792,11 @@ public class WindowManagerService extends IWindowManager.Stub return; } + if (mRenderShadowsInCompositorUri.equals(uri)) { + setShadowRenderer(); + return; + } + @UpdateAnimationScaleMode final int mode; if (mWindowAnimationScaleUri.equals(uri)) { @@ -863,6 +878,11 @@ public class WindowManagerService extends IWindowManager.Stub } } + private void setShadowRenderer() { + mRenderShadowsInCompositor = Settings.Global.getInt(mContext.getContentResolver(), + DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, 0) != 0; + } + PowerManager mPowerManager; PowerManagerInternal mPowerManagerInternal; @@ -1249,6 +1269,7 @@ public class WindowManagerService extends IWindowManager.Stub float[] spotColor = {0.f, 0.f, 0.f, spotShadowAlpha}; SurfaceControl.setGlobalShadowSettings(ambientColor, spotColor, lightY, lightZ, lightRadius); + setShadowRenderer(); } /** |