summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Rob Carr <racarr@google.com> 2017-03-01 17:49:23 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2017-03-01 17:49:27 +0000
commit0e06ccf488bb7744709b8f3421f3a5a2f5ae69f7 (patch)
tree5393e32af701a61c63bfb72f8ecbf77f9dc0ad08
parente2a3c4e8c4d902213726039c701484c6c1c721f5 (diff)
parent693f3432ae77d1fcfaaf9d168de861192aacb4c4 (diff)
Merge "Modify SurfaceView to use SurfaceFlinger child surfaces."
-rw-r--r--core/java/android/view/SurfaceControl.java17
-rw-r--r--core/java/android/view/SurfaceSession.java5
-rw-r--r--core/java/android/view/SurfaceView.java440
-rw-r--r--core/java/android/view/ViewRootImpl.java10
-rw-r--r--core/java/com/android/internal/view/SurfaceCallbackHelper.java21
-rw-r--r--core/jni/android_view_RenderNode.cpp4
-rw-r--r--core/jni/android_view_SurfaceControl.cpp28
-rw-r--r--core/jni/android_view_SurfaceSession.cpp11
-rw-r--r--media/java/android/media/tv/TvView.java4
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java10
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java20
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java14
13 files changed, 303 insertions, 290 deletions
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index b718696b2202..0ac16c1fa023 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -95,6 +95,11 @@ public class SurfaceControl {
IBinder displayToken, int mode);
private static native void nativeDeferTransactionUntil(long nativeObject,
IBinder handle, long frame);
+ private static native void nativeDeferTransactionUntilSurface(long nativeObject,
+ long surfaceObject, long frame);
+ private static native void nativeReparentChildren(long nativeObject,
+ IBinder handle);
+ private static native void nativeSeverChildren(long nativeObject);
private static native void nativeSetOverrideScalingMode(long nativeObject,
int scalingMode);
private static native IBinder nativeGetHandle(long nativeObject);
@@ -421,6 +426,18 @@ public class SurfaceControl {
nativeDeferTransactionUntil(mNativeObject, handle, frame);
}
+ public void deferTransactionUntil(Surface barrier, long frame) {
+ nativeDeferTransactionUntilSurface(mNativeObject, barrier.mNativeObject, frame);
+ }
+
+ public void reparentChildren(IBinder newParentHandle) {
+ nativeReparentChildren(mNativeObject, newParentHandle);
+ }
+
+ public void detachChildren() {
+ nativeSeverChildren(mNativeObject);
+ }
+
public void setOverrideScalingMode(int scalingMode) {
checkNotReleased();
nativeSetOverrideScalingMode(mNativeObject, scalingMode);
diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java
index 3cf5af484625..b5912bc1e1c8 100644
--- a/core/java/android/view/SurfaceSession.java
+++ b/core/java/android/view/SurfaceSession.java
@@ -27,6 +27,7 @@ public final class SurfaceSession {
private long mNativeClient; // SurfaceComposerClient*
private static native long nativeCreate();
+ private static native long nativeCreateScoped(long surfacePtr);
private static native void nativeDestroy(long ptr);
private static native void nativeKill(long ptr);
@@ -35,6 +36,10 @@ public final class SurfaceSession {
mNativeClient = nativeCreate();
}
+ public SurfaceSession(Surface root) {
+ mNativeClient = nativeCreateScoped(root.mNativeObject);
+ }
+
/* no user serviceable parts here ... */
@Override
protected void finalize() throws Throwable {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index d2577d48c3d1..64306338311b 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,6 +16,10 @@
package android.view;
+import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_SUBLAYER;
+import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_OVERLAY_SUBLAYER;
+import static android.view.WindowManagerPolicy.APPLICATION_PANEL_SUBLAYER;
+
import android.content.Context;
import android.content.res.CompatibilityInfo.Translator;
import android.content.res.Configuration;
@@ -26,16 +30,12 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.os.Handler;
import android.os.Message;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
-import com.android.internal.view.BaseIWindow;
import com.android.internal.view.SurfaceCallbackHelper;
-import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;
@@ -92,8 +92,8 @@ import java.util.concurrent.locks.ReentrantLock;
* positioned asynchronously.</p>
*/
public class SurfaceView extends View {
- static private final String TAG = "SurfaceView";
- static private final boolean DEBUG = false;
+ private static final String TAG = "SurfaceView";
+ private static final boolean DEBUG = false;
final ArrayList<SurfaceHolder.Callback> mCallbacks
= new ArrayList<SurfaceHolder.Callback>();
@@ -102,28 +102,23 @@ public class SurfaceView extends View {
final ReentrantLock mSurfaceLock = new ReentrantLock();
final Surface mSurface = new Surface(); // Current surface in use
- final Surface mNewSurface = new Surface(); // New surface we are switching to
boolean mDrawingStopped = true;
+ // We use this to track if the application has produced a frame
+ // in to the Surface. Up until that point, we should be careful not to punch
+ // holes.
+ boolean mDrawFinished = false;
+
+ final Rect mScreenRect = new Rect();
+ SurfaceSession mSurfaceSession;
- final WindowManager.LayoutParams mLayout
- = new WindowManager.LayoutParams();
- IWindowSession mSession;
- MyWindow mWindow;
- final Rect mVisibleInsets = new Rect();
- final Rect mWinFrame = new Rect();
- final Rect mOverscanInsets = new Rect();
- final Rect mContentInsets = new Rect();
- final Rect mStableInsets = new Rect();
- final Rect mOutsets = new Rect();
- final Rect mBackdropFrame = new Rect();
+ SurfaceControl mSurfaceControl;
final Rect mTmpRect = new Rect();
final Configuration mConfiguration = new Configuration();
static final int KEEP_SCREEN_ON_MSG = 1;
- static final int GET_NEW_SURFACE_MSG = 2;
- static final int UPDATE_WINDOW_MSG = 3;
+ static final int DRAW_FINISHED_MSG = 2;
- int mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+ int mSubLayer = APPLICATION_MEDIA_SUBLAYER;
boolean mIsCreating = false;
private volatile boolean mRtHandlingPositionUpdates = false;
@@ -135,11 +130,9 @@ public class SurfaceView extends View {
case KEEP_SCREEN_ON_MSG: {
setKeepScreenOn(msg.arg1 != 0);
} break;
- case GET_NEW_SURFACE_MSG: {
- handleGetNewSurface();
- } break;
- case UPDATE_WINDOW_MSG: {
- updateWindow();
+ case DRAW_FINISHED_MSG: {
+ mDrawFinished = true;
+ invalidate();
} break;
}
}
@@ -149,7 +142,7 @@ public class SurfaceView extends View {
= new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
- updateWindow();
+ updateSurface();
}
};
@@ -159,13 +152,14 @@ public class SurfaceView extends View {
public boolean onPreDraw() {
// reposition ourselves where the surface is
mHaveFrame = getWidth() > 0 && getHeight() > 0;
- updateWindow();
+ updateSurface();
return true;
}
};
boolean mRequestedVisible = false;
boolean mWindowVisibility = false;
+ boolean mLastWindowVisibility = false;
boolean mViewVisibility = false;
int mRequestedWidth = -1;
int mRequestedHeight = -1;
@@ -181,19 +175,17 @@ public class SurfaceView extends View {
boolean mVisible = false;
int mWindowSpaceLeft = -1;
int mWindowSpaceTop = -1;
- int mWindowSpaceWidth = -1;
- int mWindowSpaceHeight = -1;
+ int mSurfaceWidth = -1;
+ int mSurfaceHeight = -1;
int mFormat = -1;
final Rect mSurfaceFrame = new Rect();
int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
- boolean mUpdateWindowNeeded;
- boolean mReportDrawNeeded;
private Translator mTranslator;
- private int mWindowInsetLeft;
- private int mWindowInsetTop;
private boolean mGlobalListenersAdded;
+ private int mSurfaceFlags = SurfaceControl.HIDDEN;
+
public SurfaceView(Context context) {
this(context, null);
}
@@ -227,11 +219,8 @@ public class SurfaceView extends View {
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mParent.requestTransparentRegion(this);
- mSession = getWindowSession();
- mLayout.token = getWindowToken();
- mLayout.setTitle("SurfaceView - " + getViewRootImpl().getTitle());
- mLayout.packageName = mContext.getOpPackageName();
mViewVisibility = getVisibility() == VISIBLE;
+ mRequestedVisible = mViewVisibility && mWindowVisibility;
if (!mGlobalListenersAdded) {
ViewTreeObserver observer = getViewTreeObserver();
@@ -246,7 +235,7 @@ public class SurfaceView extends View {
super.onWindowVisibilityChanged(visibility);
mWindowVisibility = visibility == VISIBLE;
mRequestedVisible = mWindowVisibility && mViewVisibility;
- updateWindow();
+ updateSurface();
}
@Override
@@ -264,7 +253,7 @@ public class SurfaceView extends View {
requestLayout();
}
mRequestedVisible = newRequestedVisible;
- updateWindow();
+ updateSurface();
}
@Override
@@ -277,19 +266,14 @@ public class SurfaceView extends View {
}
mRequestedVisible = false;
- updateWindow();
- mHaveFrame = false;
- if (mWindow != null) {
- try {
- mSession.remove(mWindow);
- } catch (RemoteException ex) {
- // Not much we can do here...
- }
- mWindow = null;
+
+ updateSurface();
+ if (mSurfaceControl != null) {
+ mSurfaceControl.destroy();
}
- mSession = null;
- mLayout.token = null;
+ mSurfaceControl = null;
+ mHaveFrame = false;
super.onDetachedFromWindow();
}
@@ -308,13 +292,13 @@ public class SurfaceView extends View {
@Override
protected boolean setFrame(int left, int top, int right, int bottom) {
boolean result = super.setFrame(left, top, right, bottom);
- updateWindow();
+ updateSurface();
return result;
}
@Override
public boolean gatherTransparentRegion(Region region) {
- if (mWindowType == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+ if (isAboveParent()) {
return super.gatherTransparentRegion(region);
}
@@ -341,7 +325,7 @@ public class SurfaceView extends View {
@Override
public void draw(Canvas canvas) {
- if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+ if (mDrawFinished && !isAboveParent()) {
// draw() is not called when SKIP_DRAW is set
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
// punch a whole in the view-hierarchy below us
@@ -353,8 +337,8 @@ public class SurfaceView extends View {
@Override
protected void dispatchDraw(Canvas canvas) {
- if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
- // if SKIP_DRAW is cleared, draw() has already punched a hole
+ if (mDrawFinished && !isAboveParent()) {
+ // draw() is not called when SKIP_DRAW is set
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
// punch a whole in the view-hierarchy below us
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
@@ -375,9 +359,8 @@ public class SurfaceView extends View {
* <p>Calling this overrides any previous call to {@link #setZOrderOnTop}.
*/
public void setZOrderMediaOverlay(boolean isMediaOverlay) {
- mWindowType = isMediaOverlay
- ? WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
- : WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+ mSubLayer = isMediaOverlay
+ ? APPLICATION_MEDIA_OVERLAY_SUBLAYER : APPLICATION_MEDIA_SUBLAYER;
}
/**
@@ -395,12 +378,9 @@ public class SurfaceView extends View {
*/
public void setZOrderOnTop(boolean onTop) {
if (onTop) {
- mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
- // ensures the surface is placed below the IME
- mLayout.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ mSubLayer = APPLICATION_PANEL_SUBLAYER;
} else {
- mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
- mLayout.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ mSubLayer = APPLICATION_MEDIA_SUBLAYER;
}
}
@@ -418,31 +398,23 @@ public class SurfaceView extends View {
*/
public void setSecure(boolean isSecure) {
if (isSecure) {
- mLayout.flags |= WindowManager.LayoutParams.FLAG_SECURE;
+ mSurfaceFlags |= SurfaceControl.SECURE;
} else {
- mLayout.flags &= ~WindowManager.LayoutParams.FLAG_SECURE;
+ mSurfaceFlags &= ~SurfaceControl.SECURE;
}
}
- /**
- * Hack to allow special layering of windows. The type is one of the
- * types in WindowManager.LayoutParams. This is a hack so:
- * @hide
- */
- public void setWindowType(int type) {
- mWindowType = type;
- }
-
/** @hide */
- protected void updateWindow() {
+ protected void updateSurface() {
if (!mHaveFrame) {
return;
}
ViewRootImpl viewRoot = getViewRootImpl();
- if (viewRoot != null) {
- mTranslator = viewRoot.mTranslator;
+ if (viewRoot == null || viewRoot.mSurface == null || !viewRoot.mSurface.isValid()) {
+ return;
}
+ mTranslator = viewRoot.mTranslator;
if (mTranslator != null) {
mSurface.setCompatibilityTranslator(mTranslator);
}
@@ -452,17 +424,15 @@ public class SurfaceView extends View {
int myHeight = mRequestedHeight;
if (myHeight <= 0) myHeight = getHeight();
- final boolean creating = mWindow == null;
final boolean formatChanged = mFormat != mRequestedFormat;
- final boolean sizeChanged = mWindowSpaceWidth != myWidth || mWindowSpaceHeight != myHeight;
+ final boolean creating = (mSurfaceControl == null || formatChanged)
+ && mRequestedVisible;
+ final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight;
final boolean visibleChanged = mVisible != mRequestedVisible;
- final boolean layoutSizeChanged = getWidth() != mLayout.width
- || getHeight() != mLayout.height;
-
+ final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility;
boolean redrawNeeded = false;
- if (creating || formatChanged || sizeChanged || visibleChanged
- || mUpdateWindowNeeded || mReportDrawNeeded) {
+ if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) {
getLocationInWindow(mLocation);
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
@@ -476,93 +446,74 @@ public class SurfaceView extends View {
final boolean visible = mVisible = mRequestedVisible;
mWindowSpaceLeft = mLocation[0];
mWindowSpaceTop = mLocation[1];
- mWindowSpaceWidth = myWidth;
- mWindowSpaceHeight = myHeight;
+ mSurfaceWidth = myWidth;
+ mSurfaceHeight = myHeight;
mFormat = mRequestedFormat;
+ mLastWindowVisibility = mWindowVisibility;
- // Scaling/Translate window's layout here because mLayout is not used elsewhere.
-
- // Places the window relative
- mLayout.x = mWindowSpaceLeft;
- mLayout.y = mWindowSpaceTop;
- mLayout.width = getWidth();
- mLayout.height = getHeight();
+ mScreenRect.left = mWindowSpaceLeft;
+ mScreenRect.top = mWindowSpaceTop;
+ mScreenRect.right = mWindowSpaceLeft + getWidth();
+ mScreenRect.bottom = mWindowSpaceTop + getHeight();
if (mTranslator != null) {
- mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);
+ mTranslator.translateRectInAppWindowToScreen(mScreenRect);
}
- mLayout.format = mRequestedFormat;
- mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | WindowManager.LayoutParams.FLAG_SCALED
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- ;
- if (!creating && !sizeChanged) {
- mLayout.privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY;
- } else {
- mLayout.privateFlags &=
- ~WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY;
+ if (creating) {
+ mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
+ mSurfaceControl = new SurfaceControl(mSurfaceSession,
+ "SurfaceView - " + viewRoot.getTitle().toString(),
+ mSurfaceWidth, mSurfaceHeight, mFormat,
+ mSurfaceFlags);
}
- if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) {
- mLayout.privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
- }
- mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
- | WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
-
- if (mWindow == null) {
- Display display = getDisplay();
- mWindow = new MyWindow(this);
- mLayout.type = mWindowType;
- mLayout.gravity = Gravity.START|Gravity.TOP;
- mSession.addToDisplayWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
- mVisible ? VISIBLE : GONE, display.getDisplayId(), mContentInsets,
- mStableInsets);
- }
-
- boolean realSizeChanged;
- boolean reportDrawNeeded;
-
- int relayoutResult;
+ boolean realSizeChanged = false;
mSurfaceLock.lock();
try {
- mUpdateWindowNeeded = false;
- reportDrawNeeded = mReportDrawNeeded;
- mReportDrawNeeded = false;
mDrawingStopped = !visible;
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ "Cur surface: " + mSurface);
- relayoutResult = mSession.relayout(
- mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight,
- visible ? VISIBLE : GONE,
- WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
- mWinFrame, mOverscanInsets, mContentInsets,
- mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame,
- mConfiguration, mNewSurface);
- if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
- reportDrawNeeded = true;
+ SurfaceControl.openTransaction();
+ try {
+ mSurfaceControl.setLayer(mSubLayer);
+ if (mViewVisibility) {
+ mSurfaceControl.show();
+ } else {
+ mSurfaceControl.hide();
+ }
+
+ // While creating the surface, we will set it's initial
+ // geometry. Outside of that though, we should generally
+ // leave it to the RenderThread.
+ if (creating || !mRtHandlingPositionUpdates) {
+ mSurfaceControl.setPosition(mScreenRect.left, mScreenRect.top);
+ mSurfaceControl.setMatrix(mScreenRect.width() / (float) mSurfaceWidth,
+ 0.0f, 0.0f,
+ mScreenRect.height() / (float) mSurfaceHeight);
+ }
+ if (sizeChanged) {
+ mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight);
+ }
+ } finally {
+ SurfaceControl.closeTransaction();
}
- if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
- + "New surface: " + mNewSurface
- + ", vis=" + visible + ", frame=" + mWinFrame);
+ if (sizeChanged || creating) {
+ redrawNeeded = true;
+ }
mSurfaceFrame.left = 0;
mSurfaceFrame.top = 0;
if (mTranslator == null) {
- mSurfaceFrame.right = mWinFrame.width();
- mSurfaceFrame.bottom = mWinFrame.height();
+ mSurfaceFrame.right = mSurfaceWidth;
+ mSurfaceFrame.bottom = mSurfaceHeight;
} else {
float appInvertedScale = mTranslator.applicationInvertedScale;
- mSurfaceFrame.right = (int) (mWinFrame.width() * appInvertedScale + 0.5f);
- mSurfaceFrame.bottom = (int) (mWinFrame.height() * appInvertedScale + 0.5f);
+ mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f);
+ mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f);
}
final int surfaceWidth = mSurfaceFrame.right;
@@ -576,12 +527,11 @@ public class SurfaceView extends View {
}
try {
- redrawNeeded |= creating | reportDrawNeeded;
+ redrawNeeded |= visible && !mDrawFinished;
SurfaceHolder.Callback callbacks[] = null;
- final boolean surfaceChanged = (relayoutResult
- & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0;
+ final boolean surfaceChanged = creating;
if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
mSurfaceCreated = false;
if (mSurface.isValid()) {
@@ -608,7 +558,10 @@ public class SurfaceView extends View {
}
}
- mSurface.transferFrom(mNewSurface);
+ if (creating) {
+ mSurface.copyFrom(mSurfaceControl);
+ }
+
if (visible && mSurface.isValid()) {
if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
mSurfaceCreated = true;
@@ -641,53 +594,57 @@ public class SurfaceView extends View {
callbacks = getSurfaceCallbacks();
}
SurfaceCallbackHelper sch =
- new SurfaceCallbackHelper(mSession, mWindow);
+ new SurfaceCallbackHelper(this::onDrawFinished);
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
}
}
} finally {
mIsCreating = false;
- mSession.performDeferredDestroy(mWindow);
+ if (mSurfaceControl != null && !mSurfaceCreated) {
+ mSurfaceControl.destroy();
+ mSurfaceControl = null;
+ }
}
- } catch (RemoteException ex) {
+ } catch (Exception ex) {
Log.e(TAG, "Exception from relayout", ex);
}
if (DEBUG) Log.v(
- TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
- " w=" + mLayout.width + " h=" + mLayout.height +
- ", frame=" + mSurfaceFrame);
+ TAG, "Layout: x=" + mScreenRect.left + " y=" + mScreenRect.top
+ + " w=" + mScreenRect.width() + " h=" + mScreenRect.height()
+ + ", frame=" + mSurfaceFrame);
} else {
// Calculate the window position in case RT loses the window
// and we need to fallback to a UI-thread driven position update
getLocationInWindow(mLocation);
final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
|| mWindowSpaceTop != mLocation[1];
+ final boolean layoutSizeChanged = getWidth() != mScreenRect.width()
+ || getHeight() != mScreenRect.height();
if (positionChanged || layoutSizeChanged) { // Only the position has changed
mWindowSpaceLeft = mLocation[0];
mWindowSpaceTop = mLocation[1];
- // For our size changed check, we keep mLayout.width and mLayout.height
+ // For our size changed check, we keep mScreenRect.width() and mScreenRect.height()
// in view local space.
- mLocation[0] = mLayout.width = getWidth();
- mLocation[1] = mLayout.height = getHeight();
+ mLocation[0] = getWidth();
+ mLocation[1] = getHeight();
transformFromViewToWindowSpace(mLocation);
- mTmpRect.set(mWindowSpaceLeft, mWindowSpaceTop,
+ mScreenRect.set(mWindowSpaceLeft, mWindowSpaceTop,
mLocation[0], mLocation[1]);
if (mTranslator != null) {
- mTranslator.translateRectInAppWindowToScreen(mTmpRect);
+ mTranslator.translateRectInAppWindowToScreen(mScreenRect);
}
if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) {
try {
- if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition UI, " +
+ if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition UI, " +
"postion = [%d, %d, %d, %d]", System.identityHashCode(this),
- mTmpRect.left, mTmpRect.top,
- mTmpRect.right, mTmpRect.bottom));
- mSession.repositionChild(mWindow, mTmpRect.left, mTmpRect.top,
- mTmpRect.right, mTmpRect.bottom, -1, mTmpRect);
- } catch (RemoteException ex) {
+ mScreenRect.left, mScreenRect.top,
+ mScreenRect.right, mScreenRect.bottom));
+ setParentSpaceRectangle(mScreenRect, -1);
+ } catch (Exception ex) {
Log.e(TAG, "Exception from relayout", ex);
}
}
@@ -695,18 +652,40 @@ public class SurfaceView extends View {
}
}
+ private void onDrawFinished() {
+ if (DEBUG) {
+ Log.i(TAG, System.identityHashCode(this) + " "
+ + "finishedDrawing");
+ }
+ mHandler.sendEmptyMessage(DRAW_FINISHED_MSG);
+ }
+
+ private void setParentSpaceRectangle(Rect position, long frameNumber) {
+ ViewRootImpl viewRoot = getViewRootImpl();
+
+ SurfaceControl.openTransaction();
+ try {
+ if (frameNumber > 0) {
+ mSurfaceControl.deferTransactionUntil(viewRoot.mSurface, frameNumber);
+ }
+ mSurfaceControl.setPosition(position.left, position.top);
+ mSurfaceControl.setMatrix(position.width() / (float) mSurfaceWidth,
+ 0.0f, 0.0f,
+ position.height() / (float) mSurfaceHeight);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+
private Rect mRTLastReportedPosition = new Rect();
/**
* Called by native by a Rendering Worker thread to update the window position
* @hide
*/
- public final void updateWindowPosition_renderWorker(long frameNumber,
+ public final void updateSurfacePosition_renderWorker(long frameNumber,
int left, int top, int right, int bottom) {
- IWindowSession session = mSession;
- MyWindow window = mWindow;
- if (session == null || window == null) {
- // Guess we got detached, that sucks
+ if (mSurfaceControl == null) {
return;
}
// TODO: This is teensy bit racey in that a brand new SurfaceView moving on
@@ -726,35 +705,29 @@ public class SurfaceView extends View {
}
try {
if (DEBUG) {
- Log.d(TAG, String.format("%d updateWindowPosition RenderWorker, frameNr = %d, " +
+ Log.d(TAG, String.format("%d updateSurfacePosition RenderWorker, frameNr = %d, " +
"postion = [%d, %d, %d, %d]", System.identityHashCode(this),
frameNumber, left, top, right, bottom));
}
- // Just using mRTLastReportedPosition as a dummy rect here
- session.repositionChild(window, left, top, right, bottom,
- frameNumber,
- mRTLastReportedPosition);
- // Now overwrite mRTLastReportedPosition with our values
mRTLastReportedPosition.set(left, top, right, bottom);
- } catch (RemoteException ex) {
+ setParentSpaceRectangle(mRTLastReportedPosition, frameNumber);
+ // Now overwrite mRTLastReportedPosition with our values
+ } catch (Exception ex) {
Log.e(TAG, "Exception from repositionChild", ex);
}
}
/**
- * Called by native on RenderThread to notify that the window is no longer in the
+ * Called by native on RenderThread to notify that the view is no longer in the
* draw tree. UI thread is blocked at this point.
* @hide
*/
- public final void windowPositionLost_uiRtSync(long frameNumber) {
+ public final void surfacePositionLost_uiRtSync(long frameNumber) {
if (DEBUG) {
Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
System.identityHashCode(this), frameNumber));
}
- IWindowSession session = mSession;
- MyWindow window = mWindow;
- if (session == null || window == null) {
- // We got detached prior to receiving this, abort
+ if (mSurfaceControl == null) {
return;
}
if (mRtHandlingPositionUpdates) {
@@ -763,19 +736,14 @@ public class SurfaceView extends View {
// safely access other member variables at this time.
// So do what the UI thread would have done if RT wasn't handling position
// updates.
- mTmpRect.set(mLayout.x, mLayout.y,
- mLayout.x + mLayout.width,
- mLayout.y + mLayout.height);
-
- if (!mTmpRect.isEmpty() && !mTmpRect.equals(mRTLastReportedPosition)) {
+ if (!mScreenRect.isEmpty() && !mScreenRect.equals(mRTLastReportedPosition)) {
try {
- if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition, " +
+ if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition, " +
"postion = [%d, %d, %d, %d]", System.identityHashCode(this),
- mTmpRect.left, mTmpRect.top,
- mTmpRect.right, mTmpRect.bottom));
- session.repositionChild(window, mTmpRect.left, mTmpRect.top,
- mTmpRect.right, mTmpRect.bottom, frameNumber, mWinFrame);
- } catch (RemoteException ex) {
+ mScreenRect.left, mScreenRect.top,
+ mScreenRect.right, mScreenRect.bottom));
+ setParentSpaceRectangle(mScreenRect, frameNumber);
+ } catch (Exception ex) {
Log.e(TAG, "Exception from relayout", ex);
}
}
@@ -792,10 +760,6 @@ public class SurfaceView extends View {
return callbacks;
}
- void handleGetNewSurface() {
- updateWindow();
- }
-
/**
* Check to see if the surface has fixed size dimensions or if the surface's
* dimensions are dimensions are dependent on its current layout.
@@ -807,65 +771,8 @@ public class SurfaceView extends View {
return (mRequestedWidth != -1 || mRequestedHeight != -1);
}
- private static class MyWindow extends BaseIWindow {
- private final WeakReference<SurfaceView> mSurfaceView;
-
- public MyWindow(SurfaceView surfaceView) {
- mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
- }
-
- @Override
- public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
- Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
- Configuration newConfig, Rect backDropRect, boolean forceLayout,
- boolean alwaysConsumeNavBar, int displayId) {
- SurfaceView surfaceView = mSurfaceView.get();
- if (surfaceView != null) {
- if (DEBUG) Log.v(TAG, surfaceView + " got resized: w=" + frame.width()
- + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight);
- surfaceView.mSurfaceLock.lock();
- try {
- if (reportDraw) {
- surfaceView.mUpdateWindowNeeded = true;
- surfaceView.mReportDrawNeeded = true;
- surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
- } else if (surfaceView.mWinFrame.width() != frame.width()
- || surfaceView.mWinFrame.height() != frame.height()
- || forceLayout) {
- surfaceView.mUpdateWindowNeeded = true;
- surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
- }
- } finally {
- surfaceView.mSurfaceLock.unlock();
- }
- }
- }
-
- @Override
- public void dispatchAppVisibility(boolean visible) {
- // The point of SurfaceView is to let the app control the surface.
- }
-
- @Override
- public void dispatchGetNewSurface() {
- SurfaceView surfaceView = mSurfaceView.get();
- if (surfaceView != null) {
- Message msg = surfaceView.mHandler.obtainMessage(GET_NEW_SURFACE_MSG);
- surfaceView.mHandler.sendMessage(msg);
- }
- }
-
- @Override
- public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
- Log.w("SurfaceView", "Unexpected focus in surface: focus=" + hasFocus + ", touchEnabled=" + touchEnabled);
- }
-
- @Override
- public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
- }
-
- int mCurWidth = -1;
- int mCurHeight = -1;
+ private boolean isAboveParent() {
+ return mSubLayer >= 0;
}
private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
@@ -913,15 +820,14 @@ public class SurfaceView extends View {
@Override
public void setFormat(int format) {
-
// for backward compatibility reason, OPAQUE always
// means 565 for SurfaceView
if (format == PixelFormat.OPAQUE)
format = PixelFormat.RGB_565;
mRequestedFormat = format;
- if (mWindow != null) {
- updateWindow();
+ if (mSurfaceControl != null) {
+ updateSurface();
}
}
@@ -982,10 +888,10 @@ public class SurfaceView extends View {
mSurfaceLock.lock();
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Locking canvas... stopped="
- + mDrawingStopped + ", win=" + mWindow);
+ + mDrawingStopped + ", surfaceControl=" + mSurfaceControl);
Canvas c = null;
- if (!mDrawingStopped && mWindow != null) {
+ if (!mDrawingStopped && mSurfaceControl != null) {
try {
if (hardware) {
c = mSurface.lockHardwareCanvas();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 20d960fff661..f9863b0a6761 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2632,6 +2632,14 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ private void onDrawFinished() {
+ try {
+ mWindowSession.finishDrawing(mWindow);
+ } catch (RemoteException e) {
+ // Have fun!
+ }
+ }
+
private void performDraw() {
if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
return;
@@ -2682,7 +2690,7 @@ public final class ViewRootImpl implements ViewParent,
}
if (mSurfaceHolder != null && mSurface.isValid()) {
- SurfaceCallbackHelper sch = new SurfaceCallbackHelper(mWindowSession, mWindow);
+ SurfaceCallbackHelper sch = new SurfaceCallbackHelper(this::onDrawFinished);
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
diff --git a/core/java/com/android/internal/view/SurfaceCallbackHelper.java b/core/java/com/android/internal/view/SurfaceCallbackHelper.java
index 5b6a82cf1c43..507b673ec279 100644
--- a/core/java/com/android/internal/view/SurfaceCallbackHelper.java
+++ b/core/java/com/android/internal/view/SurfaceCallbackHelper.java
@@ -17,14 +17,11 @@
package com.android.internal.view;
import android.os.RemoteException;
-import android.view.IWindow;
-import android.view.IWindowSession;
import android.view.Surface;
import android.view.SurfaceHolder;
public class SurfaceCallbackHelper {
- IWindowSession mSession;
- IWindow.Stub mWindow;
+ Runnable mRunnable;
int mFinishDrawingCollected = 0;
int mFinishDrawingExpected = 0;
@@ -37,26 +34,18 @@ public class SurfaceCallbackHelper {
if (mFinishDrawingCollected < mFinishDrawingExpected) {
return;
}
- try {
- mSession.finishDrawing(mWindow);
- } catch (RemoteException e) {
- }
+ mRunnable.run();
}
}
};
- public SurfaceCallbackHelper(IWindowSession session,
- IWindow.Stub window) {
- mSession = session;
- mWindow = window;
+ public SurfaceCallbackHelper(Runnable callbacksCollected) {
+ mRunnable = callbacksCollected;
}
public void dispatchSurfaceRedrawNeededAsync(SurfaceHolder holder, SurfaceHolder.Callback callbacks[]) {
if (callbacks == null || callbacks.length == 0) {
- try {
- mSession.finishDrawing(mWindow);
- } catch (RemoteException e) {
- }
+ mRunnable.run();
return;
}
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index f221392f16bd..edcbb3f783c3 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -627,9 +627,9 @@ static const JNINativeMethod gMethods[] = {
int register_android_view_RenderNode(JNIEnv* env) {
jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
- "updateWindowPosition_renderWorker", "(JIIII)V");
+ "updateSurfacePosition_renderWorker", "(JIIII)V");
gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz,
- "windowPositionLost_uiRtSync", "(J)V");
+ "surfacePositionLost_uiRtSync", "(J)V");
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index a81901df9a1b..be86f5c6b8ab 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -693,7 +693,6 @@ static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject
return JNI_TRUE;
}
-
static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong nativeObject,
jobject handleObject, jlong frameNumber) {
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
@@ -702,6 +701,27 @@ static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong nativeO
ctrl->deferTransactionUntil(handle, frameNumber);
}
+static void nativeDeferTransactionUntilSurface(JNIEnv* env, jclass clazz, jlong nativeObject,
+ jobject surfaceObject, jlong frameNumber) {
+ auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ sp<Surface> barrier = reinterpret_cast<Surface *>(surfaceObject);
+
+ ctrl->deferTransactionUntil(barrier, frameNumber);
+}
+
+static void nativeReparentChildren(JNIEnv* env, jclass clazz, jlong nativeObject,
+ jobject newParentObject) {
+ auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ sp<IBinder> handle = ibinderForJavaObject(env, newParentObject);
+
+ ctrl->reparentChildren(handle);
+}
+
+static void nativeSeverChildren(JNIEnv* env, jclass clazz, jlong nativeObject) {
+ auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ ctrl->detachChildren();
+}
+
static void nativeSetOverrideScalingMode(JNIEnv* env, jclass clazz, jlong nativeObject,
jint scalingMode) {
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
@@ -824,6 +844,12 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetDisplayPowerMode },
{"nativeDeferTransactionUntil", "(JLandroid/os/IBinder;J)V",
(void*)nativeDeferTransactionUntil },
+ {"nativeDeferTransactionUntilSurface", "(JJJ)V",
+ (void*)nativeDeferTransactionUntilSurface },
+ {"nativeReparentChildren", "(JLandroid/os/IBinder;)V",
+ (void*)nativeReparentChildren } ,
+ {"nativeSeverChildren", "(J)V",
+ (void*)nativeSeverChildren } ,
{"nativeSetOverrideScalingMode", "(JI)V",
(void*)nativeSetOverrideScalingMode },
{"nativeGetHandle", "(J)Landroid/os/IBinder;",
diff --git a/core/jni/android_view_SurfaceSession.cpp b/core/jni/android_view_SurfaceSession.cpp
index dad6958560c0..508d89795569 100644
--- a/core/jni/android_view_SurfaceSession.cpp
+++ b/core/jni/android_view_SurfaceSession.cpp
@@ -24,6 +24,7 @@
#include <utils/RefBase.h>
#include <gui/SurfaceComposerClient.h>
+#include <gui/Surface.h>
namespace android {
@@ -45,6 +46,13 @@ static jlong nativeCreate(JNIEnv* env, jclass clazz) {
return reinterpret_cast<jlong>(client);
}
+static jlong nativeCreateScoped(JNIEnv* env, jclass clazz, jlong surfaceObject) {
+ Surface *parent = reinterpret_cast<Surface*>(surfaceObject);
+ SurfaceComposerClient* client = new SurfaceComposerClient(parent->getIGraphicBufferProducer());
+ client->incStrong((void*)nativeCreate);
+ return reinterpret_cast<jlong>(client);
+}
+
static void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
SurfaceComposerClient* client = reinterpret_cast<SurfaceComposerClient*>(ptr);
client->decStrong((void*)nativeCreate);
@@ -55,11 +63,12 @@ static void nativeKill(JNIEnv* env, jclass clazz, jlong ptr) {
client->dispose();
}
-
static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeCreate", "()J",
(void*)nativeCreate },
+ { "nativeCreateScoped", "(J)J",
+ (void*)nativeCreateScoped },
{ "nativeDestroy", "(J)V",
(void*)nativeDestroy },
{ "nativeKill", "(J)V",
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index aee9d38e0a27..e5af35711311 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -776,8 +776,8 @@ public class TvView extends ViewGroup {
mSurface = null;
mSurfaceView = new SurfaceView(getContext(), mAttrs, mDefStyleAttr) {
@Override
- protected void updateWindow() {
- super.updateWindow();
+ protected void updateSurface() {
+ super.updateSurface();
relayoutSessionOverlayView();
}};
// The surface view's content should be treated as secure all the time.
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 22630428ad01..379e3cea405e 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -762,6 +762,16 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (canFreezeBounds()) {
freezeBounds();
}
+
+ // In the process of tearing down before relaunching, the app will
+ // try and clean up it's child surfaces. We need to prevent this from
+ // happening, so we sever the children, transfering their ownership
+ // from the client it-self to the parent surface (owned by us).
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState w = mChildren.get(i);
+ w.mWinAnimator.detachChildren();
+ }
+
mPendingRelaunchCount++;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2a4dfc444fe2..eb10f0c2978c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2199,6 +2199,15 @@ public class WindowManagerService extends IWindowManager.Stub
if (mAccessibilityController != null && win.getDisplayId() == DEFAULT_DISPLAY) {
mAccessibilityController.onWindowTransitionLocked(win, transit);
}
+
+ // When we start the exit animation we take the Surface from the client
+ // so it will stop perturbing it. We need to likewise takeaway the SurfaceFlinger
+ // side child surfaces, so they will remain preserved in their current state
+ // (rather than be cleaned up immediately by the app code).
+ SurfaceControl.openTransaction();
+ winAnimator.detachChildren();
+ SurfaceControl.closeTransaction();
+
return focusMayChange;
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 98598e1654dc..4b7133836db8 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -566,6 +566,20 @@ class WindowStateAnimator {
if (!mDestroyPreservedSurfaceUponRedraw) {
return;
}
+ if (mSurfaceController != null) {
+ if (mPendingDestroySurface != null) {
+ // If we are preserving a surface but we aren't relaunching that means
+ // we are just doing an in-place switch. In that case any SurfaceFlinger side
+ // 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) {
+ SurfaceControl.openTransaction();
+ mPendingDestroySurface.reparentChildrenInTransaction(mSurfaceController);
+ SurfaceControl.closeTransaction();
+ }
+ }
+ }
+
destroyDeferredSurfaceLocked();
mDestroyPreservedSurfaceUponRedraw = false;
}
@@ -1965,4 +1979,10 @@ class WindowStateAnimator {
}
return mForceScaleUntilResize;
}
+
+ void detachChildren() {
+ if (mSurfaceController != null) {
+ mSurfaceController.detachChildren();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index f8e74284fafd..f7d3343831bf 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -135,6 +135,20 @@ class WindowSurfaceController {
}
}
+ void reparentChildrenInTransaction(WindowSurfaceController other) {
+ if (SHOW_TRANSACTIONS) Slog.i(TAG, "REPARENT from: " + this + " to: " + other);
+ if ((mSurfaceControl != null) && (other.mSurfaceControl != null)) {
+ mSurfaceControl.reparentChildren(other.getHandle());
+ }
+ }
+
+ void detachChildren() {
+ if (SHOW_TRANSACTIONS) Slog.i(TAG, "SEVER CHILDREN");
+ if (mSurfaceControl != null) {
+ mSurfaceControl.detachChildren();
+ }
+ }
+
void hideInTransaction(String reason) {
if (SHOW_TRANSACTIONS) logSurface("HIDE ( " + reason + " )", null);
mHiddenForOtherReasons = true;