summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Andrii Kulian <akulian@google.com> 2017-08-07 22:31:03 +0000
committer android-build-merger <android-build-merger@google.com> 2017-08-07 22:31:03 +0000
commit7a0cf480229e65375843c96d576b0c076293cc46 (patch)
tree2d061243fc9ced6cf457316d4ab387678af4b35f
parentff9914ee5637bf6c152be6d3f78b2dfee7ec60ec (diff)
parent66994114e7a42fc6394b236ea46e574d3fc82e74 (diff)
Merge "Add black frame behind app window" into oc-dr1-dev am: cbdaf04101
am: 66994114e7 Change-Id: I58305f008170c734e1c7291ff53f16e87776fe08
-rw-r--r--core/java/android/view/SurfaceControl.java3
-rw-r--r--services/core/java/com/android/server/wm/RemoteSurfaceTrace.java5
-rw-r--r--services/core/java/com/android/server/wm/SurfaceControlWithBackground.java306
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java16
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java33
6 files changed, 351 insertions, 21 deletions
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 44c88e146879..1a2968f6345f 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -65,7 +65,8 @@ public class SurfaceControl {
private static native void nativeSetSize(long nativeObject, int w, int h);
private static native void nativeSetTransparentRegionHint(long nativeObject, Region region);
private static native void nativeSetAlpha(long nativeObject, float alpha);
- private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx, float dsdy, float dtdy);
+ private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx,
+ float dtdy, float dsdy);
private static native void nativeSetFlags(long nativeObject, int flags, int mask);
private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
private static native void nativeSetFinalCrop(long nativeObject, int l, int t, int r, int b);
diff --git a/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java b/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java
index 0508fdff531a..a12c2c40152d 100644
--- a/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java
+++ b/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java
@@ -32,7 +32,7 @@ import java.io.DataOutputStream;
// the surface control.
//
// See cts/hostsidetests/../../SurfaceTraceReceiver.java for parsing side.
-class RemoteSurfaceTrace extends SurfaceControl {
+class RemoteSurfaceTrace extends SurfaceControlWithBackground {
static final String TAG = "RemoteSurfaceTrace";
final FileDescriptor mWriteFd;
@@ -41,7 +41,8 @@ class RemoteSurfaceTrace extends SurfaceControl {
final WindowManagerService mService;
final WindowState mWindow;
- RemoteSurfaceTrace(FileDescriptor fd, SurfaceControl wrapped, WindowState window) {
+ RemoteSurfaceTrace(FileDescriptor fd, SurfaceControlWithBackground wrapped,
+ WindowState window) {
super(wrapped);
mWriteFd = fd;
diff --git a/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
new file mode 100644
index 000000000000..f5ef2e66f0a6
--- /dev/null
+++ b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2017 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 android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+/**
+ * SurfaceControl extension that has background sized to match its container.
+ */
+class SurfaceControlWithBackground extends SurfaceControl {
+ // SurfaceControl that holds the background behind opaque letterboxed app windows.
+ private SurfaceControl mBackgroundControl;
+
+ // Flags that define whether the background should be shown.
+ private boolean mOpaque;
+ private boolean mVisible;
+
+ // Way to communicate with corresponding window.
+ private WindowSurfaceController mWindowSurfaceController;
+
+ // Rect to hold task bounds when computing metrics for background.
+ private Rect mTmpContainerRect = new Rect();
+
+ // Last metrics applied to the main SurfaceControl.
+ private float mLastWidth, mLastHeight;
+ private float mLastDsDx = 1, mLastDsDy = 1;
+ private float mLastX, mLastY;
+
+ public SurfaceControlWithBackground(SurfaceControlWithBackground other) {
+ super(other);
+ mBackgroundControl = other.mBackgroundControl;
+ mOpaque = other.mOpaque;
+ mVisible = other.mVisible;
+ mWindowSurfaceController = other.mWindowSurfaceController;
+ }
+
+ public SurfaceControlWithBackground(SurfaceSession s, String name, int w, int h, int format,
+ int flags, int windowType, int ownerUid,
+ WindowSurfaceController windowSurfaceController) throws OutOfResourcesException {
+ super(s, name, w, h, format, flags, windowType, ownerUid);
+
+ // We should only show background when the window is letterboxed in a task.
+ if (!windowSurfaceController.mAnimator.mWin.isLetterboxedAppWindow()) {
+ return;
+ }
+ mWindowSurfaceController = windowSurfaceController;
+ mLastWidth = w;
+ mLastHeight = h;
+ mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ mBackgroundControl = new SurfaceControl(s, "Background for - " + name,
+ mTmpContainerRect.width(), mTmpContainerRect.height(), PixelFormat.OPAQUE,
+ flags | SurfaceControl.FX_SURFACE_DIM);
+ }
+
+ @Override
+ public void setAlpha(float alpha) {
+ super.setAlpha(alpha);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.setAlpha(alpha);
+ }
+
+ @Override
+ public void setLayer(int zorder) {
+ super.setLayer(zorder);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ // TODO: Use setRelativeLayer(Integer.MIN_VALUE) when it's fixed.
+ mBackgroundControl.setLayer(zorder - 1);
+ }
+
+ @Override
+ public void setPosition(float x, float y) {
+ super.setPosition(x, y);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mLastX = x;
+ mLastY = y;
+ updateBgPosition();
+ }
+
+ private void updateBgPosition() {
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame;
+ final float offsetX = (mTmpContainerRect.left - winFrame.left) * mLastDsDx;
+ final float offsetY = (mTmpContainerRect.top - winFrame.top) * mLastDsDy;
+ mBackgroundControl.setPosition(mLastX + offsetX, mLastY + offsetY);
+ }
+
+ @Override
+ public void setSize(int w, int h) {
+ super.setSize(w, h);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mLastWidth = w;
+ mLastHeight = h;
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ mBackgroundControl.setSize(mTmpContainerRect.width(), mTmpContainerRect.height());
+ }
+
+ @Override
+ public void setWindowCrop(Rect crop) {
+ super.setWindowCrop(crop);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ if (crop.width() < mLastWidth || crop.height() < mLastHeight) {
+ // We're animating and cropping window, compute the appropriate crop for background.
+ calculateBgCrop(crop);
+ mBackgroundControl.setWindowCrop(mTmpContainerRect);
+ } else {
+ // When not animating just set crop to container rect.
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ mBackgroundControl.setWindowCrop(mTmpContainerRect);
+ }
+ }
+
+ @Override
+ public void setFinalCrop(Rect crop) {
+ super.setFinalCrop(crop);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ if (crop.width() < mLastWidth || crop.height() < mLastHeight) {
+ // We're animating and cropping window, compute the appropriate crop for background.
+ calculateBgCrop(crop);
+ mBackgroundControl.setFinalCrop(mTmpContainerRect);
+ } else {
+ // When not animating just set crop to container rect.
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ mBackgroundControl.setFinalCrop(mTmpContainerRect);
+ }
+ }
+
+ /** Compute background crop based on current animation progress for main surface control. */
+ private void calculateBgCrop(Rect crop) {
+ // Track overall progress of animation by computing cropped portion of status bar.
+ final Rect contentInsets = mWindowSurfaceController.mAnimator.mWin.mContentInsets;
+ float d = contentInsets.top == 0 ? 0 : (float) crop.top / contentInsets.top;
+
+ // Compute additional offset for the background when app window is positioned not at (0,0).
+ // E.g. landscape with navigation bar on the left.
+ final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame;
+ final int offsetX = (int) (winFrame.left * mLastDsDx * d + 0.5);
+ final int offsetY = (int) (winFrame.top * mLastDsDy * d + 0.5);
+
+ // Compute new scaled width and height for background that will depend on current animation
+ // progress. Those consist of current crop rect for the main surface + scaled areas outside
+ // of letterboxed area.
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ final int backgroundWidth =
+ (int) (crop.width() + (mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5);
+ final int backgroundHeight =
+ (int) (crop.height() + (mTmpContainerRect.height() - mLastHeight) * (1 - d) + 0.5);
+
+ mTmpContainerRect.set(crop);
+ // Make sure that part of background to left/top is visible and scaled.
+ mTmpContainerRect.offset(offsetX, offsetY);
+ // Set correct width/height, so that area to right/bottom is cropped properly.
+ mTmpContainerRect.right = mTmpContainerRect.left + backgroundWidth;
+ mTmpContainerRect.bottom = mTmpContainerRect.top + backgroundHeight;
+ }
+
+ @Override
+ public void setLayerStack(int layerStack) {
+ super.setLayerStack(layerStack);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.setLayerStack(layerStack);
+ }
+
+ @Override
+ public void setOpaque(boolean isOpaque) {
+ super.setOpaque(isOpaque);
+ mOpaque = isOpaque;
+ updateBackgroundVisibility();
+ }
+
+ @Override
+ public void setSecure(boolean isSecure) {
+ super.setSecure(isSecure);
+ }
+
+ @Override
+ public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
+ super.setMatrix(dsdx, dtdx, dtdy, dsdy);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.setMatrix(dsdx, dtdx, dtdy, dsdy);
+ mLastDsDx = dsdx;
+ mLastDsDy = dsdy;
+ updateBgPosition();
+ }
+
+ @Override
+ public void hide() {
+ super.hide();
+ mVisible = false;
+ updateBackgroundVisibility();
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ mVisible = true;
+ updateBackgroundVisibility();
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.destroy();
+ }
+
+ @Override
+ public void release() {
+ super.release();
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.release();
+ }
+
+ @Override
+ public void setTransparentRegionHint(Region region) {
+ super.setTransparentRegionHint(region);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.setTransparentRegionHint(region);
+ }
+
+ @Override
+ public void deferTransactionUntil(IBinder handle, long frame) {
+ super.deferTransactionUntil(handle, frame);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.deferTransactionUntil(handle, frame);
+ }
+
+ @Override
+ public void deferTransactionUntil(Surface barrier, long frame) {
+ super.deferTransactionUntil(barrier, frame);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.deferTransactionUntil(barrier, frame);
+ }
+
+ private void updateBackgroundVisibility() {
+ if (mBackgroundControl == null) {
+ return;
+ }
+ if (mOpaque && mVisible) {
+ mBackgroundControl.show();
+ } else {
+ mBackgroundControl.hide();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 0c217caf2dba..90a2892a1ac5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3244,6 +3244,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return !isInMultiWindowMode();
}
+ /** @return true when the window is in fullscreen task, but has non-fullscreen bounds set. */
+ boolean isLetterboxedAppWindow() {
+ final Task task = getTask();
+ final boolean taskIsFullscreen = task != null && task.isFullscreen();
+ final boolean appWindowIsFullscreen = mAppToken != null && !mAppToken.hasBounds();
+
+ return taskIsFullscreen && !appWindowIsFullscreen;
+ }
+
/** Returns the appropriate bounds to use for computing frames. */
private void getContainerBounds(Rect outBounds) {
if (isInMultiWindowMode()) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 0cc505ea9d05..86265c297b1b 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1200,7 +1200,8 @@ class WindowStateAnimator {
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
+ w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
- final boolean fullscreen = w.fillsDisplay();
+ final Task task = w.getTask();
+ final boolean fullscreen = w.fillsDisplay() || (task != null && task.isFullscreen());
final boolean isFreeformResizing =
w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
@@ -1526,6 +1527,19 @@ class WindowStateAnimator {
}
}
+ /**
+ * Get rect of the task this window is currently in. If there is no task, rect will be set to
+ * empty.
+ */
+ void getContainerRect(Rect rect) {
+ final Task task = mWin.getTask();
+ if (task != null) {
+ task.getDimBounds(rect);
+ } else {
+ rect.left = rect.top = rect.right = rect.bottom = 0;
+ }
+ }
+
void prepareSurfaceLocked(final boolean recoveringMemory) {
final WindowState w = mWin;
if (!hasSurface()) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 1728cfbb6ef0..110d5cb90f45 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -50,7 +50,7 @@ class WindowSurfaceController {
final WindowStateAnimator mAnimator;
- private SurfaceControl mSurfaceControl;
+ private SurfaceControlWithBackground mSurfaceControl;
// Should only be set from within setShown().
private boolean mSurfaceShown = false;
@@ -97,15 +97,10 @@ class WindowSurfaceController {
mWindowType = windowType;
mWindowSession = win.mSession;
- if (DEBUG_SURFACE_TRACE) {
- mSurfaceControl = new SurfaceTrace(
- s, name, w, h, format, flags, windowType, ownerUid);
- } else {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
- mSurfaceControl = new SurfaceControl(
- s, name, w, h, format, flags, windowType, ownerUid);
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- }
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
+ mSurfaceControl = new SurfaceControlWithBackground(
+ s, name, w, h, format, flags, windowType, ownerUid, this);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (mService.mRoot.mSurfaceTraceEnabled) {
mSurfaceControl = new RemoteSurfaceTrace(
@@ -118,7 +113,7 @@ class WindowSurfaceController {
}
void removeRemoteTrace() {
- mSurfaceControl = new SurfaceControl(mSurfaceControl);
+ mSurfaceControl = new SurfaceControlWithBackground(mSurfaceControl);
}
@@ -291,30 +286,30 @@ class WindowSurfaceController {
mSurfaceControl.setGeometryAppliesWithResize();
}
- void setMatrixInTransaction(float dsdx, float dtdx, float dsdy, float dtdy,
+ void setMatrixInTransaction(float dsdx, float dtdx, float dtdy, float dsdy,
boolean recoveringMemory) {
final boolean matrixChanged = mLastDsdx != dsdx || mLastDtdx != dtdx ||
- mLastDsdy != dsdy || mLastDtdy != dtdy;
+ mLastDtdy != dtdy || mLastDsdy != dsdy;
if (!matrixChanged) {
return;
}
mLastDsdx = dsdx;
mLastDtdx = dtdx;
- mLastDsdy = dsdy;
mLastDtdy = dtdy;
+ mLastDsdy = dsdy;
try {
if (SHOW_TRANSACTIONS) logSurface(
- "MATRIX [" + dsdx + "," + dtdx + "," + dsdy + "," + dtdy + "]", null);
+ "MATRIX [" + dsdx + "," + dtdx + "," + dtdy + "," + dsdy + "]", null);
mSurfaceControl.setMatrix(
- dsdx, dtdx, dsdy, dtdy);
+ dsdx, dtdx, dtdy, dsdy);
} catch (RuntimeException e) {
// If something goes wrong with the surface (such
// as running out of memory), don't take down the
// entire system.
Slog.e(TAG, "Error setting matrix on surface surface" + title
- + " MATRIX [" + dsdx + "," + dtdx + "," + dsdy + "," + dtdy + "]", null);
+ + " MATRIX [" + dsdx + "," + dtdx + "," + dtdy + "," + dsdy + "]", null);
if (!recoveringMemory) {
mAnimator.reclaimSomeSurfaceMemory("matrix", true);
}
@@ -421,6 +416,10 @@ class WindowSurfaceController {
}
}
+ void getContainerRect(Rect rect) {
+ mAnimator.getContainerRect(rect);
+ }
+
boolean showRobustlyInTransaction() {
if (SHOW_TRANSACTIONS) logSurface(
"SHOW (performLayout)", null);