Merge "Handle reperenting of InlineContentView" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f8b9ddea71
@@ -5506,6 +5506,19 @@ package android.widget {
|
||||
|
||||
}
|
||||
|
||||
package android.widget.inline {
|
||||
|
||||
public class InlineContentView extends android.view.ViewGroup {
|
||||
method public void setChildSurfacePackageUpdater(@Nullable android.widget.inline.InlineContentView.SurfacePackageUpdater);
|
||||
}
|
||||
|
||||
public static interface InlineContentView.SurfacePackageUpdater {
|
||||
method public void getSurfacePackage(@NonNull java.util.function.Consumer<android.view.SurfaceControlViewHost.SurfacePackage>);
|
||||
method public void onSurfacePackageReleased();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.window {
|
||||
|
||||
public final class DisplayAreaInfo implements android.os.Parcelable {
|
||||
|
||||
@@ -63,8 +63,10 @@ import dalvik.system.CloseGuard;
|
||||
import libcore.util.NativeAllocationRegistry;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -226,24 +228,86 @@ public final class SurfaceControl implements Parcelable {
|
||||
private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject,
|
||||
int transformHint);
|
||||
|
||||
@Nullable
|
||||
@GuardedBy("sLock")
|
||||
private ArrayList<OnReparentListener> mReparentListeners;
|
||||
|
||||
/**
|
||||
* Listener to observe surface reparenting.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface OnReparentListener {
|
||||
|
||||
/**
|
||||
* Callback for reparenting surfaces.
|
||||
*
|
||||
* Important: You should only interact with the provided surface control
|
||||
* only if you have a contract with its owner to avoid them closing it
|
||||
* under you or vise versa.
|
||||
*
|
||||
* @param transaction The transaction that would commit reparenting.
|
||||
* @param parent The future parent surface.
|
||||
*/
|
||||
void onReparent(@NonNull Transaction transaction, @Nullable SurfaceControl parent);
|
||||
}
|
||||
|
||||
private final CloseGuard mCloseGuard = CloseGuard.get();
|
||||
private String mName;
|
||||
/**
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public long mNativeObject;
|
||||
private long mNativeHandle;
|
||||
|
||||
// TODO: Move this to native.
|
||||
private final Object mSizeLock = new Object();
|
||||
@GuardedBy("mSizeLock")
|
||||
// TODO: Move width/height to native and fix locking through out.
|
||||
private final Object mLock = new Object();
|
||||
@GuardedBy("mLock")
|
||||
private int mWidth;
|
||||
@GuardedBy("mSizeLock")
|
||||
@GuardedBy("mLock")
|
||||
private int mHeight;
|
||||
|
||||
private WeakReference<View> mLocalOwnerView;
|
||||
|
||||
static Transaction sGlobalTransaction;
|
||||
static long sTransactionNestCount = 0;
|
||||
|
||||
/**
|
||||
* Adds a reparenting listener.
|
||||
*
|
||||
* @param listener The listener.
|
||||
* @return Whether listener was added.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public boolean addOnReparentListener(@NonNull OnReparentListener listener) {
|
||||
synchronized (mLock) {
|
||||
if (mReparentListeners == null) {
|
||||
mReparentListeners = new ArrayList<>(1);
|
||||
}
|
||||
return mReparentListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a reparenting listener.
|
||||
*
|
||||
* @param listener The listener.
|
||||
* @return Whether listener was removed.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public boolean removeOnReparentListener(@NonNull OnReparentListener listener) {
|
||||
synchronized (mLock) {
|
||||
final boolean removed = mReparentListeners.remove(listener);
|
||||
if (mReparentListeners.isEmpty()) {
|
||||
mReparentListeners = null;
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
}
|
||||
|
||||
/* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
|
||||
|
||||
/**
|
||||
@@ -455,6 +519,7 @@ public final class SurfaceControl implements Parcelable {
|
||||
mName = other.mName;
|
||||
mWidth = other.mWidth;
|
||||
mHeight = other.mHeight;
|
||||
mLocalOwnerView = other.mLocalOwnerView;
|
||||
assignNativeObject(nativeCopyFromSurfaceControl(other.mNativeObject));
|
||||
}
|
||||
|
||||
@@ -553,6 +618,7 @@ public final class SurfaceControl implements Parcelable {
|
||||
private int mHeight;
|
||||
private int mFormat = PixelFormat.OPAQUE;
|
||||
private String mName;
|
||||
private WeakReference<View> mLocalOwnerView;
|
||||
private SurfaceControl mParent;
|
||||
private SparseIntArray mMetadata;
|
||||
|
||||
@@ -587,7 +653,8 @@ public final class SurfaceControl implements Parcelable {
|
||||
"Only buffer layers can set a valid buffer size.");
|
||||
}
|
||||
return new SurfaceControl(
|
||||
mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata);
|
||||
mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata,
|
||||
mLocalOwnerView);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,6 +668,27 @@ public final class SurfaceControl implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the local owner view for the surface. This view is only
|
||||
* valid in the same process and is not transferred in an IPC.
|
||||
*
|
||||
* Note: This is used for cases where we want to know the view
|
||||
* that manages the surface control while intercepting reparenting.
|
||||
* A specific example is InlineContentView which exposes is surface
|
||||
* control for reparenting as a way to implement clipping of several
|
||||
* InlineContentView instances within a certain area.
|
||||
*
|
||||
* @param view The owner view.
|
||||
* @return This builder.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setLocalOwnerView(@NonNull View view) {
|
||||
mLocalOwnerView = new WeakReference<>(view);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the initial size of the controlled surface's buffers in pixels.
|
||||
*
|
||||
@@ -858,7 +946,7 @@ public final class SurfaceControl implements Parcelable {
|
||||
* @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
|
||||
*/
|
||||
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
|
||||
SurfaceControl parent, SparseIntArray metadata)
|
||||
SurfaceControl parent, SparseIntArray metadata, WeakReference<View> localOwnerView)
|
||||
throws OutOfResourcesException, IllegalArgumentException {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("name must not be null");
|
||||
@@ -867,6 +955,7 @@ public final class SurfaceControl implements Parcelable {
|
||||
mName = name;
|
||||
mWidth = w;
|
||||
mHeight = h;
|
||||
mLocalOwnerView = localOwnerView;
|
||||
Parcel metaParcel = Parcel.obtain();
|
||||
try {
|
||||
if (metadata != null && metadata.size() > 0) {
|
||||
@@ -1307,7 +1396,7 @@ public final class SurfaceControl implements Parcelable {
|
||||
* @hide
|
||||
*/
|
||||
public int getWidth() {
|
||||
synchronized (mSizeLock) {
|
||||
synchronized (mLock) {
|
||||
return mWidth;
|
||||
}
|
||||
}
|
||||
@@ -1316,11 +1405,22 @@ public final class SurfaceControl implements Parcelable {
|
||||
* @hide
|
||||
*/
|
||||
public int getHeight() {
|
||||
synchronized (mSizeLock) {
|
||||
synchronized (mLock) {
|
||||
return mHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local view that owns this surface.
|
||||
*
|
||||
* @return The owner view.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public @Nullable View getLocalOwnerView() {
|
||||
return (mLocalOwnerView != null) ? mLocalOwnerView.get() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Surface(name=" + mName + ")/@0x" +
|
||||
@@ -2165,6 +2265,9 @@ public final class SurfaceControl implements Parcelable {
|
||||
public long mNativeObject;
|
||||
|
||||
private final ArrayMap<SurfaceControl, Point> mResizedSurfaces = new ArrayMap<>();
|
||||
private final ArrayMap<SurfaceControl, SurfaceControl> mReparentedSurfaces =
|
||||
new ArrayMap<>();
|
||||
|
||||
Runnable mFreeNativeResources;
|
||||
private static final float[] INVALID_COLOR = {-1, -1, -1};
|
||||
|
||||
@@ -2205,6 +2308,8 @@ public final class SurfaceControl implements Parcelable {
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
mResizedSurfaces.clear();
|
||||
mReparentedSurfaces.clear();
|
||||
mFreeNativeResources.run();
|
||||
mNativeObject = 0;
|
||||
}
|
||||
@@ -2215,6 +2320,7 @@ public final class SurfaceControl implements Parcelable {
|
||||
*/
|
||||
public void apply(boolean sync) {
|
||||
applyResizedSurfaces();
|
||||
notifyReparentedSurfaces();
|
||||
nativeApplyTransaction(mNativeObject, sync);
|
||||
}
|
||||
|
||||
@@ -2222,7 +2328,7 @@ public final class SurfaceControl implements Parcelable {
|
||||
for (int i = mResizedSurfaces.size() - 1; i >= 0; i--) {
|
||||
final Point size = mResizedSurfaces.valueAt(i);
|
||||
final SurfaceControl surfaceControl = mResizedSurfaces.keyAt(i);
|
||||
synchronized (surfaceControl.mSizeLock) {
|
||||
synchronized (surfaceControl.mLock) {
|
||||
surfaceControl.mWidth = size.x;
|
||||
surfaceControl.mHeight = size.y;
|
||||
}
|
||||
@@ -2230,6 +2336,22 @@ public final class SurfaceControl implements Parcelable {
|
||||
mResizedSurfaces.clear();
|
||||
}
|
||||
|
||||
private void notifyReparentedSurfaces() {
|
||||
final int reparentCount = mReparentedSurfaces.size();
|
||||
for (int i = reparentCount - 1; i >= 0; i--) {
|
||||
final SurfaceControl child = mReparentedSurfaces.keyAt(i);
|
||||
synchronized (child.mLock) {
|
||||
final int listenerCount = (child.mReparentListeners != null)
|
||||
? child.mReparentListeners.size() : 0;
|
||||
for (int j = 0; j < listenerCount; j++) {
|
||||
final OnReparentListener listener = child.mReparentListeners.get(j);
|
||||
listener.onReparent(this, mReparentedSurfaces.valueAt(i));
|
||||
}
|
||||
mReparentedSurfaces.removeAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the visibility of a given Layer and it's sub-tree.
|
||||
*
|
||||
@@ -2632,6 +2754,7 @@ public final class SurfaceControl implements Parcelable {
|
||||
otherObject = newParent.mNativeObject;
|
||||
}
|
||||
nativeReparent(mNativeObject, sc.mNativeObject, otherObject);
|
||||
mReparentedSurfaces.put(sc, newParent);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -2912,6 +3035,8 @@ public final class SurfaceControl implements Parcelable {
|
||||
}
|
||||
mResizedSurfaces.putAll(other.mResizedSurfaces);
|
||||
other.mResizedSurfaces.clear();
|
||||
mReparentedSurfaces.putAll(other.mReparentedSurfaces);
|
||||
other.mReparentedSurfaces.clear();
|
||||
nativeMergeTransaction(mNativeObject, other.mNativeObject);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ import android.os.SystemClock;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
import android.view.SurfaceControlViewHost;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.accessibility.IAccessibilityEmbeddedConnection;
|
||||
|
||||
@@ -988,6 +987,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
||||
|
||||
mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
|
||||
.setName(name)
|
||||
.setLocalOwnerView(this)
|
||||
.setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)
|
||||
.setBufferSize(mSurfaceWidth, mSurfaceHeight)
|
||||
.setFormat(mFormat)
|
||||
@@ -996,6 +996,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
||||
.build();
|
||||
mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession)
|
||||
.setName("Background for -" + name)
|
||||
.setLocalOwnerView(this)
|
||||
.setOpaque(true)
|
||||
.setColorLayer()
|
||||
.setParent(mSurfaceControl)
|
||||
@@ -1051,11 +1052,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
||||
// we still need to latch a buffer).
|
||||
// b/28866173
|
||||
if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
|
||||
mTmpTransaction.setPosition(mSurfaceControl, mScreenRect.left,
|
||||
mScreenRect.top);
|
||||
mTmpTransaction.setMatrix(mSurfaceControl,
|
||||
mScreenRect.width() / (float) mSurfaceWidth, 0.0f, 0.0f,
|
||||
mScreenRect.height() / (float) mSurfaceHeight);
|
||||
onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl,
|
||||
mScreenRect.left, /*positionLeft*/
|
||||
mScreenRect.top /*positionTop*/ ,
|
||||
mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
|
||||
mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
|
||||
|
||||
// Set a window crop when creating the surface or changing its size to
|
||||
// crop the buffer to the surface size since the buffer producer may
|
||||
// use SCALING_MODE_SCALE and submit a larger size than the surface
|
||||
@@ -1211,6 +1213,40 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
||||
Surface viewRootSurface, long nextViewRootFrameNumber) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the surface position and scale. Can be called on
|
||||
* the UI thread as well as on the renderer thread.
|
||||
*
|
||||
* @param transaction Transaction in which to execute.
|
||||
* @param surface Surface whose location to set.
|
||||
* @param positionLeft The left position to set.
|
||||
* @param positionTop The top position to set.
|
||||
* @param postScaleX The X axis post scale
|
||||
* @param postScaleY The Y axis post scale
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
protected void onSetSurfacePositionAndScaleRT(@NonNull Transaction transaction,
|
||||
@NonNull SurfaceControl surface, int positionLeft, int positionTop,
|
||||
float postScaleX, float postScaleY) {
|
||||
transaction.setPosition(surface, positionLeft, positionTop);
|
||||
transaction.setMatrix(surface, postScaleX /*dsdx*/, 0f /*dtdx*/,
|
||||
0f /*dsdy*/, postScaleY /*dtdy*/);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void requestUpdateSurfacePositionAndScale() {
|
||||
if (mSurfaceControl == null) {
|
||||
return;
|
||||
}
|
||||
onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl,
|
||||
mScreenRect.left, /*positionLeft*/
|
||||
mScreenRect.top/*positionTop*/ ,
|
||||
mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
|
||||
mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
|
||||
mTmpTransaction.apply();
|
||||
}
|
||||
|
||||
private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
|
||||
Rect position, long frameNumber) {
|
||||
final ViewRootImpl viewRoot = getViewRootImpl();
|
||||
@@ -1219,16 +1255,26 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
||||
frameNumber);
|
||||
}
|
||||
|
||||
t.setPosition(surface, position.left, position.top);
|
||||
t.setMatrix(surface,
|
||||
position.width() / (float) mSurfaceWidth,
|
||||
0.0f, 0.0f,
|
||||
position.height() / (float) mSurfaceHeight);
|
||||
onSetSurfacePositionAndScaleRT(t, surface,
|
||||
position.left /*positionLeft*/,
|
||||
position.top /*positionTop*/,
|
||||
position.width() / (float) mSurfaceWidth /*postScaleX*/,
|
||||
position.height() / (float) mSurfaceHeight /*postScaleY*/);
|
||||
|
||||
if (mViewVisibility) {
|
||||
t.show(surface);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The last render position of the backing surface or an empty rect.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public @NonNull Rect getSurfaceRenderPosition() {
|
||||
return mRTLastReportedPosition;
|
||||
}
|
||||
|
||||
private void setParentSpaceRectangle(Rect position, long frameNumber) {
|
||||
final ViewRootImpl viewRoot = getViewRootImpl();
|
||||
final boolean useBLAST = viewRoot.isDrawingToBLASTTransaction();
|
||||
|
||||
@@ -18,18 +18,22 @@ package android.widget.inline;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.TestApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.PointF;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControlViewHost;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver.OnPreDrawListener;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -88,8 +92,10 @@ public class InlineContentView extends ViewGroup {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public interface SurfacePackageUpdater {
|
||||
|
||||
|
||||
/**
|
||||
* Called when the previous surface package is released due to view being detached
|
||||
* from the window.
|
||||
@@ -101,14 +107,16 @@ public class InlineContentView extends ViewGroup {
|
||||
*
|
||||
* @param consumer consumes the updated surface package.
|
||||
*/
|
||||
void getSurfacePackage(Consumer<SurfaceControlViewHost.SurfacePackage> consumer);
|
||||
void getSurfacePackage(@NonNull Consumer<SurfaceControlViewHost.SurfacePackage> consumer);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private final SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(@NonNull SurfaceHolder holder) {
|
||||
mSurfaceControlCallback.onCreated(mSurfaceView.getSurfaceControl());
|
||||
final SurfaceControl surfaceControl = mSurfaceView.getSurfaceControl();
|
||||
surfaceControl.addOnReparentListener(mOnReparentListener);
|
||||
mSurfaceControlCallback.onCreated(surfaceControl);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,29 +127,58 @@ public class InlineContentView extends ViewGroup {
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
|
||||
mSurfaceControlCallback.onDestroyed(mSurfaceView.getSurfaceControl());
|
||||
final SurfaceControl surfaceControl = mSurfaceView.getSurfaceControl();
|
||||
surfaceControl.removeOnReparentListener(mOnReparentListener);
|
||||
mSurfaceControlCallback.onDestroyed(surfaceControl);
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
private final SurfaceControl.OnReparentListener mOnReparentListener =
|
||||
new SurfaceControl.OnReparentListener() {
|
||||
@Override
|
||||
public void onReparent(SurfaceControl.Transaction transaction,
|
||||
SurfaceControl parent) {
|
||||
final View parentSurfaceOwnerView = (parent != null)
|
||||
? parent.getLocalOwnerView() : null;
|
||||
if (parentSurfaceOwnerView instanceof SurfaceView) {
|
||||
mParentSurfaceOwnerView = new WeakReference<>(
|
||||
(SurfaceView) parentSurfaceOwnerView);
|
||||
} else {
|
||||
mParentSurfaceOwnerView = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
private final ViewTreeObserver.OnDrawListener mOnDrawListener =
|
||||
new ViewTreeObserver.OnDrawListener() {
|
||||
@Override
|
||||
public void onDraw() {
|
||||
computeParentPositionAndScale();
|
||||
final int visibility = InlineContentView.this.isShown() ? VISIBLE : GONE;
|
||||
mSurfaceView.setVisibility(visibility);
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
private final SurfaceView mSurfaceView;
|
||||
|
||||
@Nullable
|
||||
private WeakReference<SurfaceView> mParentSurfaceOwnerView;
|
||||
|
||||
@Nullable
|
||||
private int[] mParentPosition;
|
||||
|
||||
@Nullable
|
||||
private PointF mParentScale;
|
||||
|
||||
@Nullable
|
||||
private SurfaceControlCallback mSurfaceControlCallback;
|
||||
|
||||
@Nullable
|
||||
private SurfacePackageUpdater mSurfacePackageUpdater;
|
||||
|
||||
@NonNull
|
||||
private final OnPreDrawListener mDrawListener = new OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
int visibility = InlineContentView.this.isShown() ? VISIBLE : GONE;
|
||||
mSurfaceView.setVisibility(visibility);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @hide
|
||||
@@ -192,10 +229,33 @@ public class InlineContentView extends ViewGroup {
|
||||
public InlineContentView(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
mSurfaceView = new SurfaceView(context, attrs, defStyleAttr, defStyleRes);
|
||||
mSurfaceView = new SurfaceView(context, attrs, defStyleAttr, defStyleRes) {
|
||||
@Override
|
||||
protected void onSetSurfacePositionAndScaleRT(
|
||||
@NonNull SurfaceControl.Transaction transaction,
|
||||
@NonNull SurfaceControl surface, int positionLeft, int positionTop,
|
||||
float postScaleX, float postScaleY) {
|
||||
// If we have a parent position, we need to make our coordinates relative
|
||||
// to the parent in the rendering space.
|
||||
if (mParentPosition != null) {
|
||||
positionLeft = (int) ((positionLeft - mParentPosition[0]) / mParentScale.x);
|
||||
positionTop = (int) ((positionTop - mParentPosition[1]) / mParentScale.y);
|
||||
}
|
||||
|
||||
// Any scaling done to the parent or its predecessors would be applied
|
||||
// via the surfaces parent -> child relation, so we only propagate any
|
||||
// scaling set on the InlineContentView itself.
|
||||
postScaleX = InlineContentView.this.getScaleX();
|
||||
postScaleY = InlineContentView.this.getScaleY();
|
||||
|
||||
super.onSetSurfacePositionAndScaleRT(transaction, surface, positionLeft,
|
||||
positionTop, postScaleX, postScaleY);
|
||||
}
|
||||
};
|
||||
mSurfaceView.setZOrderOnTop(true);
|
||||
mSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT);
|
||||
addView(mSurfaceView);
|
||||
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,6 +263,7 @@ public class InlineContentView extends ViewGroup {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public void setChildSurfacePackageUpdater(
|
||||
@Nullable SurfacePackageUpdater surfacePackageUpdater) {
|
||||
mSurfacePackageUpdater = surfacePackageUpdater;
|
||||
@@ -221,8 +282,9 @@ public class InlineContentView extends ViewGroup {
|
||||
}
|
||||
});
|
||||
}
|
||||
mSurfaceView.setVisibility(VISIBLE);
|
||||
getViewTreeObserver().addOnPreDrawListener(mDrawListener);
|
||||
|
||||
mSurfaceView.setVisibility(getVisibility());
|
||||
getViewTreeObserver().addOnDrawListener(mOnDrawListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -232,7 +294,9 @@ public class InlineContentView extends ViewGroup {
|
||||
if (mSurfacePackageUpdater != null) {
|
||||
mSurfacePackageUpdater.onSurfacePackageReleased();
|
||||
}
|
||||
getViewTreeObserver().removeOnPreDrawListener(mDrawListener);
|
||||
|
||||
getViewTreeObserver().removeOnDrawListener(mOnDrawListener);
|
||||
mSurfaceView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -279,4 +343,67 @@ public class InlineContentView extends ViewGroup {
|
||||
public boolean setZOrderedOnTop(boolean onTop) {
|
||||
return mSurfaceView.setZOrderedOnTop(onTop, /*allowDynamicChange*/ true);
|
||||
}
|
||||
|
||||
|
||||
private void computeParentPositionAndScale() {
|
||||
boolean contentPositionOrScaleChanged = false;
|
||||
|
||||
// This method can be called on the UI or render thread but for the cases
|
||||
// it is called these threads are not running concurrently, so no need to lock.
|
||||
final SurfaceView parentSurfaceOwnerView = (mParentSurfaceOwnerView != null)
|
||||
? mParentSurfaceOwnerView.get() : null;
|
||||
|
||||
if (parentSurfaceOwnerView != null) {
|
||||
if (mParentPosition == null) {
|
||||
mParentPosition = new int[2];
|
||||
}
|
||||
final int oldParentPositionX = mParentPosition[0];
|
||||
final int oldParentPositionY = mParentPosition[1];
|
||||
parentSurfaceOwnerView.getLocationInSurface(mParentPosition);
|
||||
if (oldParentPositionX != mParentPosition[0]
|
||||
|| oldParentPositionY != mParentPosition[1]) {
|
||||
contentPositionOrScaleChanged = true;
|
||||
}
|
||||
|
||||
if (mParentScale == null) {
|
||||
mParentScale = new PointF();
|
||||
}
|
||||
|
||||
final float lastParentSurfaceWidth = parentSurfaceOwnerView
|
||||
.getSurfaceRenderPosition().width();
|
||||
final float oldParentScaleX = mParentScale.x;
|
||||
if (lastParentSurfaceWidth > 0) {
|
||||
mParentScale.x = lastParentSurfaceWidth /
|
||||
(float) parentSurfaceOwnerView.getWidth();
|
||||
} else {
|
||||
mParentScale.x = 1.0f;
|
||||
}
|
||||
if (!contentPositionOrScaleChanged
|
||||
&& Float.compare(oldParentScaleX, mParentScale.x) != 0) {
|
||||
contentPositionOrScaleChanged = true;
|
||||
}
|
||||
|
||||
final float lastParentSurfaceHeight = parentSurfaceOwnerView
|
||||
.getSurfaceRenderPosition().height();
|
||||
final float oldParentScaleY = mParentScale.y;
|
||||
if (lastParentSurfaceHeight > 0) {
|
||||
mParentScale.y = lastParentSurfaceHeight
|
||||
/ (float) parentSurfaceOwnerView.getHeight();
|
||||
} else {
|
||||
mParentScale.y = 1.0f;
|
||||
}
|
||||
if (!contentPositionOrScaleChanged
|
||||
&& Float.compare(oldParentScaleY, mParentScale.y) != 0) {
|
||||
contentPositionOrScaleChanged = true;
|
||||
}
|
||||
} else if (mParentPosition != null || mParentScale != null) {
|
||||
contentPositionOrScaleChanged = true;
|
||||
mParentPosition = null;
|
||||
mParentScale = null;
|
||||
}
|
||||
|
||||
if (contentPositionOrScaleChanged) {
|
||||
mSurfaceView.requestUpdateSurfacePositionAndScale();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user