Merge "Add black frame behind app window" into oc-dr1-dev
am: cbdaf04101
Change-Id: I121cca690aca4f2c9552440a47165b34fcb26d8b
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3219,6 +3219,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()) {
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -52,7 +52,7 @@ class WindowSurfaceController {
|
||||
|
||||
final WindowStateAnimator mAnimator;
|
||||
|
||||
private SurfaceControl mSurfaceControl;
|
||||
private SurfaceControlWithBackground mSurfaceControl;
|
||||
|
||||
// Should only be set from within setShown().
|
||||
private boolean mSurfaceShown = false;
|
||||
@@ -99,15 +99,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(
|
||||
@@ -120,7 +115,7 @@ class WindowSurfaceController {
|
||||
}
|
||||
|
||||
void removeRemoteTrace() {
|
||||
mSurfaceControl = new SurfaceControl(mSurfaceControl);
|
||||
mSurfaceControl = new SurfaceControlWithBackground(mSurfaceControl);
|
||||
}
|
||||
|
||||
|
||||
@@ -293,30 +288,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);
|
||||
}
|
||||
@@ -423,6 +418,10 @@ class WindowSurfaceController {
|
||||
}
|
||||
}
|
||||
|
||||
void getContainerRect(Rect rect) {
|
||||
mAnimator.getContainerRect(rect);
|
||||
}
|
||||
|
||||
boolean showRobustlyInTransaction() {
|
||||
if (SHOW_TRANSACTIONS) logSurface(
|
||||
"SHOW (performLayout)", null);
|
||||
|
||||
Reference in New Issue
Block a user