Loading core/java/android/app/ActivityView.java +1 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,7 @@ public class ActivityView extends ViewGroup { mActivityTaskManager = ActivityTaskManager.getService(); mSurfaceView = new SurfaceView(context); mSurfaceView.setUseAlpha(); mSurfaceView.setAlpha(0f); mSurfaceCallback = new SurfaceCallback(); mSurfaceView.getHolder().addCallback(mSurfaceCallback); Loading core/java/android/view/SurfaceView.java +189 −31 Original line number Diff line number Diff line Loading @@ -99,6 +99,7 @@ import java.util.concurrent.locks.ReentrantLock; public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback { private static final String TAG = "SurfaceView"; private static final boolean DEBUG = false; private static final boolean DEBUG_POSITION = false; @UnsupportedAppUsage final ArrayList<SurfaceHolder.Callback> mCallbacks = new ArrayList<>(); Loading @@ -124,6 +125,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb // we need to preserve the old one until the new one has drawn. SurfaceControl mDeferredDestroySurfaceControl; SurfaceControl mBackgroundControl; final Object mSurfaceControlLock = new Object(); final Rect mTmpRect = new Rect(); Paint mRoundedViewportPaint; Loading Loading @@ -161,6 +163,9 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb @UnsupportedAppUsage int mRequestedFormat = PixelFormat.RGB_565; boolean mUseAlpha = false; float mSurfaceAlpha = 1f; @UnsupportedAppUsage boolean mHaveFrame = false; boolean mSurfaceCreated = false; Loading Loading @@ -276,6 +281,152 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb updateSurface(); } /** * Make alpha value of this view reflect onto the surface. This can only be called from at most * one SurfaceView within a view tree. * * <p class="note"><strong>Note:</strong> Alpha value of the view is ignored and the underlying * surface is rendered opaque by default.</p> * * @hide */ public void setUseAlpha() { if (!mUseAlpha) { mUseAlpha = true; updateSurfaceAlpha(); } } @Override public void setAlpha(float alpha) { // Sets the opacity of the view to a value, where 0 means the view is completely transparent // and 1 means the view is completely opaque. // // Note: Alpha value of this view is ignored by default. To enable alpha blending, you need // to call setUseAlpha() as well. // This view doesn't support translucent opacity if the view is located z-below, since the // logic to punch a hole in the view hierarchy cannot handle such case. See also // #clearSurfaceViewPort(Canvas) if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " setAlpha: mUseAlpha = " + mUseAlpha + " alpha=" + alpha); } super.setAlpha(alpha); updateSurfaceAlpha(); } private float getFixedAlpha() { // Compute alpha value to be set on the underlying surface. final float alpha = getAlpha(); return mUseAlpha && (mSubLayer > 0 || alpha == 0f) ? alpha : 1f; } private void updateSurfaceAlpha() { if (!mUseAlpha) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha: setUseAlpha() is not called, ignored."); } return; } final float viewAlpha = getAlpha(); if (mSubLayer < 0 && 0f < viewAlpha && viewAlpha < 1f) { Log.w(TAG, System.identityHashCode(this) + " updateSurfaceAlpha:" + " translucent color is not supported for a surface placed z-below."); } if (!mHaveFrame) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha: has no surface."); } return; } final ViewRootImpl viewRoot = getViewRootImpl(); if (viewRoot == null) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha: ViewRootImpl not available."); } return; } if (mSurfaceControl == null) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + "updateSurfaceAlpha:" + " surface is not yet created, or already released."); } return; } final Surface parent = viewRoot.mSurface; if (parent == null || !parent.isValid()) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha: ViewRootImpl has no valid surface"); } return; } final float alpha = getFixedAlpha(); if (alpha != mSurfaceAlpha) { if (isHardwareAccelerated()) { /* * Schedule a callback that reflects an alpha value onto the underlying surfaces. * This gets called on a RenderThread worker thread, so members accessed here must * be protected by a lock. */ viewRoot.registerRtFrameCallback(frame -> { try { final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); synchronized (mSurfaceControlLock) { if (!parent.isValid()) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha RT:" + " ViewRootImpl has no valid surface"); } return; } if (mSurfaceControl == null) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + "updateSurfaceAlpha RT:" + " mSurfaceControl has already released"); } return; } if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha RT: set alpha=" + alpha); } t.setAlpha(mSurfaceControl, alpha); t.deferTransactionUntilSurface(mSurfaceControl, parent, frame); } // It's possible that mSurfaceControl is released in the UI thread before // the transaction completes. If that happens, an exception is thrown, which // must be caught immediately. t.apply(); } catch (Exception e) { Log.e(TAG, System.identityHashCode(this) + "updateSurfaceAlpha RT: Exception during surface transaction", e); } }); damageInParent(); } else { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha: set alpha=" + alpha); } SurfaceControl.openTransaction(); try { mSurfaceControl.setAlpha(alpha); } finally { SurfaceControl.closeTransaction(); } } mSurfaceAlpha = alpha; } } private void performDrawFinished() { if (mPendingReportDraws > 0) { mDrawFinished = true; Loading Loading @@ -326,11 +477,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mRequestedVisible = false; updateSurface(); if (mSurfaceControl != null) { mTmpTransaction.remove(mSurfaceControl).apply(); } mSurfaceControl = null; releaseSurfaces(); mHaveFrame = false; super.onDetachedFromWindow(); Loading Loading @@ -499,15 +646,6 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb } } private Rect getParentSurfaceInsets() { final ViewRootImpl root = getViewRootImpl(); if (root == null) { return null; } else { return root.mWindowAttributes.surfaceInsets; } } private void updateBackgroundVisibilityInTransaction(SurfaceControl viewRoot) { if (mBackgroundControl == null) { return; Loading @@ -521,6 +659,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb } private void releaseSurfaces() { synchronized (mSurfaceControlLock) { if (mSurfaceControl != null) { mTmpTransaction.remove(mSurfaceControl); mSurfaceControl = null; Loading @@ -531,14 +670,23 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb } mTmpTransaction.apply(); } mSurfaceAlpha = 1f; } /** @hide */ protected void updateSurface() { if (!mHaveFrame) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurface: has no frame"); } return; } ViewRootImpl viewRoot = getViewRootImpl(); if (viewRoot == null || viewRoot.mSurface == null || !viewRoot.mSurface.isValid()) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurface: no valid surface"); } return; } Loading @@ -552,20 +700,25 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb int myHeight = mRequestedHeight; if (myHeight <= 0) myHeight = getHeight(); final float alpha = getFixedAlpha(); final boolean formatChanged = mFormat != mRequestedFormat; final boolean visibleChanged = mVisible != mRequestedVisible; final boolean alphaChanged = mSurfaceAlpha != alpha; final boolean creating = (mSurfaceControl == null || formatChanged || visibleChanged) && mRequestedVisible; final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight; final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility; boolean redrawNeeded = false; if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) { if (creating || formatChanged || sizeChanged || visibleChanged || (mUseAlpha && alphaChanged) || windowVisibleChanged) { getLocationInWindow(mLocation); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Changes: creating=" + creating + " format=" + formatChanged + " size=" + sizeChanged + " visible=" + visibleChanged + " alpha=" + alphaChanged + " mUseAlpha=" + mUseAlpha + " visible=" + visibleChanged + " left=" + (mWindowSpaceLeft != mLocation[0]) + " top=" + (mWindowSpaceTop != mLocation[1])); Loading @@ -587,7 +740,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb translator.translateRectInAppWindowToScreen(mScreenRect); } final Rect surfaceInsets = getParentSurfaceInsets(); final Rect surfaceInsets = viewRoot.mWindowAttributes.surfaceInsets; mScreenRect.offset(surfaceInsets.left, surfaceInsets.top); if (creating) { Loading Loading @@ -636,6 +789,10 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mSurfaceControl.hide(); } updateBackgroundVisibilityInTransaction(viewRoot.getSurfaceControl()); if (mUseAlpha) { mSurfaceControl.setAlpha(alpha); mSurfaceAlpha = alpha; } // While creating the surface, we will set it's initial // geometry. Outside of that though, we should generally Loading Loading @@ -778,7 +935,6 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mIsCreating = false; if (mSurfaceControl != null && !mSurfaceCreated) { mSurface.release(); releaseSurfaces(); } } Loading Loading @@ -818,10 +974,13 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) { try { if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition UI, " + "position = [%d, %d, %d, %d]", System.identityHashCode(this), if (DEBUG_POSITION) { Log.d(TAG, String.format("%d updateSurfacePosition UI, " + "position = [%d, %d, %d, %d]", System.identityHashCode(this), mScreenRect.left, mScreenRect.top, mScreenRect.right, mScreenRect.bottom)); } setParentSpaceRectangle(mScreenRect, -1); } catch (Exception ex) { Log.e(TAG, "Exception configuring surface", ex); Loading Loading @@ -872,7 +1031,6 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb if (mViewVisibility) { mRtTransaction.show(surface); } } private void setParentSpaceRectangle(Rect position, long frameNumber) { Loading Loading @@ -913,7 +1071,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb return; } try { if (DEBUG) { if (DEBUG_POSITION) { Log.d(TAG, String.format( "%d updateSurfacePosition RenderWorker, frameNr = %d, " + "position = [%d, %d, %d, %d]", Loading Loading
core/java/android/app/ActivityView.java +1 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,7 @@ public class ActivityView extends ViewGroup { mActivityTaskManager = ActivityTaskManager.getService(); mSurfaceView = new SurfaceView(context); mSurfaceView.setUseAlpha(); mSurfaceView.setAlpha(0f); mSurfaceCallback = new SurfaceCallback(); mSurfaceView.getHolder().addCallback(mSurfaceCallback); Loading
core/java/android/view/SurfaceView.java +189 −31 Original line number Diff line number Diff line Loading @@ -99,6 +99,7 @@ import java.util.concurrent.locks.ReentrantLock; public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback { private static final String TAG = "SurfaceView"; private static final boolean DEBUG = false; private static final boolean DEBUG_POSITION = false; @UnsupportedAppUsage final ArrayList<SurfaceHolder.Callback> mCallbacks = new ArrayList<>(); Loading @@ -124,6 +125,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb // we need to preserve the old one until the new one has drawn. SurfaceControl mDeferredDestroySurfaceControl; SurfaceControl mBackgroundControl; final Object mSurfaceControlLock = new Object(); final Rect mTmpRect = new Rect(); Paint mRoundedViewportPaint; Loading Loading @@ -161,6 +163,9 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb @UnsupportedAppUsage int mRequestedFormat = PixelFormat.RGB_565; boolean mUseAlpha = false; float mSurfaceAlpha = 1f; @UnsupportedAppUsage boolean mHaveFrame = false; boolean mSurfaceCreated = false; Loading Loading @@ -276,6 +281,152 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb updateSurface(); } /** * Make alpha value of this view reflect onto the surface. This can only be called from at most * one SurfaceView within a view tree. * * <p class="note"><strong>Note:</strong> Alpha value of the view is ignored and the underlying * surface is rendered opaque by default.</p> * * @hide */ public void setUseAlpha() { if (!mUseAlpha) { mUseAlpha = true; updateSurfaceAlpha(); } } @Override public void setAlpha(float alpha) { // Sets the opacity of the view to a value, where 0 means the view is completely transparent // and 1 means the view is completely opaque. // // Note: Alpha value of this view is ignored by default. To enable alpha blending, you need // to call setUseAlpha() as well. // This view doesn't support translucent opacity if the view is located z-below, since the // logic to punch a hole in the view hierarchy cannot handle such case. See also // #clearSurfaceViewPort(Canvas) if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " setAlpha: mUseAlpha = " + mUseAlpha + " alpha=" + alpha); } super.setAlpha(alpha); updateSurfaceAlpha(); } private float getFixedAlpha() { // Compute alpha value to be set on the underlying surface. final float alpha = getAlpha(); return mUseAlpha && (mSubLayer > 0 || alpha == 0f) ? alpha : 1f; } private void updateSurfaceAlpha() { if (!mUseAlpha) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha: setUseAlpha() is not called, ignored."); } return; } final float viewAlpha = getAlpha(); if (mSubLayer < 0 && 0f < viewAlpha && viewAlpha < 1f) { Log.w(TAG, System.identityHashCode(this) + " updateSurfaceAlpha:" + " translucent color is not supported for a surface placed z-below."); } if (!mHaveFrame) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha: has no surface."); } return; } final ViewRootImpl viewRoot = getViewRootImpl(); if (viewRoot == null) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha: ViewRootImpl not available."); } return; } if (mSurfaceControl == null) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + "updateSurfaceAlpha:" + " surface is not yet created, or already released."); } return; } final Surface parent = viewRoot.mSurface; if (parent == null || !parent.isValid()) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha: ViewRootImpl has no valid surface"); } return; } final float alpha = getFixedAlpha(); if (alpha != mSurfaceAlpha) { if (isHardwareAccelerated()) { /* * Schedule a callback that reflects an alpha value onto the underlying surfaces. * This gets called on a RenderThread worker thread, so members accessed here must * be protected by a lock. */ viewRoot.registerRtFrameCallback(frame -> { try { final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); synchronized (mSurfaceControlLock) { if (!parent.isValid()) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha RT:" + " ViewRootImpl has no valid surface"); } return; } if (mSurfaceControl == null) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + "updateSurfaceAlpha RT:" + " mSurfaceControl has already released"); } return; } if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha RT: set alpha=" + alpha); } t.setAlpha(mSurfaceControl, alpha); t.deferTransactionUntilSurface(mSurfaceControl, parent, frame); } // It's possible that mSurfaceControl is released in the UI thread before // the transaction completes. If that happens, an exception is thrown, which // must be caught immediately. t.apply(); } catch (Exception e) { Log.e(TAG, System.identityHashCode(this) + "updateSurfaceAlpha RT: Exception during surface transaction", e); } }); damageInParent(); } else { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurfaceAlpha: set alpha=" + alpha); } SurfaceControl.openTransaction(); try { mSurfaceControl.setAlpha(alpha); } finally { SurfaceControl.closeTransaction(); } } mSurfaceAlpha = alpha; } } private void performDrawFinished() { if (mPendingReportDraws > 0) { mDrawFinished = true; Loading Loading @@ -326,11 +477,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mRequestedVisible = false; updateSurface(); if (mSurfaceControl != null) { mTmpTransaction.remove(mSurfaceControl).apply(); } mSurfaceControl = null; releaseSurfaces(); mHaveFrame = false; super.onDetachedFromWindow(); Loading Loading @@ -499,15 +646,6 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb } } private Rect getParentSurfaceInsets() { final ViewRootImpl root = getViewRootImpl(); if (root == null) { return null; } else { return root.mWindowAttributes.surfaceInsets; } } private void updateBackgroundVisibilityInTransaction(SurfaceControl viewRoot) { if (mBackgroundControl == null) { return; Loading @@ -521,6 +659,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb } private void releaseSurfaces() { synchronized (mSurfaceControlLock) { if (mSurfaceControl != null) { mTmpTransaction.remove(mSurfaceControl); mSurfaceControl = null; Loading @@ -531,14 +670,23 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb } mTmpTransaction.apply(); } mSurfaceAlpha = 1f; } /** @hide */ protected void updateSurface() { if (!mHaveFrame) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurface: has no frame"); } return; } ViewRootImpl viewRoot = getViewRootImpl(); if (viewRoot == null || viewRoot.mSurface == null || !viewRoot.mSurface.isValid()) { if (DEBUG) { Log.d(TAG, System.identityHashCode(this) + " updateSurface: no valid surface"); } return; } Loading @@ -552,20 +700,25 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb int myHeight = mRequestedHeight; if (myHeight <= 0) myHeight = getHeight(); final float alpha = getFixedAlpha(); final boolean formatChanged = mFormat != mRequestedFormat; final boolean visibleChanged = mVisible != mRequestedVisible; final boolean alphaChanged = mSurfaceAlpha != alpha; final boolean creating = (mSurfaceControl == null || formatChanged || visibleChanged) && mRequestedVisible; final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight; final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility; boolean redrawNeeded = false; if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) { if (creating || formatChanged || sizeChanged || visibleChanged || (mUseAlpha && alphaChanged) || windowVisibleChanged) { getLocationInWindow(mLocation); if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Changes: creating=" + creating + " format=" + formatChanged + " size=" + sizeChanged + " visible=" + visibleChanged + " alpha=" + alphaChanged + " mUseAlpha=" + mUseAlpha + " visible=" + visibleChanged + " left=" + (mWindowSpaceLeft != mLocation[0]) + " top=" + (mWindowSpaceTop != mLocation[1])); Loading @@ -587,7 +740,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb translator.translateRectInAppWindowToScreen(mScreenRect); } final Rect surfaceInsets = getParentSurfaceInsets(); final Rect surfaceInsets = viewRoot.mWindowAttributes.surfaceInsets; mScreenRect.offset(surfaceInsets.left, surfaceInsets.top); if (creating) { Loading Loading @@ -636,6 +789,10 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mSurfaceControl.hide(); } updateBackgroundVisibilityInTransaction(viewRoot.getSurfaceControl()); if (mUseAlpha) { mSurfaceControl.setAlpha(alpha); mSurfaceAlpha = alpha; } // While creating the surface, we will set it's initial // geometry. Outside of that though, we should generally Loading Loading @@ -778,7 +935,6 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb mIsCreating = false; if (mSurfaceControl != null && !mSurfaceCreated) { mSurface.release(); releaseSurfaces(); } } Loading Loading @@ -818,10 +974,13 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) { try { if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition UI, " + "position = [%d, %d, %d, %d]", System.identityHashCode(this), if (DEBUG_POSITION) { Log.d(TAG, String.format("%d updateSurfacePosition UI, " + "position = [%d, %d, %d, %d]", System.identityHashCode(this), mScreenRect.left, mScreenRect.top, mScreenRect.right, mScreenRect.bottom)); } setParentSpaceRectangle(mScreenRect, -1); } catch (Exception ex) { Log.e(TAG, "Exception configuring surface", ex); Loading Loading @@ -872,7 +1031,6 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb if (mViewVisibility) { mRtTransaction.show(surface); } } private void setParentSpaceRectangle(Rect position, long frameNumber) { Loading Loading @@ -913,7 +1071,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb return; } try { if (DEBUG) { if (DEBUG_POSITION) { Log.d(TAG, String.format( "%d updateSurfacePosition RenderWorker, frameNr = %d, " + "position = [%d, %d, %d, %d]", Loading