summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vishnu Nair <vishnun@google.com> 2020-01-25 00:44:04 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-01-25 00:44:04 +0000
commitf85c92f4f6628d7c074f6b81b500f39c1c845a42 (patch)
treecc26fedd9f84ea9cb836c45b1fe2857f91e23e3b
parent8127bfcc4355156e60f041cd2ddc913085fd6e51 (diff)
parentf6ef1c7071f3ca7250cc6d9078155b9d6b1d9fa8 (diff)
Merge "Switch to compositor shadows for PiP and Freeform windows (disabled by default)"
-rw-r--r--core/java/android/provider/Settings.java10
-rw-r--r--core/java/com/android/internal/policy/DecorView.java14
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java8
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--packages/SystemUI/res/values/styles.xml2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java16
-rw-r--r--services/core/java/com/android/server/wm/Task.java90
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java21
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();
}
/**