Merge "Add APIs to move suggestions below/above window" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
09b9570862
@@ -56772,6 +56772,19 @@ package android.view.contentcapture {
|
||||
|
||||
package android.view.inline {
|
||||
|
||||
public class InlineContentView extends android.view.ViewGroup {
|
||||
method @Nullable public android.view.SurfaceControl getSurfaceControl();
|
||||
method public boolean isZOrderedOnTop();
|
||||
method public void onLayout(boolean, int, int, int, int);
|
||||
method public void setSurfaceControlCallback(@Nullable android.view.inline.InlineContentView.SurfaceControlCallback);
|
||||
method public boolean setZOrderedOnTop(boolean);
|
||||
}
|
||||
|
||||
public static interface InlineContentView.SurfaceControlCallback {
|
||||
method public void onCreated(@NonNull android.view.SurfaceControl);
|
||||
method public void onDestroyed(@NonNull android.view.SurfaceControl);
|
||||
}
|
||||
|
||||
public final class InlinePresentationSpec implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public android.util.Size getMaxSize();
|
||||
@@ -56960,7 +56973,7 @@ package android.view.inputmethod {
|
||||
public final class InlineSuggestion implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public android.view.inputmethod.InlineSuggestionInfo getInfo();
|
||||
method public void inflate(@NonNull android.content.Context, @NonNull android.util.Size, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.View>);
|
||||
method public void inflate(@NonNull android.content.Context, @NonNull android.util.Size, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.view.inline.InlineContentView>);
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InlineSuggestion> CREATOR;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,9 @@ public class InlineSuggestionRoot extends FrameLayout {
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
final float distance = MathUtils.dist(mDownX, mDownY,
|
||||
event.getX(), event.getY());
|
||||
if (distance > mTouchSlop) {
|
||||
final boolean isSecure = (event.getFlags()
|
||||
& MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) == 0;
|
||||
if (!isSecure || distance > mTouchSlop) {
|
||||
try {
|
||||
mCallback.onTransferTouchFocusToImeWindow(getViewRootImpl().getInputToken(),
|
||||
getContext().getDisplayId());
|
||||
|
||||
@@ -686,16 +686,107 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
|
||||
* SurfaceView is in will be visible on top of its surface.
|
||||
*
|
||||
* <p>Note that this must be set before the surface view's containing
|
||||
* window is attached to the window manager.
|
||||
* window is attached to the window manager. If you target {@link Build.VERSION_CODES#R}
|
||||
* the Z ordering can be changed dynamically if the backing surface is
|
||||
* created, otherwise it would be applied at surface construction time.
|
||||
*
|
||||
* <p>Calling this overrides any previous call to {@link #setZOrderMediaOverlay}.
|
||||
*
|
||||
* @param onTop Whether to show the surface on top of this view's window.
|
||||
*/
|
||||
public void setZOrderOnTop(boolean onTop) {
|
||||
// In R and above we allow dynamic layer changes.
|
||||
final boolean allowDynamicChange = getContext().getApplicationInfo().targetSdkVersion
|
||||
> Build.VERSION_CODES.Q;
|
||||
setZOrderedOnTop(onTop, allowDynamicChange);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the surface backing this view appears on top of its parent.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public boolean isZOrderedOnTop() {
|
||||
return mSubLayer > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls whether the surface view's surface is placed on top of its
|
||||
* window. Normally it is placed behind the window, to allow it to
|
||||
* (for the most part) appear to composite with the views in the
|
||||
* hierarchy. By setting this, you cause it to be placed above the
|
||||
* window. This means that none of the contents of the window this
|
||||
* SurfaceView is in will be visible on top of its surface.
|
||||
*
|
||||
* <p>Calling this overrides any previous call to {@link #setZOrderMediaOverlay}.
|
||||
*
|
||||
* @param onTop Whether to show the surface on top of this view's window.
|
||||
* @param allowDynamicChange Whether this can happen after the surface is created.
|
||||
* @return Whether the Z ordering changed.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public boolean setZOrderedOnTop(boolean onTop, boolean allowDynamicChange) {
|
||||
final int subLayer;
|
||||
if (onTop) {
|
||||
mSubLayer = APPLICATION_PANEL_SUBLAYER;
|
||||
subLayer = APPLICATION_PANEL_SUBLAYER;
|
||||
} else {
|
||||
mSubLayer = APPLICATION_MEDIA_SUBLAYER;
|
||||
subLayer = APPLICATION_MEDIA_SUBLAYER;
|
||||
}
|
||||
if (mSubLayer == subLayer) {
|
||||
return false;
|
||||
}
|
||||
mSubLayer = subLayer;
|
||||
|
||||
if (!allowDynamicChange) {
|
||||
return false;
|
||||
}
|
||||
if (mSurfaceControl == null) {
|
||||
return true;
|
||||
}
|
||||
final ViewRootImpl viewRoot = getViewRootImpl();
|
||||
if (viewRoot == null) {
|
||||
return true;
|
||||
}
|
||||
final Surface parent = viewRoot.mSurface;
|
||||
if (parent == null || !parent.isValid()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Schedule a callback that reflects an alpha value onto the underlying surfaces.
|
||||
* This gets called on a RenderThread worker thread, so members accessed here must
|
||||
* be protected by a lock.
|
||||
*/
|
||||
final boolean useBLAST = viewRoot.useBLAST();
|
||||
viewRoot.registerRtFrameCallback(frame -> {
|
||||
try {
|
||||
final SurfaceControl.Transaction t = useBLAST
|
||||
? viewRoot.getBLASTSyncTransaction()
|
||||
: new SurfaceControl.Transaction();
|
||||
synchronized (mSurfaceControlLock) {
|
||||
if (!parent.isValid() || mSurfaceControl == null) {
|
||||
return;
|
||||
}
|
||||
updateRelativeZ(t);
|
||||
if (!useBLAST) {
|
||||
t.deferTransactionUntil(mSurfaceControl,
|
||||
viewRoot.getRenderSurfaceControl(), frame);
|
||||
}
|
||||
}
|
||||
// It's possible that mSurfaceControl is released in the UI thread before
|
||||
// the transaction completes. If that happens, an exception is thrown, which
|
||||
// must be caught immediately.
|
||||
t.apply();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, System.identityHashCode(this)
|
||||
+ "setZOrderOnTop RT: Exception during surface transaction", e);
|
||||
}
|
||||
});
|
||||
|
||||
invalidate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,22 +17,189 @@
|
||||
package android.view.inline;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControlViewHost;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
/**
|
||||
* This class represents a view that can hold an opaque content that may be from a different source.
|
||||
* This class represents a view that holds opaque content from another app that
|
||||
* you can inline in your UI.
|
||||
*
|
||||
* @hide
|
||||
* <p>Since the content presented by this view is from another security domain,it is
|
||||
* shown on a remote surface preventing the host application from accessing that content.
|
||||
* Also the host application cannot interact with the inlined content by injecting touch
|
||||
* events or clicking programmatically.
|
||||
*
|
||||
* <p>This view can be overlaid by other windows, i.e. redressed, but if this is the case
|
||||
* the inined UI would not be interactive. Sometimes this is desirable, e.g. animating
|
||||
* transitions.
|
||||
*
|
||||
* <p>By default the surface backing this view is shown on top of the hosting window such
|
||||
* that the inlined content is interactive. However, you can temporarily move the surface
|
||||
* under the hosting window which could be useful in some cases, e.g. animating transitions.
|
||||
* At this point the inlined content will not be interactive and the touch events would
|
||||
* be delivered to your app.
|
||||
*/
|
||||
public class InlineContentView extends SurfaceView {
|
||||
public InlineContentView(@NonNull Context context,
|
||||
@NonNull SurfaceControlViewHost.SurfacePackage surfacePackage) {
|
||||
super(context);
|
||||
setZOrderOnTop(true);
|
||||
setChildSurfacePackage(surfacePackage);
|
||||
getHolder().setFormat(PixelFormat.TRANSPARENT);
|
||||
public class InlineContentView extends ViewGroup {
|
||||
|
||||
/**
|
||||
* Callback for observing the lifecycle of the surface control
|
||||
* that manipulates the backing secure embedded UI surface.
|
||||
*/
|
||||
public interface SurfaceControlCallback {
|
||||
/**
|
||||
* Called when the backing surface is being created.
|
||||
*
|
||||
* @param surfaceControl The surface control to manipulate the surface.
|
||||
*/
|
||||
void onCreated(@NonNull SurfaceControl surfaceControl);
|
||||
|
||||
/**
|
||||
* Called when the backing surface is being destroyed.
|
||||
*
|
||||
* @param surfaceControl The surface control to manipulate the surface.
|
||||
*/
|
||||
void onDestroyed(@NonNull SurfaceControl surfaceControl);
|
||||
}
|
||||
|
||||
private final @NonNull SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(@NonNull SurfaceHolder holder) {
|
||||
mSurfaceControlCallback.onCreated(mSurfaceView.getSurfaceControl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(@NonNull SurfaceHolder holder,
|
||||
int format, int width, int height) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
|
||||
mSurfaceControlCallback.onDestroyed(mSurfaceView.getSurfaceControl());
|
||||
}
|
||||
};
|
||||
|
||||
private final @NonNull SurfaceView mSurfaceView;
|
||||
|
||||
private @Nullable SurfaceControlCallback mSurfaceControlCallback;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public InlineContentView(@NonNull Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public InlineContentView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public InlineContentView(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the surface control. If the surface is not created this method
|
||||
* returns {@code null}.
|
||||
*
|
||||
* @return The surface control.
|
||||
*
|
||||
* @see #setSurfaceControlCallback(SurfaceControlCallback)
|
||||
*/
|
||||
public @Nullable SurfaceControl getSurfaceControl() {
|
||||
return mSurfaceView.getSurfaceControl();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
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.setZOrderOnTop(true);
|
||||
mSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT);
|
||||
addView(mSurfaceView);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the embedded UI.
|
||||
* @param surfacePackage The embedded UI.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void setChildSurfacePackage(
|
||||
@Nullable SurfaceControlViewHost.SurfacePackage surfacePackage) {
|
||||
mSurfaceView.setChildSurfacePackage(surfacePackage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
mSurfaceView.layout(l, t, r, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a callback to observe the lifecycle of the surface control for
|
||||
* managing the backing surface.
|
||||
*
|
||||
* @param callback The callback to set or {@code null} to clear.
|
||||
*/
|
||||
public void setSurfaceControlCallback(@Nullable SurfaceControlCallback callback) {
|
||||
if (mSurfaceControlCallback != null) {
|
||||
mSurfaceView.getHolder().removeCallback(mSurfaceCallback);
|
||||
}
|
||||
mSurfaceControlCallback = callback;
|
||||
if (mSurfaceControlCallback != null) {
|
||||
mSurfaceView.getHolder().addCallback(mSurfaceCallback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the surface backing this view appears on top of its parent.
|
||||
*
|
||||
* @see #setZOrderedOnTop(boolean)
|
||||
*/
|
||||
public boolean isZOrderedOnTop() {
|
||||
return mSurfaceView.isZOrderedOnTop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls whether the backing surface is placed on top of this view's window.
|
||||
* Normally, it is placed on top of the window, to allow interaction
|
||||
* with the inlined UI. Via this method, you can place the surface below the
|
||||
* window. This means that all of the contents of the window this view is in
|
||||
* will be visible on top of its surface.
|
||||
*
|
||||
* <p> The Z ordering can be changed dynamically if the backing surface is
|
||||
* created, otherwise the ordering would be applied at surface construction time.
|
||||
*
|
||||
* @param onTop Whether to show the surface on top of this view's window.
|
||||
*
|
||||
* @see #isZOrderedOnTop()
|
||||
*/
|
||||
public boolean setZOrderedOnTop(boolean onTop) {
|
||||
return mSurfaceView.setZOrderedOnTop(onTop, /*allowDynamicChange*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import android.os.RemoteException;
|
||||
import android.util.Size;
|
||||
import android.util.Slog;
|
||||
import android.view.SurfaceControlViewHost;
|
||||
import android.view.View;
|
||||
import android.view.inline.InlineContentView;
|
||||
import android.view.inline.InlinePresentationSpec;
|
||||
|
||||
@@ -94,15 +93,15 @@ public final class InlineSuggestion implements Parcelable {
|
||||
this(info, contentProvider, /* inlineContentCallback */ null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inflates a view with the content of this suggestion at a specific size.
|
||||
* The size must be between the {@link InlinePresentationSpec#getMinSize() min size}
|
||||
* and the {@link InlinePresentationSpec#getMaxSize() max size} of the presentation
|
||||
* spec returned by {@link InlineSuggestionInfo#getPresentationSpec()}.
|
||||
*
|
||||
* <p> The caller can attach an {@link View.OnClickListener} and/or an
|
||||
* {@link View.OnLongClickListener} to the view in the {@code callback} to receive click and
|
||||
* <p> The caller can attach an {@link android.view.View.OnClickListener} and/or an
|
||||
* {@link android.view.View.OnLongClickListener} to the view in the
|
||||
* {@code callback} to receive click and
|
||||
* long click events on the view.
|
||||
*
|
||||
* @param context Context in which to inflate the view.
|
||||
@@ -113,7 +112,7 @@ public final class InlineSuggestion implements Parcelable {
|
||||
*/
|
||||
public void inflate(@NonNull Context context, @NonNull Size size,
|
||||
@NonNull @CallbackExecutor Executor callbackExecutor,
|
||||
@NonNull Consumer<View> callback) {
|
||||
@NonNull Consumer<InlineContentView> callback) {
|
||||
final Size minSize = mInfo.getPresentationSpec().getMinSize();
|
||||
final Size maxSize = mInfo.getPresentationSpec().getMaxSize();
|
||||
if (size.getHeight() < minSize.getHeight() || size.getHeight() > maxSize.getHeight()
|
||||
@@ -138,7 +137,7 @@ public final class InlineSuggestion implements Parcelable {
|
||||
}
|
||||
|
||||
private synchronized InlineContentCallbackImpl getInlineContentCallback(Context context,
|
||||
Executor callbackExecutor, Consumer<View> callback) {
|
||||
Executor callbackExecutor, Consumer<InlineContentView> callback) {
|
||||
if (mInlineContentCallback != null) {
|
||||
throw new IllegalStateException("Already called #inflate()");
|
||||
}
|
||||
@@ -185,12 +184,12 @@ public final class InlineSuggestion implements Parcelable {
|
||||
|
||||
private final @NonNull Context mContext;
|
||||
private final @NonNull Executor mCallbackExecutor;
|
||||
private final @NonNull Consumer<View> mCallback;
|
||||
private @Nullable View mView;
|
||||
private final @NonNull Consumer<InlineContentView> mCallback;
|
||||
private @Nullable InlineContentView mView;
|
||||
|
||||
InlineContentCallbackImpl(@NonNull Context context,
|
||||
@NonNull @CallbackExecutor Executor callbackExecutor,
|
||||
@NonNull Consumer<View> callback) {
|
||||
@NonNull Consumer<InlineContentView> callback) {
|
||||
mContext = context;
|
||||
mCallbackExecutor = callbackExecutor;
|
||||
mCallback = callback;
|
||||
@@ -201,7 +200,8 @@ public final class InlineSuggestion implements Parcelable {
|
||||
if (content == null) {
|
||||
mCallbackExecutor.execute(() -> mCallback.accept(/* view */null));
|
||||
} else {
|
||||
mView = new InlineContentView(mContext, content);
|
||||
mView = new InlineContentView(mContext);
|
||||
mView.setChildSurfacePackage(content);
|
||||
mCallbackExecutor.execute(() -> mCallback.accept(mView));
|
||||
}
|
||||
}
|
||||
@@ -398,10 +398,10 @@ public final class InlineSuggestion implements Parcelable {
|
||||
};
|
||||
|
||||
@DataClass.Generated(
|
||||
time = 1583889058241L,
|
||||
time = 1584679775946L,
|
||||
codegenVersion = "1.0.15",
|
||||
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java",
|
||||
inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.view.View>)\nprivate synchronized android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.view.View>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
|
||||
inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.view.inline.InlineContentView>)\nprivate synchronized android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.view.inline.InlineContentView>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
|
||||
@Deprecated
|
||||
private void __metadata() {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user