Merge "Prevent SurfaceView from drawing over parent surface insets"
This commit is contained in:
committed by
Android (Google) Code Review
commit
d08dc911f9
@@ -105,7 +105,7 @@ public abstract class WallpaperService extends Service {
|
||||
|
||||
static final String TAG = "WallpaperService";
|
||||
static final boolean DEBUG = false;
|
||||
|
||||
|
||||
private static final int DO_ATTACH = 10;
|
||||
private static final int DO_DETACH = 20;
|
||||
private static final int DO_SET_DESIRED_SIZE = 30;
|
||||
@@ -126,7 +126,7 @@ public abstract class WallpaperService extends Service {
|
||||
|
||||
private final ArrayList<Engine> mActiveEngines
|
||||
= new ArrayList<Engine>();
|
||||
|
||||
|
||||
static final class WallpaperCommand {
|
||||
String action;
|
||||
int x;
|
||||
@@ -145,7 +145,7 @@ public abstract class WallpaperService extends Service {
|
||||
*/
|
||||
public class Engine {
|
||||
IWallpaperEngineWrapper mIWallpaperEngine;
|
||||
|
||||
|
||||
// Copies from mIWallpaperEngine.
|
||||
HandlerCaller mCaller;
|
||||
IWallpaperConnection mConnection;
|
||||
@@ -155,7 +155,7 @@ public abstract class WallpaperService extends Service {
|
||||
boolean mVisible;
|
||||
boolean mReportedVisible;
|
||||
boolean mDestroyed;
|
||||
|
||||
|
||||
// Current window state.
|
||||
boolean mCreated;
|
||||
boolean mSurfaceCreated;
|
||||
@@ -258,7 +258,7 @@ public abstract class WallpaperService extends Service {
|
||||
}
|
||||
super.setFixedSize(width, height);
|
||||
}
|
||||
|
||||
|
||||
public void setKeepScreenOn(boolean screenOn) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Wallpapers do not support keep screen on");
|
||||
@@ -403,14 +403,14 @@ public abstract class WallpaperService extends Service {
|
||||
mClockFunction = clockFunction;
|
||||
mHandler = handler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides access to the surface in which this wallpaper is drawn.
|
||||
*/
|
||||
public SurfaceHolder getSurfaceHolder() {
|
||||
return mSurfaceHolder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience for {@link WallpaperManager#getDesiredMinimumWidth()
|
||||
* WallpaperManager.getDesiredMinimumWidth()}, returning the width
|
||||
@@ -419,7 +419,7 @@ public abstract class WallpaperService extends Service {
|
||||
public int getDesiredMinimumWidth() {
|
||||
return mIWallpaperEngine.mReqWidth;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience for {@link WallpaperManager#getDesiredMinimumHeight()
|
||||
* WallpaperManager.getDesiredMinimumHeight()}, returning the height
|
||||
@@ -437,7 +437,7 @@ public abstract class WallpaperService extends Service {
|
||||
public boolean isVisible() {
|
||||
return mReportedVisible;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if this engine is running in preview mode -- that is,
|
||||
* it is being shown to the user before they select it as the actual
|
||||
@@ -456,7 +456,7 @@ public abstract class WallpaperService extends Service {
|
||||
public boolean isInAmbientMode() {
|
||||
return mIsInAmbientMode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Control whether this wallpaper will receive raw touch events
|
||||
* from the window manager as the user interacts with the window
|
||||
@@ -557,7 +557,7 @@ public abstract class WallpaperService extends Service {
|
||||
* {@link WallpaperManager#sendWallpaperCommand}.
|
||||
* The default implementation does nothing, and always returns null
|
||||
* as the result.
|
||||
*
|
||||
*
|
||||
* @param action The name of the command to perform. This tells you
|
||||
* what to do and how to interpret the rest of the arguments.
|
||||
* @param x Generic integer parameter.
|
||||
@@ -794,7 +794,7 @@ public abstract class WallpaperService extends Service {
|
||||
}
|
||||
|
||||
mLayout.format = mFormat;
|
||||
|
||||
|
||||
mCurWindowFlags = mWindowFlags;
|
||||
mLayout.flags = mWindowFlags
|
||||
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||
@@ -1020,7 +1020,7 @@ public abstract class WallpaperService extends Service {
|
||||
mIsCreating = false;
|
||||
mSurfaceCreated = true;
|
||||
if (redrawNeeded) {
|
||||
mSession.finishDrawing(mWindow);
|
||||
mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
|
||||
}
|
||||
mIWallpaperEngine.reportShown();
|
||||
}
|
||||
@@ -1045,7 +1045,7 @@ public abstract class WallpaperService extends Service {
|
||||
mSurfaceHolder.setSizeFromLayout();
|
||||
mInitializing = true;
|
||||
mSession = WindowManagerGlobal.getWindowSession();
|
||||
|
||||
|
||||
mWindow.setSession(mSession);
|
||||
|
||||
mLayout.packageName = getPackageName();
|
||||
@@ -1149,7 +1149,7 @@ public abstract class WallpaperService extends Service {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void doOffsetsChanged(boolean always) {
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
@@ -1187,7 +1187,7 @@ public abstract class WallpaperService extends Service {
|
||||
mOffsetsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sync) {
|
||||
try {
|
||||
if (DEBUG) Log.v(TAG, "Reporting offsets change complete");
|
||||
@@ -1196,7 +1196,7 @@ public abstract class WallpaperService extends Service {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void doCommand(WallpaperCommand cmd) {
|
||||
Bundle result;
|
||||
if (!mDestroyed) {
|
||||
@@ -1213,7 +1213,7 @@ public abstract class WallpaperService extends Service {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reportSurfaceDestroyed() {
|
||||
if (mSurfaceCreated) {
|
||||
mSurfaceCreated = false;
|
||||
@@ -1229,12 +1229,12 @@ public abstract class WallpaperService extends Service {
|
||||
onSurfaceDestroyed(mSurfaceHolder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void detach() {
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
mDestroyed = true;
|
||||
|
||||
if (mIWallpaperEngine.mDisplayManager != null) {
|
||||
@@ -1246,9 +1246,9 @@ public abstract class WallpaperService extends Service {
|
||||
if (DEBUG) Log.v(TAG, "onVisibilityChanged(false): " + this);
|
||||
onVisibilityChanged(false);
|
||||
}
|
||||
|
||||
|
||||
reportSurfaceDestroyed();
|
||||
|
||||
|
||||
if (DEBUG) Log.v(TAG, "onDestroy(): " + this);
|
||||
onDestroy();
|
||||
|
||||
@@ -1256,18 +1256,18 @@ public abstract class WallpaperService extends Service {
|
||||
try {
|
||||
if (DEBUG) Log.v(TAG, "Removing window and destroying surface "
|
||||
+ mSurfaceHolder.getSurface() + " of: " + this);
|
||||
|
||||
|
||||
if (mInputEventReceiver != null) {
|
||||
mInputEventReceiver.dispose();
|
||||
mInputEventReceiver = null;
|
||||
}
|
||||
|
||||
|
||||
mSession.remove(mWindow);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
mSurfaceHolder.mSurface.release();
|
||||
mCreated = false;
|
||||
|
||||
|
||||
// Dispose the input channel after removing the window so the Window Manager
|
||||
// doesn't interpret the input channel being closed as an abnormal termination.
|
||||
if (mInputChannel != null) {
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
**
|
||||
** Copyright 2006, 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
|
||||
** 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
|
||||
** 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.
|
||||
** 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.
|
||||
*/
|
||||
@@ -31,6 +31,7 @@ import android.view.WindowManager;
|
||||
import android.view.InsetsState;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.Transaction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -57,7 +58,7 @@ interface IWindowSession {
|
||||
* position should be ignored) and surface of the window. The surface
|
||||
* will be invalid if the window is currently hidden, else you can use it
|
||||
* to draw the window's contents.
|
||||
*
|
||||
*
|
||||
* @param window The window being modified.
|
||||
* @param seq Ordering sequence number.
|
||||
* @param attrs If non-null, new attributes to apply to the window.
|
||||
@@ -147,8 +148,15 @@ interface IWindowSession {
|
||||
*/
|
||||
void getDisplayFrame(IWindow window, out Rect outDisplayFrame);
|
||||
|
||||
/**
|
||||
* Called when the client has finished drawing the surface, if needed.
|
||||
*
|
||||
* @param postDrawTransaction transaction filled by the client that can be
|
||||
* used to synchronize any post draw transactions with the server. Transaction
|
||||
* is null if there is no sync required.
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
void finishDrawing(IWindow window);
|
||||
void finishDrawing(IWindow window, in Transaction postDrawTransaction);
|
||||
|
||||
@UnsupportedAppUsage
|
||||
void setInTouchMode(boolean showFocus);
|
||||
|
||||
@@ -2693,6 +2693,14 @@ public final class SurfaceControl implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the transaction to parcel, clearing the transaction as if it had been applied so
|
||||
* it can be used to store future transactions. It's the responsibility of the parcel
|
||||
* reader to apply the original transaction.
|
||||
*
|
||||
* @param dest parcel to write the transaction to
|
||||
* @param flags
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) {
|
||||
if (mNativeObject == 0) {
|
||||
|
||||
@@ -98,7 +98,8 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
* artifacts may occur on previous versions of the platform when its window is
|
||||
* positioned asynchronously.</p>
|
||||
*/
|
||||
public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback {
|
||||
public class SurfaceView extends View
|
||||
implements ViewRootImpl.WindowStoppedCallback, ViewRootImpl.SurfaceChangedCallback {
|
||||
private static final String TAG = "SurfaceView";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
@@ -120,7 +121,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
|
||||
boolean mDrawFinished = false;
|
||||
|
||||
final Rect mScreenRect = new Rect();
|
||||
SurfaceSession mSurfaceSession;
|
||||
final SurfaceSession mSurfaceSession = new SurfaceSession();
|
||||
|
||||
SurfaceControl mSurfaceControl;
|
||||
// In the case of format changes we switch out the surface in-place
|
||||
@@ -266,11 +267,22 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
|
||||
updateSurface();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public void surfaceChangedCallback(SurfaceControl.Transaction transaction) {
|
||||
if (getViewRootImpl() != null && mBackgroundControl != null && mSurfaceControl != null) {
|
||||
SurfaceControl sc = getViewRootImpl().getSurfaceControl();
|
||||
transaction.setRelativeLayer(mBackgroundControl, sc, Integer.MIN_VALUE);
|
||||
transaction.setRelativeLayer(mSurfaceControl, sc, mSubLayer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
||||
getViewRootImpl().addWindowStoppedCallback(this);
|
||||
getViewRootImpl().addSurfaceChangedCallback(this);
|
||||
mWindowStopped = false;
|
||||
|
||||
mViewVisibility = getVisibility() == VISIBLE;
|
||||
@@ -356,6 +368,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
|
||||
// the SurfaceHolder forward, most live wallpapers do it.
|
||||
if (viewRoot != null) {
|
||||
viewRoot.removeWindowStoppedCallback(this);
|
||||
viewRoot.removeSurfaceChangedCallback(this);
|
||||
}
|
||||
|
||||
mAttachedToWindow = false;
|
||||
@@ -637,21 +650,34 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
|
||||
mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);
|
||||
|
||||
if (creating) {
|
||||
viewRoot.createBoundsSurface(mSubLayer);
|
||||
mSurfaceSession = new SurfaceSession();
|
||||
mDeferredDestroySurfaceControl = mSurfaceControl;
|
||||
|
||||
updateOpaqueFlag();
|
||||
// SurfaceView hierarchy
|
||||
// ViewRootImpl surface
|
||||
// - bounds layer (crops all child surfaces to parent surface insets)
|
||||
// - SurfaceView surface (drawn relative to ViewRootImpl surface)
|
||||
// - Background color layer (drawn behind all SurfaceView surfaces)
|
||||
//
|
||||
// The bounds layer is used to crop the surface view so it does not draw into
|
||||
// the parent surface inset region. Since there can be multiple surface views
|
||||
// below or above the parent surface, one option is to create multiple bounds
|
||||
// layer for each z order. The other option, the one implement is to create
|
||||
// a single bounds layer and set z order for each child surface relative to the
|
||||
// parent surface.
|
||||
// When creating the surface view, we parent it to the bounds layer and then
|
||||
// set the relative z order. When the parent surface changes, we have to
|
||||
// make sure to update the relative z via ViewRootImpl.SurfaceChangedCallback.
|
||||
final String name = "SurfaceView - " + viewRoot.getTitle().toString();
|
||||
|
||||
mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
|
||||
.setName(name)
|
||||
.setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)
|
||||
.setBufferSize(mSurfaceWidth, mSurfaceHeight)
|
||||
.setFormat(mFormat)
|
||||
.setParent(viewRoot.getSurfaceControl())
|
||||
.setFlags(mSurfaceFlags)
|
||||
.build();
|
||||
mSurfaceControl =
|
||||
new SurfaceControl.Builder(mSurfaceSession)
|
||||
.setName(name)
|
||||
.setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)
|
||||
.setBufferSize(mSurfaceWidth, mSurfaceHeight)
|
||||
.setFormat(mFormat)
|
||||
.setParent(viewRoot.getBoundsLayer())
|
||||
.setFlags(mSurfaceFlags)
|
||||
.build();
|
||||
mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession)
|
||||
.setName("Background for -" + name)
|
||||
.setOpaque(true)
|
||||
@@ -674,7 +700,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
|
||||
|
||||
SurfaceControl.openTransaction();
|
||||
try {
|
||||
mSurfaceControl.setLayer(mSubLayer);
|
||||
mSurfaceControl.setRelativeLayer(viewRoot.getSurfaceControl(), mSubLayer);
|
||||
|
||||
if (mViewVisibility) {
|
||||
mSurfaceControl.show();
|
||||
|
||||
@@ -68,6 +68,7 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
@@ -476,17 +477,19 @@ public final class ViewRootImpl implements ViewParent,
|
||||
@UnsupportedAppUsage
|
||||
public final Surface mSurface = new Surface();
|
||||
private final SurfaceControl mSurfaceControl = new SurfaceControl();
|
||||
private IBinder mPreviousSurfaceControlHandle = null;
|
||||
|
||||
private final Transaction mChangeSurfaceTransaction = new Transaction();
|
||||
private final SurfaceSession mSurfaceSession = new SurfaceSession();
|
||||
|
||||
/**
|
||||
* Child surface of {@code mSurface} with the same bounds as its parent, and crop bounds
|
||||
* are set to the parent's bounds adjusted for surface insets. This surface is created when
|
||||
* {@link ViewRootImpl#createBoundsSurface(int)} is called.
|
||||
* By parenting to this bounds surface, child surfaces can ensure they do not draw into the
|
||||
* surface inset regions set by the parent window.
|
||||
* Child container layer of {@code mSurface} with the same bounds as its parent, and cropped to
|
||||
* the surface insets. This surface is created only if a client requests it via {@link
|
||||
* #getBoundsLayer()}. By parenting to this bounds surface, child surfaces can ensure they do
|
||||
* not draw into the surface inset regions set by the parent window.
|
||||
*/
|
||||
public final Surface mBoundsSurface = new Surface();
|
||||
private SurfaceSession mSurfaceSession;
|
||||
private SurfaceControl mBoundsSurfaceControl;
|
||||
private SurfaceControl mBoundsLayer;
|
||||
|
||||
private final Transaction mTransaction = new Transaction();
|
||||
|
||||
@UnsupportedAppUsage
|
||||
@@ -1576,65 +1579,76 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a surface as a child of {@code mSurface} with the same bounds as its parent and
|
||||
* crop bounds set to the parent's bounds adjusted for surface insets.
|
||||
*
|
||||
* @param zOrderLayer Z order relative to the parent surface.
|
||||
*/
|
||||
public void createBoundsSurface(int zOrderLayer) {
|
||||
if (mSurfaceSession == null) {
|
||||
mSurfaceSession = new SurfaceSession();
|
||||
}
|
||||
if (mBoundsSurfaceControl != null && mBoundsSurface.isValid()) {
|
||||
return; // surface control for bounds surface already exists.
|
||||
}
|
||||
/** Register callback to be notified when the ViewRootImpl surface changes. */
|
||||
interface SurfaceChangedCallback {
|
||||
void surfaceChangedCallback(SurfaceControl.Transaction transaction);
|
||||
}
|
||||
|
||||
mBoundsSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
|
||||
private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>();
|
||||
void addSurfaceChangedCallback(SurfaceChangedCallback c) {
|
||||
mSurfaceChangedCallbacks.add(c);
|
||||
}
|
||||
|
||||
void removeSurfaceChangedCallback(SurfaceChangedCallback c) {
|
||||
mSurfaceChangedCallbacks.remove(c);
|
||||
}
|
||||
|
||||
private void notifySurfaceChanged(SurfaceControl.Transaction transaction) {
|
||||
for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) {
|
||||
mSurfaceChangedCallbacks.get(i).surfaceChangedCallback(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a child layer with the same bounds as its parent {@code mSurface} and cropped to the
|
||||
* surface insets. If the layer does not exist, it is created.
|
||||
*
|
||||
* <p>Parenting to this layer will ensure that its children are cropped by the view's surface
|
||||
* insets.
|
||||
*/
|
||||
public SurfaceControl getBoundsLayer() {
|
||||
if (mBoundsLayer == null) {
|
||||
mBoundsLayer = new SurfaceControl.Builder(mSurfaceSession)
|
||||
.setContainerLayer()
|
||||
.setName("Bounds for - " + getTitle().toString())
|
||||
.setParent(mSurfaceControl)
|
||||
.build();
|
||||
|
||||
setBoundsSurfaceCrop();
|
||||
mTransaction.setLayer(mBoundsSurfaceControl, zOrderLayer)
|
||||
.show(mBoundsSurfaceControl)
|
||||
.apply();
|
||||
mBoundsSurface.copyFrom(mBoundsSurfaceControl);
|
||||
setBoundsLayerCrop(mTransaction);
|
||||
mTransaction.show(mBoundsLayer).apply();
|
||||
}
|
||||
return mBoundsLayer;
|
||||
}
|
||||
|
||||
private void setBoundsSurfaceCrop() {
|
||||
private void setBoundsLayerCrop(Transaction t) {
|
||||
// mWinFrame is already adjusted for surface insets. So offset it and use it as
|
||||
// the cropping bounds.
|
||||
mTempBoundsRect.set(mWinFrame);
|
||||
mTempBoundsRect.offsetTo(mWindowAttributes.surfaceInsets.left,
|
||||
mWindowAttributes.surfaceInsets.top);
|
||||
mTransaction.setWindowCrop(mBoundsSurfaceControl, mTempBoundsRect);
|
||||
t.setWindowCrop(mBoundsLayer, mTempBoundsRect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after window layout to update the bounds surface. If the surface insets have
|
||||
* changed or the surface has resized, update the bounds surface.
|
||||
* Called after window layout to update the bounds surface. If the surface insets have changed
|
||||
* or the surface has resized, update the bounds surface.
|
||||
*/
|
||||
private void updateBoundsSurface() {
|
||||
if (mBoundsSurfaceControl != null && mSurface.isValid()) {
|
||||
setBoundsSurfaceCrop();
|
||||
mTransaction.deferTransactionUntilSurface(mBoundsSurfaceControl,
|
||||
private void updateBoundsLayer() {
|
||||
if (mBoundsLayer != null) {
|
||||
setBoundsLayerCrop(mTransaction);
|
||||
mTransaction.deferTransactionUntilSurface(mBoundsLayer,
|
||||
mSurface, mSurface.getNextFrameNumber())
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
|
||||
private void destroySurface() {
|
||||
if (mBoundsLayer != null) {
|
||||
mBoundsLayer.release();
|
||||
mBoundsLayer = null;
|
||||
}
|
||||
mSurface.release();
|
||||
mSurfaceControl.release();
|
||||
|
||||
mSurfaceSession = null;
|
||||
|
||||
if (mBoundsSurfaceControl != null) {
|
||||
mBoundsSurfaceControl.remove();
|
||||
mBoundsSurface.release();
|
||||
mBoundsSurfaceControl = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2598,7 +2612,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
|
||||
if (surfaceSizeChanged) {
|
||||
updateBoundsSurface();
|
||||
updateBoundsLayer();
|
||||
}
|
||||
|
||||
final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
|
||||
@@ -3438,7 +3452,9 @@ public final class ViewRootImpl implements ViewParent,
|
||||
private void reportDrawFinished() {
|
||||
try {
|
||||
mDrawsNeededToReport = 0;
|
||||
mWindowSession.finishDrawing(mWindow);
|
||||
if (mSurfaceControl.isValid()) {
|
||||
mWindowSession.finishDrawing(mWindow, mChangeSurfaceTransaction);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// Have fun!
|
||||
}
|
||||
@@ -7089,6 +7105,9 @@ public final class ViewRootImpl implements ViewParent,
|
||||
frameNumber = mSurface.getNextFrameNumber();
|
||||
}
|
||||
|
||||
mPreviousSurfaceControlHandle = mSurfaceControl.isValid()
|
||||
? mSurfaceControl.getHandle() : null;
|
||||
|
||||
int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params,
|
||||
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
|
||||
(int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
|
||||
@@ -7102,6 +7121,11 @@ public final class ViewRootImpl implements ViewParent,
|
||||
destroySurface();
|
||||
}
|
||||
|
||||
if (mPreviousSurfaceControlHandle != null && mSurfaceControl.isValid()
|
||||
&& mPreviousSurfaceControlHandle != mSurfaceControl.getHandle()) {
|
||||
notifySurfaceChanged(mChangeSurfaceTransaction);
|
||||
}
|
||||
|
||||
mPendingAlwaysConsumeSystemBars =
|
||||
(relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0;
|
||||
|
||||
@@ -7326,7 +7350,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
try {
|
||||
if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
|
||||
& WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
|
||||
mWindowSession.finishDrawing(mWindow);
|
||||
mWindowSession.finishDrawing(
|
||||
mWindow, null /* postDrawTransaction */);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public class BaseIWindow extends IWindow.Stub {
|
||||
DisplayCutout.ParcelableWrapper displayCutout) {
|
||||
if (reportDraw) {
|
||||
try {
|
||||
mSession.finishDrawing(this);
|
||||
mSession.finishDrawing(this, null /* postDrawTransaction */);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1266,6 +1266,7 @@ static void nativeWriteTransactionToParcel(JNIEnv* env, jclass clazz, jlong nati
|
||||
reinterpret_cast<SurfaceComposerClient::Transaction *>(nativeObject);
|
||||
if (self != nullptr) {
|
||||
self->writeToParcel(parcel);
|
||||
self->clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITION
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ClipData;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
@@ -225,10 +226,11 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishDrawing(IWindow window) {
|
||||
public void finishDrawing(IWindow window,
|
||||
@Nullable SurfaceControl.Transaction postDrawTransaction) {
|
||||
if (WindowManagerService.localLOGV) Slog.v(
|
||||
TAG_WM, "IWindow finishDrawing called for " + window);
|
||||
mService.finishDrawingWindow(this, window);
|
||||
mService.finishDrawingWindow(this, window, postDrawTransaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -418,7 +418,7 @@ class TaskSnapshotSurface implements StartingSurface {
|
||||
|
||||
private void reportDrawn() {
|
||||
try {
|
||||
mSession.finishDrawing(mWindow);
|
||||
mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
|
||||
} catch (RemoteException e) {
|
||||
// Local call.
|
||||
}
|
||||
|
||||
@@ -2356,14 +2356,15 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
void finishDrawingWindow(Session session, IWindow client) {
|
||||
void finishDrawingWindow(Session session, IWindow client,
|
||||
@Nullable SurfaceControl.Transaction postDrawTransaction) {
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mGlobalLock) {
|
||||
WindowState win = windowForClientLocked(session, client, false);
|
||||
if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "finishDrawingWindow: " + win + " mDrawState="
|
||||
+ (win != null ? win.mWinAnimator.drawStateToString() : "null"));
|
||||
if (win != null && win.mWinAnimator.finishDrawingLocked()) {
|
||||
if (win != null && win.mWinAnimator.finishDrawingLocked(postDrawTransaction)) {
|
||||
if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
|
||||
win.getDisplayContent().pendingLayoutChanges |=
|
||||
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
|
||||
|
||||
@@ -220,7 +220,16 @@ class WindowStateAnimator {
|
||||
|
||||
private final Rect mTmpSize = new Rect();
|
||||
|
||||
private final SurfaceControl.Transaction mReparentTransaction = new SurfaceControl.Transaction();
|
||||
/**
|
||||
* Handles surface changes synchronized to after the client has drawn the surface. This
|
||||
* transaction is currently used to reparent the old surface children to the new surface once
|
||||
* the client has completed drawing to the new surface.
|
||||
* This transaction is also used to merge transactions parceled in by the client. The client
|
||||
* uses the transaction to update the relative z of its children from the old parent surface
|
||||
* to the new parent surface once window manager reparents its children.
|
||||
*/
|
||||
private final SurfaceControl.Transaction mPostDrawTransaction =
|
||||
new SurfaceControl.Transaction();
|
||||
|
||||
// Used to track whether we have called detach children on the way to invisibility, in which
|
||||
// case we need to give the client a new Surface if it lays back out to a visible state.
|
||||
@@ -301,7 +310,7 @@ class WindowStateAnimator {
|
||||
SurfaceControl.mergeToGlobalTransaction(mTmpTransaction);
|
||||
}
|
||||
|
||||
boolean finishDrawingLocked() {
|
||||
boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction) {
|
||||
final boolean startingWindow =
|
||||
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
|
||||
if (DEBUG_STARTING_WINDOW && startingWindow) {
|
||||
@@ -321,6 +330,9 @@ class WindowStateAnimator {
|
||||
mDrawState = COMMIT_DRAW_PENDING;
|
||||
layoutNeeded = true;
|
||||
}
|
||||
if (postDrawTransaction != null) {
|
||||
mPostDrawTransaction.merge(postDrawTransaction);
|
||||
}
|
||||
|
||||
return layoutNeeded;
|
||||
}
|
||||
@@ -385,7 +397,7 @@ class WindowStateAnimator {
|
||||
// child layers need to be reparented to the new surface to make this
|
||||
// transparent to the app.
|
||||
if (mWin.mAppToken == null || mWin.mAppToken.isRelaunching() == false) {
|
||||
mReparentTransaction.reparentChildren(mPendingDestroySurface.mSurfaceControl,
|
||||
mPostDrawTransaction.reparentChildren(mPendingDestroySurface.mSurfaceControl,
|
||||
mSurfaceController.mSurfaceControl.getHandle())
|
||||
.apply();
|
||||
}
|
||||
@@ -1150,7 +1162,7 @@ class WindowStateAnimator {
|
||||
// LogicalDisplay.
|
||||
mAnimator.setPendingLayoutChanges(w.getDisplayId(),
|
||||
FINISH_LAYOUT_REDO_ANIM);
|
||||
if (DEBUG_LAYOUT_REPEATS) {
|
||||
if (DEBUG_LAYOUT_REPEATS) {
|
||||
mService.mWindowPlacerLocked.debugLayoutRepeats(
|
||||
"showSurfaceRobustlyLocked " + w,
|
||||
mAnimator.getPendingLayoutChanges(w.getDisplayId()));
|
||||
@@ -1281,10 +1293,13 @@ class WindowStateAnimator {
|
||||
// If we had a preserved surface it's no longer needed, and it may be harmful
|
||||
// if we are transparent.
|
||||
if (mPendingDestroySurface != null && mDestroyPreservedSurfaceUponRedraw) {
|
||||
mPendingDestroySurface.mSurfaceControl.hide();
|
||||
mPendingDestroySurface.reparentChildrenInTransaction(mSurfaceController);
|
||||
final SurfaceControl pendingSurfaceControl = mPendingDestroySurface.mSurfaceControl;
|
||||
mPostDrawTransaction.hide(pendingSurfaceControl);
|
||||
mPostDrawTransaction.reparentChildren(pendingSurfaceControl,
|
||||
mSurfaceController.getHandle());
|
||||
}
|
||||
|
||||
mPostDrawTransaction.apply();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user