diff options
| author | 2017-03-01 17:49:23 +0000 | |
|---|---|---|
| committer | 2017-03-01 17:49:27 +0000 | |
| commit | 0e06ccf488bb7744709b8f3421f3a5a2f5ae69f7 (patch) | |
| tree | 5393e32af701a61c63bfb72f8ecbf77f9dc0ad08 | |
| parent | e2a3c4e8c4d902213726039c701484c6c1c721f5 (diff) | |
| parent | 693f3432ae77d1fcfaaf9d168de861192aacb4c4 (diff) | |
Merge "Modify SurfaceView to use SurfaceFlinger child surfaces."
| -rw-r--r-- | core/java/android/view/SurfaceControl.java | 17 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceSession.java | 5 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 440 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 10 | ||||
| -rw-r--r-- | core/java/com/android/internal/view/SurfaceCallbackHelper.java | 21 | ||||
| -rw-r--r-- | core/jni/android_view_RenderNode.cpp | 4 | ||||
| -rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 28 | ||||
| -rw-r--r-- | core/jni/android_view_SurfaceSession.cpp | 11 | ||||
| -rw-r--r-- | media/java/android/media/tv/TvView.java | 4 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/AppWindowToken.java | 10 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 9 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowStateAnimator.java | 20 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowSurfaceController.java | 14 |
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; |