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 {
|
package android.window {
|
||||||
|
|
||||||
public final class DisplayAreaInfo implements android.os.Parcelable {
|
public final class DisplayAreaInfo implements android.os.Parcelable {
|
||||||
|
|||||||
@@ -63,8 +63,10 @@ import dalvik.system.CloseGuard;
|
|||||||
import libcore.util.NativeAllocationRegistry;
|
import libcore.util.NativeAllocationRegistry;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,24 +228,86 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject,
|
private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject,
|
||||||
int transformHint);
|
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 final CloseGuard mCloseGuard = CloseGuard.get();
|
||||||
private String mName;
|
private String mName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public long mNativeObject;
|
public long mNativeObject;
|
||||||
private long mNativeHandle;
|
private long mNativeHandle;
|
||||||
|
|
||||||
// TODO: Move this to native.
|
// TODO: Move width/height to native and fix locking through out.
|
||||||
private final Object mSizeLock = new Object();
|
private final Object mLock = new Object();
|
||||||
@GuardedBy("mSizeLock")
|
@GuardedBy("mLock")
|
||||||
private int mWidth;
|
private int mWidth;
|
||||||
@GuardedBy("mSizeLock")
|
@GuardedBy("mLock")
|
||||||
private int mHeight;
|
private int mHeight;
|
||||||
|
|
||||||
|
private WeakReference<View> mLocalOwnerView;
|
||||||
|
|
||||||
static Transaction sGlobalTransaction;
|
static Transaction sGlobalTransaction;
|
||||||
static long sTransactionNestCount = 0;
|
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) */
|
/* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -455,6 +519,7 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
mName = other.mName;
|
mName = other.mName;
|
||||||
mWidth = other.mWidth;
|
mWidth = other.mWidth;
|
||||||
mHeight = other.mHeight;
|
mHeight = other.mHeight;
|
||||||
|
mLocalOwnerView = other.mLocalOwnerView;
|
||||||
assignNativeObject(nativeCopyFromSurfaceControl(other.mNativeObject));
|
assignNativeObject(nativeCopyFromSurfaceControl(other.mNativeObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,6 +618,7 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
private int mHeight;
|
private int mHeight;
|
||||||
private int mFormat = PixelFormat.OPAQUE;
|
private int mFormat = PixelFormat.OPAQUE;
|
||||||
private String mName;
|
private String mName;
|
||||||
|
private WeakReference<View> mLocalOwnerView;
|
||||||
private SurfaceControl mParent;
|
private SurfaceControl mParent;
|
||||||
private SparseIntArray mMetadata;
|
private SparseIntArray mMetadata;
|
||||||
|
|
||||||
@@ -587,7 +653,8 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
"Only buffer layers can set a valid buffer size.");
|
"Only buffer layers can set a valid buffer size.");
|
||||||
}
|
}
|
||||||
return new SurfaceControl(
|
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;
|
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.
|
* 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.
|
* @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
|
||||||
*/
|
*/
|
||||||
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
|
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 {
|
throws OutOfResourcesException, IllegalArgumentException {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
throw new IllegalArgumentException("name must not be null");
|
throw new IllegalArgumentException("name must not be null");
|
||||||
@@ -867,6 +955,7 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
mName = name;
|
mName = name;
|
||||||
mWidth = w;
|
mWidth = w;
|
||||||
mHeight = h;
|
mHeight = h;
|
||||||
|
mLocalOwnerView = localOwnerView;
|
||||||
Parcel metaParcel = Parcel.obtain();
|
Parcel metaParcel = Parcel.obtain();
|
||||||
try {
|
try {
|
||||||
if (metadata != null && metadata.size() > 0) {
|
if (metadata != null && metadata.size() > 0) {
|
||||||
@@ -1307,7 +1396,7 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public int getWidth() {
|
public int getWidth() {
|
||||||
synchronized (mSizeLock) {
|
synchronized (mLock) {
|
||||||
return mWidth;
|
return mWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1316,11 +1405,22 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public int getHeight() {
|
public int getHeight() {
|
||||||
synchronized (mSizeLock) {
|
synchronized (mLock) {
|
||||||
return mHeight;
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Surface(name=" + mName + ")/@0x" +
|
return "Surface(name=" + mName + ")/@0x" +
|
||||||
@@ -2165,6 +2265,9 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
public long mNativeObject;
|
public long mNativeObject;
|
||||||
|
|
||||||
private final ArrayMap<SurfaceControl, Point> mResizedSurfaces = new ArrayMap<>();
|
private final ArrayMap<SurfaceControl, Point> mResizedSurfaces = new ArrayMap<>();
|
||||||
|
private final ArrayMap<SurfaceControl, SurfaceControl> mReparentedSurfaces =
|
||||||
|
new ArrayMap<>();
|
||||||
|
|
||||||
Runnable mFreeNativeResources;
|
Runnable mFreeNativeResources;
|
||||||
private static final float[] INVALID_COLOR = {-1, -1, -1};
|
private static final float[] INVALID_COLOR = {-1, -1, -1};
|
||||||
|
|
||||||
@@ -2205,6 +2308,8 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
mResizedSurfaces.clear();
|
||||||
|
mReparentedSurfaces.clear();
|
||||||
mFreeNativeResources.run();
|
mFreeNativeResources.run();
|
||||||
mNativeObject = 0;
|
mNativeObject = 0;
|
||||||
}
|
}
|
||||||
@@ -2215,6 +2320,7 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public void apply(boolean sync) {
|
public void apply(boolean sync) {
|
||||||
applyResizedSurfaces();
|
applyResizedSurfaces();
|
||||||
|
notifyReparentedSurfaces();
|
||||||
nativeApplyTransaction(mNativeObject, sync);
|
nativeApplyTransaction(mNativeObject, sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2222,7 +2328,7 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
for (int i = mResizedSurfaces.size() - 1; i >= 0; i--) {
|
for (int i = mResizedSurfaces.size() - 1; i >= 0; i--) {
|
||||||
final Point size = mResizedSurfaces.valueAt(i);
|
final Point size = mResizedSurfaces.valueAt(i);
|
||||||
final SurfaceControl surfaceControl = mResizedSurfaces.keyAt(i);
|
final SurfaceControl surfaceControl = mResizedSurfaces.keyAt(i);
|
||||||
synchronized (surfaceControl.mSizeLock) {
|
synchronized (surfaceControl.mLock) {
|
||||||
surfaceControl.mWidth = size.x;
|
surfaceControl.mWidth = size.x;
|
||||||
surfaceControl.mHeight = size.y;
|
surfaceControl.mHeight = size.y;
|
||||||
}
|
}
|
||||||
@@ -2230,6 +2336,22 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
mResizedSurfaces.clear();
|
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.
|
* 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;
|
otherObject = newParent.mNativeObject;
|
||||||
}
|
}
|
||||||
nativeReparent(mNativeObject, sc.mNativeObject, otherObject);
|
nativeReparent(mNativeObject, sc.mNativeObject, otherObject);
|
||||||
|
mReparentedSurfaces.put(sc, newParent);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2912,6 +3035,8 @@ public final class SurfaceControl implements Parcelable {
|
|||||||
}
|
}
|
||||||
mResizedSurfaces.putAll(other.mResizedSurfaces);
|
mResizedSurfaces.putAll(other.mResizedSurfaces);
|
||||||
other.mResizedSurfaces.clear();
|
other.mResizedSurfaces.clear();
|
||||||
|
mReparentedSurfaces.putAll(other.mReparentedSurfaces);
|
||||||
|
other.mReparentedSurfaces.clear();
|
||||||
nativeMergeTransaction(mNativeObject, other.mNativeObject);
|
nativeMergeTransaction(mNativeObject, other.mNativeObject);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ import android.os.SystemClock;
|
|||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.SurfaceControl.Transaction;
|
import android.view.SurfaceControl.Transaction;
|
||||||
import android.view.SurfaceControlViewHost;
|
|
||||||
import android.view.accessibility.AccessibilityNodeInfo;
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
import android.view.accessibility.IAccessibilityEmbeddedConnection;
|
import android.view.accessibility.IAccessibilityEmbeddedConnection;
|
||||||
|
|
||||||
@@ -988,6 +987,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
|
|
||||||
mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
|
mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
|
||||||
.setName(name)
|
.setName(name)
|
||||||
|
.setLocalOwnerView(this)
|
||||||
.setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)
|
.setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)
|
||||||
.setBufferSize(mSurfaceWidth, mSurfaceHeight)
|
.setBufferSize(mSurfaceWidth, mSurfaceHeight)
|
||||||
.setFormat(mFormat)
|
.setFormat(mFormat)
|
||||||
@@ -996,6 +996,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
.build();
|
.build();
|
||||||
mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession)
|
mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession)
|
||||||
.setName("Background for -" + name)
|
.setName("Background for -" + name)
|
||||||
|
.setLocalOwnerView(this)
|
||||||
.setOpaque(true)
|
.setOpaque(true)
|
||||||
.setColorLayer()
|
.setColorLayer()
|
||||||
.setParent(mSurfaceControl)
|
.setParent(mSurfaceControl)
|
||||||
@@ -1051,11 +1052,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
// we still need to latch a buffer).
|
// we still need to latch a buffer).
|
||||||
// b/28866173
|
// b/28866173
|
||||||
if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
|
if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
|
||||||
mTmpTransaction.setPosition(mSurfaceControl, mScreenRect.left,
|
onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl,
|
||||||
mScreenRect.top);
|
mScreenRect.left, /*positionLeft*/
|
||||||
mTmpTransaction.setMatrix(mSurfaceControl,
|
mScreenRect.top /*positionTop*/ ,
|
||||||
mScreenRect.width() / (float) mSurfaceWidth, 0.0f, 0.0f,
|
mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/,
|
||||||
mScreenRect.height() / (float) mSurfaceHeight);
|
mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
|
||||||
|
|
||||||
// Set a window crop when creating the surface or changing its size to
|
// 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
|
// crop the buffer to the surface size since the buffer producer may
|
||||||
// use SCALING_MODE_SCALE and submit a larger size than the surface
|
// 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) {
|
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,
|
private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
|
||||||
Rect position, long frameNumber) {
|
Rect position, long frameNumber) {
|
||||||
final ViewRootImpl viewRoot = getViewRootImpl();
|
final ViewRootImpl viewRoot = getViewRootImpl();
|
||||||
@@ -1219,16 +1255,26 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
|||||||
frameNumber);
|
frameNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
t.setPosition(surface, position.left, position.top);
|
onSetSurfacePositionAndScaleRT(t, surface,
|
||||||
t.setMatrix(surface,
|
position.left /*positionLeft*/,
|
||||||
position.width() / (float) mSurfaceWidth,
|
position.top /*positionTop*/,
|
||||||
0.0f, 0.0f,
|
position.width() / (float) mSurfaceWidth /*postScaleX*/,
|
||||||
position.height() / (float) mSurfaceHeight);
|
position.height() / (float) mSurfaceHeight /*postScaleY*/);
|
||||||
|
|
||||||
if (mViewVisibility) {
|
if (mViewVisibility) {
|
||||||
t.show(surface);
|
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) {
|
private void setParentSpaceRectangle(Rect position, long frameNumber) {
|
||||||
final ViewRootImpl viewRoot = getViewRootImpl();
|
final ViewRootImpl viewRoot = getViewRootImpl();
|
||||||
final boolean useBLAST = viewRoot.isDrawingToBLASTTransaction();
|
final boolean useBLAST = viewRoot.isDrawingToBLASTTransaction();
|
||||||
|
|||||||
@@ -18,18 +18,22 @@ package android.widget.inline;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.TestApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.PointF;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.view.SurfaceControlViewHost;
|
import android.view.SurfaceControlViewHost;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewTreeObserver.OnPreDrawListener;
|
import android.view.ViewTreeObserver;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,8 +92,10 @@ public class InlineContentView extends ViewGroup {
|
|||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@TestApi
|
||||||
public interface SurfacePackageUpdater {
|
public interface SurfacePackageUpdater {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the previous surface package is released due to view being detached
|
* Called when the previous surface package is released due to view being detached
|
||||||
* from the window.
|
* from the window.
|
||||||
@@ -101,14 +107,16 @@ public class InlineContentView extends ViewGroup {
|
|||||||
*
|
*
|
||||||
* @param consumer consumes the updated surface package.
|
* @param consumer consumes the updated surface package.
|
||||||
*/
|
*/
|
||||||
void getSurfacePackage(Consumer<SurfaceControlViewHost.SurfacePackage> consumer);
|
void getSurfacePackage(@NonNull Consumer<SurfaceControlViewHost.SurfacePackage> consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {
|
private final SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void surfaceCreated(@NonNull SurfaceHolder holder) {
|
public void surfaceCreated(@NonNull SurfaceHolder holder) {
|
||||||
mSurfaceControlCallback.onCreated(mSurfaceView.getSurfaceControl());
|
final SurfaceControl surfaceControl = mSurfaceView.getSurfaceControl();
|
||||||
|
surfaceControl.addOnReparentListener(mOnReparentListener);
|
||||||
|
mSurfaceControlCallback.onCreated(surfaceControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -119,29 +127,58 @@ public class InlineContentView extends ViewGroup {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
|
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
|
@NonNull
|
||||||
private final SurfaceView mSurfaceView;
|
private final SurfaceView mSurfaceView;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private WeakReference<SurfaceView> mParentSurfaceOwnerView;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private int[] mParentPosition;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private PointF mParentScale;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private SurfaceControlCallback mSurfaceControlCallback;
|
private SurfaceControlCallback mSurfaceControlCallback;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private SurfacePackageUpdater mSurfacePackageUpdater;
|
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
|
* @inheritDoc
|
||||||
* @hide
|
* @hide
|
||||||
@@ -192,10 +229,33 @@ public class InlineContentView extends ViewGroup {
|
|||||||
public InlineContentView(@NonNull Context context, @Nullable AttributeSet attrs,
|
public InlineContentView(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||||
int defStyleAttr, int defStyleRes) {
|
int defStyleAttr, int defStyleRes) {
|
||||||
super(context, attrs, defStyleAttr, 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.setZOrderOnTop(true);
|
||||||
mSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT);
|
mSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT);
|
||||||
addView(mSurfaceView);
|
addView(mSurfaceView);
|
||||||
|
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -203,6 +263,7 @@ public class InlineContentView extends ViewGroup {
|
|||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@TestApi
|
||||||
public void setChildSurfacePackageUpdater(
|
public void setChildSurfacePackageUpdater(
|
||||||
@Nullable SurfacePackageUpdater surfacePackageUpdater) {
|
@Nullable SurfacePackageUpdater surfacePackageUpdater) {
|
||||||
mSurfacePackageUpdater = 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
|
@Override
|
||||||
@@ -232,7 +294,9 @@ public class InlineContentView extends ViewGroup {
|
|||||||
if (mSurfacePackageUpdater != null) {
|
if (mSurfacePackageUpdater != null) {
|
||||||
mSurfacePackageUpdater.onSurfacePackageReleased();
|
mSurfacePackageUpdater.onSurfacePackageReleased();
|
||||||
}
|
}
|
||||||
getViewTreeObserver().removeOnPreDrawListener(mDrawListener);
|
|
||||||
|
getViewTreeObserver().removeOnDrawListener(mOnDrawListener);
|
||||||
|
mSurfaceView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -279,4 +343,67 @@ public class InlineContentView extends ViewGroup {
|
|||||||
public boolean setZOrderedOnTop(boolean onTop) {
|
public boolean setZOrderedOnTop(boolean onTop) {
|
||||||
return mSurfaceView.setZOrderedOnTop(onTop, /*allowDynamicChange*/ true);
|
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