Merge "Modify SurfaceView to use SurfaceFlinger child surfaces."
This commit is contained in:
committed by
Android (Google) Code Review
commit
cfdfd997bd
@@ -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);
|
||||
@@ -418,7 +423,23 @@ public class SurfaceControl {
|
||||
}
|
||||
|
||||
public void deferTransactionUntil(IBinder handle, long frame) {
|
||||
nativeDeferTransactionUntil(mNativeObject, handle, frame);
|
||||
if (frame > 0) {
|
||||
nativeDeferTransactionUntil(mNativeObject, handle, frame);
|
||||
}
|
||||
}
|
||||
|
||||
public void deferTransactionUntil(Surface barrier, long frame) {
|
||||
if (frame > 0) {
|
||||
nativeDeferTransactionUntilSurface(mNativeObject, barrier.mNativeObject, frame);
|
||||
}
|
||||
}
|
||||
|
||||
public void reparentChildren(IBinder newParentHandle) {
|
||||
nativeReparentChildren(mNativeObject, newParentHandle);
|
||||
}
|
||||
|
||||
public void detachChildren() {
|
||||
nativeSeverChildren(mNativeObject);
|
||||
}
|
||||
|
||||
public void setOverrideScalingMode(int scalingMode) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 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();
|
||||
final Rect mScreenRect = new Rect();
|
||||
SurfaceSession mSurfaceSession;
|
||||
|
||||
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;
|
||||
}
|
||||
mSession = null;
|
||||
mLayout.token = null;
|
||||
|
||||
updateSurface();
|
||||
if (mSurfaceControl != null) {
|
||||
mSurfaceControl.destroy();
|
||||
}
|
||||
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,32 @@ 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;
|
||||
private Rect getParentSurfaceInsets() {
|
||||
final ViewRootImpl root = getViewRootImpl();
|
||||
if (root == null) {
|
||||
return null;
|
||||
} else {
|
||||
return root.mWindowAttributes.surfaceInsets;
|
||||
}
|
||||
}
|
||||
|
||||
/** @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 +433,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 +455,77 @@ 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;
|
||||
final Rect surfaceInsets = getParentSurfaceInsets();
|
||||
mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);
|
||||
|
||||
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 +539,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 +570,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 +606,55 @@ 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);
|
||||
getLocationInSurface(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,20 +662,43 @@ 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
|
||||
// its 2nd frame if RenderThread is running slowly could potentially see
|
||||
// this as false, enter the branch, get pre-empted, then this comes along
|
||||
@@ -726,35 +716,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 +747,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 +771,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 +782,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 +831,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 +899,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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user