705 lines
28 KiB
Java
705 lines
28 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2019 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.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package android.view.inputmethod;
|
||
|
|
||
|
import android.annotation.BinderThread;
|
||
|
import android.annotation.CallbackExecutor;
|
||
|
import android.annotation.MainThread;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.annotation.TestApi;
|
||
|
import android.content.Context;
|
||
|
import android.os.Handler;
|
||
|
import android.os.Looper;
|
||
|
import android.os.Parcel;
|
||
|
import android.os.Parcelable;
|
||
|
import android.os.RemoteException;
|
||
|
import android.util.Size;
|
||
|
import android.util.Slog;
|
||
|
import android.view.SurfaceControlViewHost;
|
||
|
import android.view.View;
|
||
|
import android.view.ViewGroup;
|
||
|
import android.widget.inline.InlineContentView;
|
||
|
|
||
|
import com.android.internal.util.DataClass;
|
||
|
import com.android.internal.util.Parcelling;
|
||
|
import com.android.internal.view.inline.IInlineContentCallback;
|
||
|
import com.android.internal.view.inline.IInlineContentProvider;
|
||
|
import com.android.internal.view.inline.InlineTooltipUi;
|
||
|
|
||
|
import java.lang.ref.WeakReference;
|
||
|
import java.util.concurrent.Executor;
|
||
|
import java.util.function.Consumer;
|
||
|
|
||
|
/**
|
||
|
* This class represents an inline suggestion which is made by one app and can be embedded into the
|
||
|
* UI of another. Suggestions may contain sensitive information not known to the host app which
|
||
|
* needs to be protected from spoofing. To address that the suggestion view inflated on demand for
|
||
|
* embedding is created in such a way that the hosting app cannot introspect its content and cannot
|
||
|
* interact with it.
|
||
|
*/
|
||
|
@DataClass(genEqualsHashCode = true, genToString = true, genHiddenConstDefs = true,
|
||
|
genHiddenConstructor = true)
|
||
|
public final class InlineSuggestion implements Parcelable {
|
||
|
|
||
|
private static final String TAG = "InlineSuggestion";
|
||
|
|
||
|
@NonNull
|
||
|
private final InlineSuggestionInfo mInfo;
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
@Nullable
|
||
|
private final IInlineContentProvider mContentProvider;
|
||
|
|
||
|
/**
|
||
|
* Used to keep a strong reference to the callback so it doesn't get garbage collected.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@DataClass.ParcelWith(InlineContentCallbackImplParceling.class)
|
||
|
@Nullable
|
||
|
private InlineContentCallbackImpl mInlineContentCallback;
|
||
|
|
||
|
/**
|
||
|
* Used to show up the inline suggestion tooltip.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@Nullable
|
||
|
@DataClass.ParcelWith(InlineTooltipUiParceling.class)
|
||
|
private InlineTooltipUi mInlineTooltipUi;
|
||
|
|
||
|
/**
|
||
|
* Creates a new {@link InlineSuggestion}, for testing purpose.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@TestApi
|
||
|
@NonNull
|
||
|
public static InlineSuggestion newInlineSuggestion(@NonNull InlineSuggestionInfo info) {
|
||
|
return new InlineSuggestion(info, null, /* inlineContentCallback */ null,
|
||
|
/* inlineTooltipUi */ null);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a new {@link InlineSuggestion}.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public InlineSuggestion(@NonNull InlineSuggestionInfo info,
|
||
|
@Nullable IInlineContentProvider contentProvider) {
|
||
|
this(info, contentProvider, /* inlineContentCallback */ null, /* inlineTooltipUi */ null);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Inflates a view with the content of this suggestion at a specific size.
|
||
|
*
|
||
|
* <p> Each dimension of the size must satisfy one of the following conditions:
|
||
|
*
|
||
|
* <ol>
|
||
|
* <li>between {@link android.widget.inline.InlinePresentationSpec#getMinSize()} and
|
||
|
* {@link android.widget.inline.InlinePresentationSpec#getMaxSize()} of the presentation spec
|
||
|
* from {@code mInfo}
|
||
|
* <li>{@link ViewGroup.LayoutParams#WRAP_CONTENT}
|
||
|
* </ol>
|
||
|
*
|
||
|
* If the size is set to {@link
|
||
|
* ViewGroup.LayoutParams#WRAP_CONTENT}, then the size of the inflated view will be just large
|
||
|
* enough to fit the content, while still conforming to the min / max size specified by the
|
||
|
* {@link android.widget.inline.InlinePresentationSpec}.
|
||
|
*
|
||
|
* <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.
|
||
|
* @param size The size at which to inflate the suggestion. For each dimension, it maybe an
|
||
|
* exact value or {@link ViewGroup.LayoutParams#WRAP_CONTENT}.
|
||
|
* @param callback Callback for receiving the inflated view, where the {@link
|
||
|
* ViewGroup.LayoutParams} of the view is set as the actual size of the
|
||
|
* underlying remote view.
|
||
|
* @throws IllegalArgumentException If an invalid argument is passed.
|
||
|
* @throws IllegalStateException If this method is already called.
|
||
|
*/
|
||
|
public void inflate(@NonNull Context context, @NonNull Size size,
|
||
|
@NonNull @CallbackExecutor Executor callbackExecutor,
|
||
|
@NonNull Consumer<InlineContentView> callback) {
|
||
|
final Size minSize = mInfo.getInlinePresentationSpec().getMinSize();
|
||
|
final Size maxSize = mInfo.getInlinePresentationSpec().getMaxSize();
|
||
|
if (!isValid(size.getWidth(), minSize.getWidth(), maxSize.getWidth())
|
||
|
|| !isValid(size.getHeight(), minSize.getHeight(), maxSize.getHeight())) {
|
||
|
throw new IllegalArgumentException(
|
||
|
"size is neither between min:" + minSize + " and max:" + maxSize
|
||
|
+ ", nor wrap_content");
|
||
|
}
|
||
|
|
||
|
InlineSuggestion toolTip = mInfo.getTooltip();
|
||
|
if (toolTip != null) {
|
||
|
if (mInlineTooltipUi == null) {
|
||
|
mInlineTooltipUi = new InlineTooltipUi(context);
|
||
|
}
|
||
|
} else {
|
||
|
mInlineTooltipUi = null;
|
||
|
}
|
||
|
|
||
|
mInlineContentCallback = getInlineContentCallback(context, callbackExecutor, callback,
|
||
|
mInlineTooltipUi);
|
||
|
if (mContentProvider == null) {
|
||
|
callbackExecutor.execute(() -> callback.accept(/* view */ null));
|
||
|
mInlineTooltipUi = null;
|
||
|
return;
|
||
|
}
|
||
|
try {
|
||
|
mContentProvider.provideContent(size.getWidth(), size.getHeight(),
|
||
|
new InlineContentCallbackWrapper(mInlineContentCallback));
|
||
|
} catch (RemoteException e) {
|
||
|
Slog.w(TAG, "Error creating suggestion content surface: " + e);
|
||
|
callbackExecutor.execute(() -> callback.accept(/* view */ null));
|
||
|
}
|
||
|
if (toolTip == null) return;
|
||
|
|
||
|
final Size tooltipSize = new Size(ViewGroup.LayoutParams.WRAP_CONTENT,
|
||
|
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||
|
mInfo.getTooltip().inflate(context, tooltipSize, callbackExecutor, view -> {
|
||
|
Handler.getMain().post(() -> mInlineTooltipUi.setTooltipView(view));
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if the {@code actual} length is within [min, max] or is {@link
|
||
|
* ViewGroup.LayoutParams#WRAP_CONTENT}.
|
||
|
*/
|
||
|
private static boolean isValid(int actual, int min, int max) {
|
||
|
if (actual == ViewGroup.LayoutParams.WRAP_CONTENT) {
|
||
|
return true;
|
||
|
}
|
||
|
return actual >= min && actual <= max;
|
||
|
}
|
||
|
|
||
|
private synchronized InlineContentCallbackImpl getInlineContentCallback(Context context,
|
||
|
Executor callbackExecutor, Consumer<InlineContentView> callback,
|
||
|
InlineTooltipUi inlineTooltipUi) {
|
||
|
if (mInlineContentCallback != null) {
|
||
|
throw new IllegalStateException("Already called #inflate()");
|
||
|
}
|
||
|
return new InlineContentCallbackImpl(context, mContentProvider, callbackExecutor,
|
||
|
callback, inlineTooltipUi);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* A wrapper class around the {@link InlineContentCallbackImpl} to ensure it's not strongly
|
||
|
* reference by the remote system server process.
|
||
|
*/
|
||
|
private static final class InlineContentCallbackWrapper extends IInlineContentCallback.Stub {
|
||
|
|
||
|
private final WeakReference<InlineContentCallbackImpl> mCallbackImpl;
|
||
|
|
||
|
InlineContentCallbackWrapper(InlineContentCallbackImpl callbackImpl) {
|
||
|
mCallbackImpl = new WeakReference<>(callbackImpl);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@BinderThread
|
||
|
public void onContent(SurfaceControlViewHost.SurfacePackage content, int width,
|
||
|
int height) {
|
||
|
final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get();
|
||
|
if (callbackImpl != null) {
|
||
|
callbackImpl.onContent(content, width, height);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@BinderThread
|
||
|
public void onClick() {
|
||
|
final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get();
|
||
|
if (callbackImpl != null) {
|
||
|
callbackImpl.onClick();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@BinderThread
|
||
|
public void onLongClick() {
|
||
|
final InlineContentCallbackImpl callbackImpl = mCallbackImpl.get();
|
||
|
if (callbackImpl != null) {
|
||
|
callbackImpl.onLongClick();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handles the communication between the inline suggestion view in current (IME) process and
|
||
|
* the remote view provided from the system server.
|
||
|
*
|
||
|
* <p>This class is thread safe, because all the outside calls are piped into a single
|
||
|
* handler thread to be processed.
|
||
|
*/
|
||
|
private static final class InlineContentCallbackImpl {
|
||
|
|
||
|
@NonNull
|
||
|
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
|
||
|
|
||
|
@NonNull
|
||
|
private final Context mContext;
|
||
|
@Nullable
|
||
|
private final IInlineContentProvider mInlineContentProvider;
|
||
|
@NonNull
|
||
|
private final Executor mCallbackExecutor;
|
||
|
|
||
|
/**
|
||
|
* Callback from the client (IME) that will receive the inflated suggestion view. It'll
|
||
|
* only be called once when the view SurfacePackage is first sent back to the client. Any
|
||
|
* updates to the view due to attach to window and detach from window events will be
|
||
|
* handled under the hood, transparent from the client.
|
||
|
*/
|
||
|
@NonNull
|
||
|
private final Consumer<InlineContentView> mCallback;
|
||
|
|
||
|
/**
|
||
|
* Indicates whether the first content has been received or not.
|
||
|
*/
|
||
|
private boolean mFirstContentReceived = false;
|
||
|
|
||
|
/**
|
||
|
* The client (IME) side view which internally wraps a remote view. It'll be set when
|
||
|
* {@link #onContent(SurfaceControlViewHost.SurfacePackage, int, int)} is called, which
|
||
|
* should only happen once in the lifecycle of this inline suggestion instance.
|
||
|
*/
|
||
|
@Nullable
|
||
|
private InlineContentView mView;
|
||
|
|
||
|
/**
|
||
|
* The SurfacePackage pointing to the remote view. It's cached here to be sent to the next
|
||
|
* available consumer.
|
||
|
*/
|
||
|
@Nullable
|
||
|
private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
|
||
|
|
||
|
/**
|
||
|
* The callback (from the {@link InlineContentView}) which consumes the surface package.
|
||
|
* It's cached here to be called when the SurfacePackage is returned from the remote
|
||
|
* view owning process.
|
||
|
*/
|
||
|
@Nullable
|
||
|
private Consumer<SurfaceControlViewHost.SurfacePackage> mSurfacePackageConsumer;
|
||
|
|
||
|
@Nullable
|
||
|
private InlineTooltipUi mInlineTooltipUi;
|
||
|
|
||
|
InlineContentCallbackImpl(@NonNull Context context,
|
||
|
@Nullable IInlineContentProvider inlineContentProvider,
|
||
|
@NonNull @CallbackExecutor Executor callbackExecutor,
|
||
|
@NonNull Consumer<InlineContentView> callback,
|
||
|
@Nullable InlineTooltipUi inlineTooltipUi) {
|
||
|
mContext = context;
|
||
|
mInlineContentProvider = inlineContentProvider;
|
||
|
mCallbackExecutor = callbackExecutor;
|
||
|
mCallback = callback;
|
||
|
mInlineTooltipUi = inlineTooltipUi;
|
||
|
}
|
||
|
|
||
|
@BinderThread
|
||
|
public void onContent(SurfaceControlViewHost.SurfacePackage content, int width,
|
||
|
int height) {
|
||
|
mMainHandler.post(() -> handleOnContent(content, width, height));
|
||
|
}
|
||
|
|
||
|
@MainThread
|
||
|
private void handleOnContent(SurfaceControlViewHost.SurfacePackage content, int width,
|
||
|
int height) {
|
||
|
if (!mFirstContentReceived) {
|
||
|
handleOnFirstContentReceived(content, width, height);
|
||
|
mFirstContentReceived = true;
|
||
|
} else {
|
||
|
handleOnSurfacePackage(content);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Called when the view content is returned for the first time.
|
||
|
*/
|
||
|
@MainThread
|
||
|
private void handleOnFirstContentReceived(SurfaceControlViewHost.SurfacePackage content,
|
||
|
int width, int height) {
|
||
|
mSurfacePackage = content;
|
||
|
if (mSurfacePackage == null) {
|
||
|
mCallbackExecutor.execute(() -> mCallback.accept(/* view */null));
|
||
|
} else {
|
||
|
mView = new InlineContentView(mContext);
|
||
|
if (mInlineTooltipUi != null) {
|
||
|
mView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
|
||
|
@Override
|
||
|
public void onLayoutChange(View v, int left, int top, int right,
|
||
|
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
|
||
|
if (mInlineTooltipUi != null) {
|
||
|
mInlineTooltipUi.update(mView);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
mView.setLayoutParams(new ViewGroup.LayoutParams(width, height));
|
||
|
mView.setChildSurfacePackageUpdater(getSurfacePackageUpdater());
|
||
|
mCallbackExecutor.execute(() -> mCallback.accept(mView));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Called when any subsequent SurfacePackage is returned from the remote view owning
|
||
|
* process.
|
||
|
*/
|
||
|
@MainThread
|
||
|
private void handleOnSurfacePackage(SurfaceControlViewHost.SurfacePackage surfacePackage) {
|
||
|
if (surfacePackage == null) {
|
||
|
return;
|
||
|
}
|
||
|
if (mSurfacePackage != null || mSurfacePackageConsumer == null) {
|
||
|
// The surface package is not consumed, release it immediately.
|
||
|
surfacePackage.release();
|
||
|
try {
|
||
|
mInlineContentProvider.onSurfacePackageReleased();
|
||
|
} catch (RemoteException e) {
|
||
|
Slog.w(TAG, "Error calling onSurfacePackageReleased(): " + e);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
mSurfacePackage = surfacePackage;
|
||
|
if (mSurfacePackage == null) {
|
||
|
return;
|
||
|
}
|
||
|
if (mSurfacePackageConsumer != null) {
|
||
|
mSurfacePackageConsumer.accept(mSurfacePackage);
|
||
|
mSurfacePackageConsumer = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@MainThread
|
||
|
private void handleOnSurfacePackageReleased() {
|
||
|
if (mSurfacePackage != null) {
|
||
|
try {
|
||
|
mInlineContentProvider.onSurfacePackageReleased();
|
||
|
} catch (RemoteException e) {
|
||
|
Slog.w(TAG, "Error calling onSurfacePackageReleased(): " + e);
|
||
|
}
|
||
|
mSurfacePackage = null;
|
||
|
}
|
||
|
// Clear the pending surface package consumer, if any. This can happen if the IME
|
||
|
// attaches the view to window and then quickly detaches it from the window, before
|
||
|
// the surface package requested upon attaching to window was returned.
|
||
|
mSurfacePackageConsumer = null;
|
||
|
}
|
||
|
|
||
|
@MainThread
|
||
|
private void handleGetSurfacePackage(
|
||
|
Consumer<SurfaceControlViewHost.SurfacePackage> consumer) {
|
||
|
if (mSurfacePackage != null) {
|
||
|
consumer.accept(mSurfacePackage);
|
||
|
} else {
|
||
|
mSurfacePackageConsumer = consumer;
|
||
|
try {
|
||
|
mInlineContentProvider.requestSurfacePackage();
|
||
|
} catch (RemoteException e) {
|
||
|
Slog.w(TAG, "Error calling getSurfacePackage(): " + e);
|
||
|
consumer.accept(null);
|
||
|
mSurfacePackageConsumer = null;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private InlineContentView.SurfacePackageUpdater getSurfacePackageUpdater() {
|
||
|
return new InlineContentView.SurfacePackageUpdater() {
|
||
|
@Override
|
||
|
public void onSurfacePackageReleased() {
|
||
|
mMainHandler.post(
|
||
|
() -> InlineContentCallbackImpl.this.handleOnSurfacePackageReleased());
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void getSurfacePackage(
|
||
|
Consumer<SurfaceControlViewHost.SurfacePackage> consumer) {
|
||
|
mMainHandler.post(
|
||
|
() -> InlineContentCallbackImpl.this.handleGetSurfacePackage(consumer));
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
@BinderThread
|
||
|
public void onClick() {
|
||
|
mMainHandler.post(() -> {
|
||
|
if (mView != null && mView.hasOnClickListeners()) {
|
||
|
mView.callOnClick();
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
@BinderThread
|
||
|
public void onLongClick() {
|
||
|
mMainHandler.post(() -> {
|
||
|
if (mView != null && mView.hasOnLongClickListeners()) {
|
||
|
mView.performLongClick();
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This class used to provide parcelling logic for InlineContentCallbackImpl. It's intended to
|
||
|
* make this parcelling a no-op, since it can't be parceled and we don't need to parcel it.
|
||
|
*/
|
||
|
private static class InlineContentCallbackImplParceling implements
|
||
|
Parcelling<InlineContentCallbackImpl> {
|
||
|
@Override
|
||
|
public void parcel(InlineContentCallbackImpl item, Parcel dest, int parcelFlags) {
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public InlineContentCallbackImpl unparcel(Parcel source) {
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This class used to provide parcelling logic for InlineContentCallbackImpl. It's intended to
|
||
|
* make this parcelling a no-op, since it can't be parceled and we don't need to parcel it.
|
||
|
*/
|
||
|
private static class InlineTooltipUiParceling implements
|
||
|
Parcelling<InlineTooltipUi> {
|
||
|
@Override
|
||
|
public void parcel(InlineTooltipUi item, Parcel dest, int parcelFlags) {
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public InlineTooltipUi unparcel(Parcel source) {
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Code below generated by codegen v1.0.22.
|
||
|
//
|
||
|
// DO NOT MODIFY!
|
||
|
// CHECKSTYLE:OFF Generated code
|
||
|
//
|
||
|
// To regenerate run:
|
||
|
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java
|
||
|
//
|
||
|
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
|
||
|
// Settings > Editor > Code Style > Formatter Control
|
||
|
//@formatter:off
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Creates a new InlineSuggestion.
|
||
|
*
|
||
|
* @param inlineContentCallback
|
||
|
* Used to keep a strong reference to the callback so it doesn't get garbage collected.
|
||
|
* @param inlineTooltipUi
|
||
|
* Used to show up the inline suggestion tooltip.
|
||
|
* @hide
|
||
|
*/
|
||
|
@DataClass.Generated.Member
|
||
|
public InlineSuggestion(
|
||
|
@NonNull InlineSuggestionInfo info,
|
||
|
@Nullable IInlineContentProvider contentProvider,
|
||
|
@Nullable InlineContentCallbackImpl inlineContentCallback,
|
||
|
@Nullable InlineTooltipUi inlineTooltipUi) {
|
||
|
this.mInfo = info;
|
||
|
com.android.internal.util.AnnotationValidations.validate(
|
||
|
NonNull.class, null, mInfo);
|
||
|
this.mContentProvider = contentProvider;
|
||
|
this.mInlineContentCallback = inlineContentCallback;
|
||
|
this.mInlineTooltipUi = inlineTooltipUi;
|
||
|
|
||
|
// onConstructed(); // You can define this method to get a callback
|
||
|
}
|
||
|
|
||
|
@DataClass.Generated.Member
|
||
|
public @NonNull InlineSuggestionInfo getInfo() {
|
||
|
return mInfo;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
@DataClass.Generated.Member
|
||
|
public @Nullable IInlineContentProvider getContentProvider() {
|
||
|
return mContentProvider;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Used to keep a strong reference to the callback so it doesn't get garbage collected.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@DataClass.Generated.Member
|
||
|
public @Nullable InlineContentCallbackImpl getInlineContentCallback() {
|
||
|
return mInlineContentCallback;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Used to show up the inline suggestion tooltip.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@DataClass.Generated.Member
|
||
|
public @Nullable InlineTooltipUi getInlineTooltipUi() {
|
||
|
return mInlineTooltipUi;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@DataClass.Generated.Member
|
||
|
public String toString() {
|
||
|
// You can override field toString logic by defining methods like:
|
||
|
// String fieldNameToString() { ... }
|
||
|
|
||
|
return "InlineSuggestion { " +
|
||
|
"info = " + mInfo + ", " +
|
||
|
"contentProvider = " + mContentProvider + ", " +
|
||
|
"inlineContentCallback = " + mInlineContentCallback + ", " +
|
||
|
"inlineTooltipUi = " + mInlineTooltipUi +
|
||
|
" }";
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@DataClass.Generated.Member
|
||
|
public boolean equals(@Nullable Object o) {
|
||
|
// You can override field equality logic by defining either of the methods like:
|
||
|
// boolean fieldNameEquals(InlineSuggestion other) { ... }
|
||
|
// boolean fieldNameEquals(FieldType otherValue) { ... }
|
||
|
|
||
|
if (this == o) return true;
|
||
|
if (o == null || getClass() != o.getClass()) return false;
|
||
|
@SuppressWarnings("unchecked")
|
||
|
InlineSuggestion that = (InlineSuggestion) o;
|
||
|
//noinspection PointlessBooleanExpression
|
||
|
return true
|
||
|
&& java.util.Objects.equals(mInfo, that.mInfo)
|
||
|
&& java.util.Objects.equals(mContentProvider, that.mContentProvider)
|
||
|
&& java.util.Objects.equals(mInlineContentCallback, that.mInlineContentCallback)
|
||
|
&& java.util.Objects.equals(mInlineTooltipUi, that.mInlineTooltipUi);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@DataClass.Generated.Member
|
||
|
public int hashCode() {
|
||
|
// You can override field hashCode logic by defining methods like:
|
||
|
// int fieldNameHashCode() { ... }
|
||
|
|
||
|
int _hash = 1;
|
||
|
_hash = 31 * _hash + java.util.Objects.hashCode(mInfo);
|
||
|
_hash = 31 * _hash + java.util.Objects.hashCode(mContentProvider);
|
||
|
_hash = 31 * _hash + java.util.Objects.hashCode(mInlineContentCallback);
|
||
|
_hash = 31 * _hash + java.util.Objects.hashCode(mInlineTooltipUi);
|
||
|
return _hash;
|
||
|
}
|
||
|
|
||
|
@DataClass.Generated.Member
|
||
|
static Parcelling<InlineContentCallbackImpl> sParcellingForInlineContentCallback =
|
||
|
Parcelling.Cache.get(
|
||
|
InlineContentCallbackImplParceling.class);
|
||
|
static {
|
||
|
if (sParcellingForInlineContentCallback == null) {
|
||
|
sParcellingForInlineContentCallback = Parcelling.Cache.put(
|
||
|
new InlineContentCallbackImplParceling());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@DataClass.Generated.Member
|
||
|
static Parcelling<InlineTooltipUi> sParcellingForInlineTooltipUi =
|
||
|
Parcelling.Cache.get(
|
||
|
InlineTooltipUiParceling.class);
|
||
|
static {
|
||
|
if (sParcellingForInlineTooltipUi == null) {
|
||
|
sParcellingForInlineTooltipUi = Parcelling.Cache.put(
|
||
|
new InlineTooltipUiParceling());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@DataClass.Generated.Member
|
||
|
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||
|
// You can override field parcelling by defining methods like:
|
||
|
// void parcelFieldName(Parcel dest, int flags) { ... }
|
||
|
|
||
|
byte flg = 0;
|
||
|
if (mContentProvider != null) flg |= 0x2;
|
||
|
if (mInlineContentCallback != null) flg |= 0x4;
|
||
|
if (mInlineTooltipUi != null) flg |= 0x8;
|
||
|
dest.writeByte(flg);
|
||
|
dest.writeTypedObject(mInfo, flags);
|
||
|
if (mContentProvider != null) dest.writeStrongInterface(mContentProvider);
|
||
|
sParcellingForInlineContentCallback.parcel(mInlineContentCallback, dest, flags);
|
||
|
sParcellingForInlineTooltipUi.parcel(mInlineTooltipUi, dest, flags);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@DataClass.Generated.Member
|
||
|
public int describeContents() { return 0; }
|
||
|
|
||
|
/** @hide */
|
||
|
@SuppressWarnings({"unchecked", "RedundantCast"})
|
||
|
@DataClass.Generated.Member
|
||
|
/* package-private */ InlineSuggestion(@NonNull Parcel in) {
|
||
|
// You can override field unparcelling by defining methods like:
|
||
|
// static FieldType unparcelFieldName(Parcel in) { ... }
|
||
|
|
||
|
byte flg = in.readByte();
|
||
|
InlineSuggestionInfo info = (InlineSuggestionInfo) in.readTypedObject(InlineSuggestionInfo.CREATOR);
|
||
|
IInlineContentProvider contentProvider = (flg & 0x2) == 0 ? null : IInlineContentProvider.Stub.asInterface(in.readStrongBinder());
|
||
|
InlineContentCallbackImpl inlineContentCallback = sParcellingForInlineContentCallback.unparcel(in);
|
||
|
InlineTooltipUi inlineTooltipUi = sParcellingForInlineTooltipUi.unparcel(in);
|
||
|
|
||
|
this.mInfo = info;
|
||
|
com.android.internal.util.AnnotationValidations.validate(
|
||
|
NonNull.class, null, mInfo);
|
||
|
this.mContentProvider = contentProvider;
|
||
|
this.mInlineContentCallback = inlineContentCallback;
|
||
|
this.mInlineTooltipUi = inlineTooltipUi;
|
||
|
|
||
|
// onConstructed(); // You can define this method to get a callback
|
||
|
}
|
||
|
|
||
|
@DataClass.Generated.Member
|
||
|
public static final @NonNull Parcelable.Creator<InlineSuggestion> CREATOR
|
||
|
= new Parcelable.Creator<InlineSuggestion>() {
|
||
|
@Override
|
||
|
public InlineSuggestion[] newArray(int size) {
|
||
|
return new InlineSuggestion[size];
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public InlineSuggestion createFromParcel(@NonNull Parcel in) {
|
||
|
return new InlineSuggestion(in);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
@DataClass.Generated(
|
||
|
time = 1615562097666L,
|
||
|
codegenVersion = "1.0.22",
|
||
|
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\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineTooltipUiParceling.class) com.android.internal.view.inline.InlineTooltipUi mInlineTooltipUi\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.widget.inline.InlineContentView>)\nprivate static boolean isValid(int,int,int)\nprivate synchronized android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>,com.android.internal.view.inline.InlineTooltipUi)\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() {}
|
||
|
|
||
|
|
||
|
//@formatter:on
|
||
|
// End of generated code
|
||
|
|
||
|
}
|