DO NOT MERGE: Fix ActivityView surface can't visible for ActivityViewTest

am: dc9b319039

Change-Id: I99a0158a49b3f7d6e02f2c71a94526b7af8f3ce4
This commit is contained in:
lumark
2019-08-09 07:48:28 -07:00
committed by android-build-merger
3 changed files with 207 additions and 33 deletions

View File

@@ -120,7 +120,10 @@ public class ActivityView extends ViewGroup {
mActivityTaskManager = ActivityTaskManager.getService();
mSurfaceView = new SurfaceView(context);
mSurfaceView.setAlpha(0f);
// Since ActivityView#getAlpha has been overridden, we should use parent class's alpha
// as master to synchronize surface view's alpha value.
mSurfaceView.setAlpha(super.getAlpha());
mSurfaceView.setUseAlpha();
mSurfaceCallback = new SurfaceCallback();
mSurfaceView.getHolder().addCallback(mSurfaceCallback);
addView(mSurfaceView);
@@ -347,9 +350,20 @@ public class ActivityView extends ViewGroup {
mSurfaceView.layout(0 /* left */, 0 /* top */, r - l /* right */, b - t /* bottom */);
}
/**
* Sets the alpha value when the content of {@link SurfaceView} needs to show or hide.
* <p>Note: The surface view may ignore the alpha value in some cases. Refer to
* {@link SurfaceView#setAlpha} for more details.
*
* @param alpha The opacity of the view.
*/
@Override
public void setAlpha(float alpha) {
mSurfaceView.setAlpha(alpha);
super.setAlpha(alpha);
if (mSurfaceView != null) {
mSurfaceView.setAlpha(alpha);
}
}
@Override

View File

@@ -100,6 +100,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
@@ -126,6 +127,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();
final Configuration mConfiguration = new Configuration();
@@ -173,6 +175,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;
@@ -200,6 +205,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
private int mPendingReportDraws;
private SurfaceControl.Transaction mRtTransaction = new SurfaceControl.Transaction();
private SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
public SurfaceView(Context context) {
this(context, null);
@@ -288,6 +294,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;
@@ -337,11 +489,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
mRequestedVisible = false;
updateSurface();
if (mSurfaceControl != null) {
mSurfaceControl.remove();
}
mSurfaceControl = null;
releaseSurfaces();
mHaveFrame = false;
super.onDetachedFromWindow();
@@ -510,15 +658,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;
@@ -532,23 +671,34 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
}
private void releaseSurfaces() {
if (mSurfaceControl != null) {
mSurfaceControl.remove();
mSurfaceControl = null;
}
if (mBackgroundControl != null) {
mBackgroundControl.remove();
mBackgroundControl = null;
synchronized (mSurfaceControlLock) {
if (mSurfaceControl != null) {
mTmpTransaction.remove(mSurfaceControl);
mSurfaceControl = null;
}
if (mBackgroundControl != null) {
mTmpTransaction.remove(mBackgroundControl);
mBackgroundControl = null;
}
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;
}
@@ -562,20 +712,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]));
@@ -597,7 +752,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
mTranslator.translateRectInAppWindowToScreen(mScreenRect);
}
final Rect surfaceInsets = getParentSurfaceInsets();
final Rect surfaceInsets = viewRoot.mWindowAttributes.surfaceInsets;
mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);
if (creating) {
@@ -646,6 +801,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
@@ -788,7 +947,6 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
mIsCreating = false;
if (mSurfaceControl != null && !mSurfaceCreated) {
mSurface.release();
releaseSurfaces();
}
}
@@ -828,10 +986,13 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) {
try {
if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition UI, " +
"postion = [%d, %d, %d, %d]", System.identityHashCode(this),
mScreenRect.left, mScreenRect.top,
mScreenRect.right, mScreenRect.bottom));
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);
@@ -884,7 +1045,6 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
if (mViewVisibility) {
mRtTransaction.show(surface);
}
}
private void setParentSpaceRectangle(Rect position, long frameNumber) {
@@ -925,7 +1085,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, "
+ "postion = [%d, %d, %d, %d]",

View File

@@ -182,7 +182,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
mActivityView = new ActivityView(mContext, null /* attrs */, 0 /* defStyle */,
true /* singleTaskInstance */);
// Set ActivityView's alpha value as zero, since there is no view content to be shown.
setContentVisibility(false);
addView(mActivityView);