Merge "WindowlessWindowManager floating window support"
diff --git a/core/java/android/view/WindowlessWindowLayout.java b/core/java/android/view/WindowlessWindowLayout.java
index 8ef4d78..6fb01f2 100644
--- a/core/java/android/view/WindowlessWindowLayout.java
+++ b/core/java/android/view/WindowlessWindowLayout.java
@@ -16,13 +16,19 @@
package android.view;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
import android.app.WindowConfiguration.WindowingMode;
import android.graphics.Rect;
import android.view.WindowInsets.Type.InsetsType;
import android.window.ClientWindowFrames;
+// TODO(b/262891212) use the real WindowLayout and remove WindowlessWindowLayout
+
/**
* Computes window frames for the windowless window.
+ *
* @hide
*/
public class WindowlessWindowLayout extends WindowLayout {
@@ -32,9 +38,32 @@
Rect displayCutoutSafe, Rect windowBounds, @WindowingMode int windowingMode,
int requestedWidth, int requestedHeight, @InsetsType int requestedVisibleTypes,
float compatScale, ClientWindowFrames frames) {
- frames.frame.set(0, 0, attrs.width, attrs.height);
+ if (frames.attachedFrame == null) {
+ frames.frame.set(0, 0, attrs.width, attrs.height);
+ frames.parentFrame.set(frames.frame);
+ frames.displayFrame.set(frames.frame);
+ return;
+ }
+
+ final int height = calculateLength(attrs.height, requestedHeight,
+ frames.attachedFrame.height());
+ final int width = calculateLength(attrs.width, requestedWidth,
+ frames.attachedFrame.width());
+ Gravity.apply(attrs.gravity, width, height, frames.attachedFrame,
+ (int) (attrs.x + attrs.horizontalMargin),
+ (int) (attrs.y + attrs.verticalMargin),
+ frames.frame);
frames.displayFrame.set(frames.frame);
- frames.parentFrame.set(frames.frame);
+ frames.parentFrame.set(frames.attachedFrame);
+ }
+
+ private static int calculateLength(int attrLength, int requestedLength, int parentLength) {
+ if (attrLength == MATCH_PARENT) {
+ return parentLength;
+ }
+ if (attrLength == WRAP_CONTENT) {
+ return requestedLength;
+ }
+ return attrLength;
}
}
-
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index ecb5557..021193e 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -17,6 +17,7 @@
package android.view;
import android.annotation.Nullable;
+import android.app.WindowConfiguration;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -53,13 +54,21 @@
IBinder mInputChannelToken;
Region mInputRegion;
IWindow mClient;
- State(SurfaceControl sc, WindowManager.LayoutParams p, int displayId,
- IBinder inputChannelToken, IWindow client) {
+ SurfaceControl mLeash;
+ Rect mFrame;
+ Rect mAttachedFrame;
+
+ State(SurfaceControl sc, WindowManager.LayoutParams p,
+ int displayId, IBinder inputChannelToken, IWindow client, SurfaceControl leash,
+ Rect frame, Rect attachedFrame) {
mSurfaceControl = sc;
mParams.copyFrom(p);
mDisplayId = displayId;
mInputChannelToken = inputChannelToken;
mClient = client;
+ mLeash = leash;
+ mFrame = frame;
+ mAttachedFrame = attachedFrame;
}
};
@@ -85,6 +94,7 @@
private InsetsState mInsetsState;
private final ClientWindowFrames mTmpFrames = new ClientWindowFrames();
private final MergedConfiguration mTmpConfig = new MergedConfiguration();
+ private final WindowlessWindowLayout mLayout = new WindowlessWindowLayout();
public WindowlessWindowManager(Configuration c, SurfaceControl rootSurface,
IBinder hostInputToken) {
@@ -137,8 +147,15 @@
}
}
- protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
- b.setParent(mRootSurface);
+ protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
+ // If this is the first window, the state map is empty and the parent surface is the
+ // root. Otherwise, the parent surface is in the state map.
+ synchronized (this) {
+ if (mStateForWindow.isEmpty()) {
+ return mRootSurface;
+ }
+ return mStateForWindow.get(attrs.token).mLeash;
+ }
}
/**
@@ -150,13 +167,20 @@
InputChannel outInputChannel, InsetsState outInsetsState,
InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
float[] outSizeCompatScale) {
- final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
+ final SurfaceControl leash = new SurfaceControl.Builder(mSurfaceSession)
+ .setName(attrs.getTitle().toString() + "Leash")
+ .setCallsite("WindowlessWindowManager.addToDisplay")
+ .setParent(getParentSurface(window, attrs))
+ .build();
+
+ final SurfaceControl sc = new SurfaceControl.Builder(mSurfaceSession)
.setFormat(attrs.format)
.setBLASTLayer()
.setName(attrs.getTitle().toString())
- .setCallsite("WindowlessWindowManager.addToDisplay");
- attachToParentSurface(window, b);
- final SurfaceControl sc = b.build();
+ .setCallsite("WindowlessWindowManager.addToDisplay")
+ .setHidden(false)
+ .setParent(leash)
+ .build();
if (((attrs.inputFeatures &
WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0)) {
@@ -178,11 +202,22 @@
}
final State state = new State(sc, attrs, displayId,
- outInputChannel != null ? outInputChannel.getToken() : null, window);
+ outInputChannel != null ? outInputChannel.getToken() : null, window,
+ leash, /* frame= */ new Rect(), /* attachedFrame= */ null);
+ Rect parentFrame = null;
synchronized (this) {
+ State parentState = mStateForWindow.get(attrs.token);
+ if (parentState != null) {
+ parentFrame = parentState.mFrame;
+ }
mStateForWindow.put(window.asBinder(), state);
}
- outAttachedFrame.set(0, 0, -1, -1);
+ state.mAttachedFrame = parentFrame;
+ if (parentFrame == null) {
+ outAttachedFrame.set(0, 0, -1, -1);
+ } else {
+ outAttachedFrame.set(parentFrame);
+ }
outSizeCompatScale[0] = 1f;
final int res = WindowManagerGlobal.ADD_OKAY | WindowManagerGlobal.ADD_FLAG_APP_VISIBLE |
@@ -227,6 +262,7 @@
"Invalid window token (never added or removed already)");
}
removeSurface(state.mSurfaceControl);
+ removeSurface(state.mLeash);
}
/** Separate from {@link #remove} so that subclasses can put removal on a sync transaction. */
@@ -301,6 +337,7 @@
"Invalid window token (never added or removed already)");
}
SurfaceControl sc = state.mSurfaceControl;
+ SurfaceControl leash = state.mLeash;
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
int attrChanges = 0;
@@ -309,21 +346,37 @@
}
WindowManager.LayoutParams attrs = state.mParams;
+ ClientWindowFrames frames = new ClientWindowFrames();
+ frames.attachedFrame = state.mAttachedFrame;
+
+ mLayout.computeFrames(attrs, null, null, null, WindowConfiguration.WINDOWING_MODE_UNDEFINED,
+ requestedWidth, requestedHeight, 0, 0,
+ frames);
+
+ state.mFrame.set(frames.frame);
+ if (outFrames != null) {
+ outFrames.frame.set(frames.frame);
+ outFrames.parentFrame.set(frames.parentFrame);
+ outFrames.displayFrame.set(frames.displayFrame);
+ }
+
+ t.setPosition(leash, frames.frame.left, frames.frame.top);
+ t.setWindowCrop(leash, frames.frame.width(), frames.frame.height());
+
if (viewFlags == View.VISIBLE) {
- t.setOpaque(sc, isOpaque(attrs)).show(sc).apply();
+ // TODO(b/262892794) ViewRootImpl modifies the app's rendering SurfaceControl
+ // opaqueness. We shouldn't need to modify opaqueness for this SurfaceControl here or
+ // in the real WindowManager.
+ t.setOpaque(sc, isOpaque(attrs)).show(leash).apply();
if (outSurfaceControl != null) {
outSurfaceControl.copyFrom(sc, "WindowlessWindowManager.relayout");
}
} else {
- t.hide(sc).apply();
+ t.hide(leash).apply();
if (outSurfaceControl != null) {
outSurfaceControl.release();
}
}
- if (outFrames != null) {
- outFrames.frame.set(0, 0, attrs.width, attrs.height);
- outFrames.displayFrame.set(outFrames.frame);
- }
if (outMergedConfiguration != null) {
outMergedConfiguration.setConfiguration(mConfiguration, mConfiguration);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 94aeb2b..5e46023 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -306,7 +306,9 @@
}
}
- protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
+ @Override
+ protected SurfaceControl getParentSurface(IWindow window,
+ WindowManager.LayoutParams attrs) {
SurfaceControl leash = new SurfaceControl.Builder(new SurfaceSession())
.setContainerLayer()
.setName("SystemWindowLeash")
@@ -316,7 +318,7 @@
synchronized (this) {
mLeashForWindow.put(window.asBinder(), leash);
}
- b.setParent(leash);
+ return leash;
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index a9d3c9f..fcbf9e0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -92,7 +92,7 @@
}
@Override
- protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
+ protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
// Can't set position for the ViewRootImpl SC directly. Create a leash to manipulate later.
final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
.setContainerLayer()
@@ -101,7 +101,7 @@
.setParent(mHostLeash)
.setCallsite("SplitDecorManager#attachToParentSurface");
mIconLeash = builder.build();
- b.setParent(mIconLeash);
+ return mIconLeash;
}
/** Inflates split decor surface on the root surface. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 5397552..6b5ddcb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -93,7 +93,7 @@
}
@Override
- protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
+ protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
// Can't set position for the ViewRootImpl SC directly. Create a leash to manipulate later.
final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
.setContainerLayer()
@@ -103,7 +103,7 @@
mParentContainerCallbacks.attachToParentSurface(builder);
mLeash = builder.build();
mParentContainerCallbacks.onLeashReady(mLeash);
- b.setParent(mLeash);
+ return mLeash;
}
/** Inflates {@link DividerView} on to the root surface. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
index face243..2cc9f45 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
@@ -155,7 +155,7 @@
}
@Override
- protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
+ protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
String className = getClass().getSimpleName();
final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
.setContainerLayer()
@@ -164,9 +164,8 @@
.setCallsite(className + "#attachToParentSurface");
attachToParentSurface(builder);
mLeash = builder.build();
- b.setParent(mLeash);
-
initSurface(mLeash);
+ return mLeash;
}
/** Inits the z-order of the surface. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java
index b310ee2..8ebcd81 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java
@@ -104,7 +104,7 @@
}
@Override
- protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
+ protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
.setColorLayer()
.setBufferSize(mDisplayBounds.width(), mDisplayBounds.height())
@@ -113,7 +113,7 @@
.setName(TAG)
.setCallsite("BackgroundWindowManager#attachToParentSurface");
mLeash = builder.build();
- b.setParent(mLeash);
+ return mLeash;
}
/** Inflates background view on to the root surface. */