Merge "Fix on click listener for the inline suggestion, and some refactoring."

This commit is contained in:
TreeHugger Robot
2020-01-17 20:51:12 +00:00
committed by Android (Google) Code Review
5 changed files with 100 additions and 128 deletions

View File

@@ -20,23 +20,24 @@ import static com.android.server.autofill.Helper.sDebug;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.slice.Slice;
import android.content.Context;
import android.os.Handler;
import android.os.RemoteException;
import android.service.autofill.Dataset;
import android.service.autofill.InlinePresentation;
import android.util.Slog;
import android.view.SurfaceControl;
import android.view.View;
import android.view.autofill.AutofillId;
import android.view.autofill.IAutoFillManagerClient;
import android.view.inline.InlinePresentationSpec;
import android.view.inputmethod.InlineSuggestion;
import android.view.inputmethod.InlineSuggestionInfo;
import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.inputmethod.InlineSuggestionsResponse;
import com.android.internal.view.inline.IInlineContentCallback;
import com.android.internal.view.inline.IInlineContentProvider;
import com.android.server.UiThread;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.autofill.ui.InlineSuggestionUi;
import java.util.ArrayList;
@@ -56,23 +57,59 @@ public final class InlineSuggestionFactory {
int sessionId,
@NonNull Dataset[] datasets,
@NonNull AutofillId autofillId,
@NonNull InlineSuggestionsRequest request,
@NonNull Handler uiHandler,
@NonNull Context context,
@NonNull IAutoFillManagerClient client) {
if (sDebug) Slog.d(TAG, "createAugmentedInlineSuggestionsResponse called");
final ArrayList<InlineSuggestion> inlineSuggestions = new ArrayList<>();
final InlineSuggestionUi inlineSuggestionUi = new InlineSuggestionUi(context);
for (Dataset dataset : datasets) {
final int fieldIndex = dataset.getFieldIds().indexOf(autofillId);
if (fieldIndex < 0) {
Slog.w(TAG, "AutofillId=" + autofillId + " not found in dataset");
return null;
}
final InlinePresentation inlinePresentation = dataset.getFieldInlinePresentation(
fieldIndex);
if (inlinePresentation == null) {
Slog.w(TAG, "InlinePresentation not found in dataset");
return null;
}
InlineSuggestion inlineSuggestion = createAugmentedInlineSuggestion(sessionId, dataset,
inlinePresentation, inlineSuggestionUi, client);
inlineSuggestions.add(inlineSuggestion);
}
return new InlineSuggestionsResponse(inlineSuggestions);
}
/**
* Creates an {@link InlineSuggestionsResponse} with the {@code datasets} provided by the
* autofill service.
*/
public static InlineSuggestionsResponse createInlineSuggestionsResponse(int requestId,
@NonNull Dataset[] datasets,
@NonNull AutofillId autofillId,
@NonNull Context context,
@NonNull AutoFillUI.AutoFillUiCallback client) {
if (sDebug) Slog.d(TAG, "createInlineSuggestionsResponse called");
final ArrayList<InlineSuggestion> inlineSuggestions = new ArrayList<>();
final InlineSuggestionUi inlineSuggestionUi = new InlineSuggestionUi(context);
for (Dataset dataset : datasets) {
// TODO(b/146453195): use the spec in the dataset.
InlinePresentationSpec spec = request.getPresentationSpecs().get(0);
if (spec == null) {
Slog.w(TAG, "InlinePresentationSpec is not provided in the response data set");
continue;
final int fieldIndex = dataset.getFieldIds().indexOf(autofillId);
if (fieldIndex < 0) {
Slog.w(TAG, "AutofillId=" + autofillId + " not found in dataset");
return null;
}
InlineSuggestion inlineSuggestion = createAugmentedInlineSuggestion(sessionId, dataset,
autofillId, spec, uiHandler, inlineSuggestionUi, client);
final InlinePresentation inlinePresentation = dataset.getFieldInlinePresentation(
fieldIndex);
if (inlinePresentation == null) {
Slog.w(TAG, "InlinePresentation not found in dataset");
return null;
}
InlineSuggestion inlineSuggestion = createInlineSuggestion(requestId, dataset,
fieldIndex,
inlinePresentation, inlineSuggestionUi, client);
inlineSuggestions.add(inlineSuggestion);
}
return new InlineSuggestionsResponse(inlineSuggestions);
@@ -80,33 +117,55 @@ public final class InlineSuggestionFactory {
private static InlineSuggestion createAugmentedInlineSuggestion(int sessionId,
@NonNull Dataset dataset,
@NonNull AutofillId autofillId,
@NonNull InlinePresentationSpec spec,
@NonNull Handler uiHandler,
@NonNull InlinePresentation inlinePresentation,
@NonNull InlineSuggestionUi inlineSuggestionUi,
@NonNull IAutoFillManagerClient client) {
// TODO(b/146453195): fill in the autofill hint properly.
final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
spec, InlineSuggestionInfo.SOURCE_PLATFORM, new String[]{""});
final View.OnClickListener onClickListener = createOnClickListener(sessionId, dataset,
client);
inlinePresentation.getInlinePresentationSpec(),
InlineSuggestionInfo.SOURCE_PLATFORM, new String[]{""});
final View.OnClickListener onClickListener = v -> {
try {
client.autofill(sessionId, dataset.getFieldIds(), dataset.getFieldValues());
} catch (RemoteException e) {
Slog.w(TAG, "Encounter exception autofilling the values");
}
};
final InlineSuggestion inlineSuggestion = new InlineSuggestion(inlineSuggestionInfo,
createInlineContentProvider(autofillId, dataset, uiHandler, inlineSuggestionUi,
createInlineContentProvider(inlinePresentation.getSlice(), inlineSuggestionUi,
onClickListener));
return inlineSuggestion;
}
private static InlineSuggestion createInlineSuggestion(int requestId,
@NonNull Dataset dataset,
int fieldIndex,
@NonNull InlinePresentation inlinePresentation,
@NonNull InlineSuggestionUi inlineSuggestionUi,
@NonNull AutoFillUI.AutoFillUiCallback client) {
// TODO(b/146453195): fill in the autofill hint properly.
final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
inlinePresentation.getInlinePresentationSpec(),
InlineSuggestionInfo.SOURCE_AUTOFILL, new String[]{""});
final View.OnClickListener onClickListener = v -> {
client.fill(requestId, fieldIndex, dataset);
};
final InlineSuggestion inlineSuggestion = new InlineSuggestion(inlineSuggestionInfo,
createInlineContentProvider(inlinePresentation.getSlice(), inlineSuggestionUi,
onClickListener));
return inlineSuggestion;
}
private static IInlineContentProvider.Stub createInlineContentProvider(
@NonNull AutofillId autofillId, @NonNull Dataset dataset, @NonNull Handler uiHandler,
@NonNull InlineSuggestionUi inlineSuggestionUi,
@NonNull Slice slice, @NonNull InlineSuggestionUi inlineSuggestionUi,
@Nullable View.OnClickListener onClickListener) {
return new IInlineContentProvider.Stub() {
@Override
public void provideContent(int width, int height,
IInlineContentCallback callback) {
uiHandler.post(() -> {
SurfaceControl sc = inlineSuggestionUi.inflate(dataset, autofillId,
width, height, onClickListener);
UiThread.getHandler().post(() -> {
SurfaceControl sc = inlineSuggestionUi.inflate(slice, width, height,
onClickListener);
try {
callback.onContent(sc);
} catch (RemoteException e) {
@@ -117,19 +176,6 @@ public final class InlineSuggestionFactory {
};
}
private static View.OnClickListener createOnClickListener(int sessionId,
@NonNull Dataset dataset,
@NonNull IAutoFillManagerClient client) {
return v -> {
if (sDebug) Slog.d(TAG, "Inline suggestion clicked");
try {
client.autofill(sessionId, dataset.getFieldIds(), dataset.getFieldValues());
} catch (RemoteException e) {
Slog.w(TAG, "Encounter exception autofilling the values");
}
};
}
private InlineSuggestionFactory() {
}
}

View File

@@ -161,8 +161,7 @@ final class RemoteAugmentedAutofillService
@Override
public void onSuccess(@Nullable Dataset[] inlineSuggestionsData) {
maybeHandleInlineSuggestions(sessionId, inlineSuggestionsData,
focusedId, inlineSuggestionsRequest,
inlineSuggestionsCallback, client);
focusedId, inlineSuggestionsCallback, client);
requestAutofill.complete(null);
}
@@ -226,19 +225,15 @@ final class RemoteAugmentedAutofillService
private void maybeHandleInlineSuggestions(int sessionId,
@Nullable Dataset[] inlineSuggestionsData, @NonNull AutofillId focusedId,
@Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
@Nullable IInlineSuggestionsResponseCallback inlineSuggestionsCallback,
@NonNull IAutoFillManagerClient client) {
if (inlineSuggestionsRequest == null
|| ArrayUtils.isEmpty(inlineSuggestionsData)
|| inlineSuggestionsCallback == null) {
if (ArrayUtils.isEmpty(inlineSuggestionsData) || inlineSuggestionsCallback == null) {
return;
}
try {
inlineSuggestionsCallback.onInlineSuggestionsResponse(
InlineSuggestionFactory.createAugmentedInlineSuggestionsResponse(
sessionId, inlineSuggestionsData, focusedId, inlineSuggestionsRequest,
getJobHandler(), mContext, client));
InlineSuggestionFactory.createAugmentedInlineSuggestionsResponse(sessionId,
inlineSuggestionsData, focusedId, mContext, client));
} catch (RemoteException e) {
Slog.w(TAG, "Exception sending inline suggestions response back to IME.");
}

View File

@@ -71,7 +71,6 @@ import android.service.autofill.FieldClassificationUserData;
import android.service.autofill.FillContext;
import android.service.autofill.FillRequest;
import android.service.autofill.FillResponse;
import android.service.autofill.InlinePresentation;
import android.service.autofill.InternalSanitizer;
import android.service.autofill.InternalValidator;
import android.service.autofill.SaveInfo;
@@ -93,9 +92,6 @@ import android.view.autofill.AutofillManager.SmartSuggestionMode;
import android.view.autofill.AutofillValue;
import android.view.autofill.IAutoFillManagerClient;
import android.view.autofill.IAutofillWindowPresenter;
import android.view.inline.InlinePresentationSpec;
import android.view.inputmethod.InlineSuggestion;
import android.view.inputmethod.InlineSuggestionInfo;
import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.inputmethod.InlineSuggestionsResponse;
@@ -106,8 +102,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
import com.android.internal.view.IInlineSuggestionsRequestCallback;
import com.android.internal.view.IInlineSuggestionsResponseCallback;
import com.android.internal.view.inline.IInlineContentCallback;
import com.android.internal.view.inline.IInlineContentProvider;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.autofill.ui.PendingUi;
import com.android.server.inputmethod.InputMethodManagerInternal;
@@ -148,6 +142,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private final Handler mHandler;
private final Object mLock;
private final AutoFillUI mUi;
private final Context mContext;
private final MetricsLogger mMetricsLogger = new MetricsLogger();
@@ -773,6 +768,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mLock = lock;
mUi = ui;
mHandler = handler;
mContext = context;
mRemoteFillService = serviceComponentName == null ? null
: new RemoteFillService(context, serviceComponentName, userId, this,
bindInstantServiceAllowed);
@@ -2733,35 +2729,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return false;
}
final int size = datasets.size();
final ArrayList<InlineSuggestion> inlineSuggestions = new ArrayList<>();
for (int index = 0; index < size; index++) {
final Dataset dataset = datasets.get(index);
//TODO(b/146453536): Use the proper presentation/spec for currently focused view.
final InlinePresentation inlinePresentation = dataset.getFieldInlinePresentation(0);
if (inlinePresentation == null) {
if (sDebug) Log.d(TAG, "Missing InlinePresentation on dataset=" + dataset);
continue;
}
final InlinePresentationSpec spec = inlinePresentation.getInlinePresentationSpec();
final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
spec, InlineSuggestionInfo.SOURCE_AUTOFILL, new String[] { "" });
inlineSuggestions.add(new InlineSuggestion(inlineSuggestionInfo,
new IInlineContentProvider.Stub() {
@Override
public void provideContent(int width, int height,
IInlineContentCallback callback) throws RemoteException {
getUiForShowing().getSuggestionSurfaceForShowing(dataset, response,
mCurrentViewId, width, height, callback);
}
}));
}
InlineSuggestionsResponse inlineSuggestionsResponse =
InlineSuggestionFactory.createInlineSuggestionsResponse(response.getRequestId(),
datasets.toArray(new Dataset[]{}), mCurrentViewId, mContext, this);
try {
inlineContentCallback.onInlineSuggestionsResponse(
new InlineSuggestionsResponse(inlineSuggestions));
inlineContentCallback.onInlineSuggestionsResponse(inlineSuggestionsResponse);
} catch (RemoteException e) {
Log.w(TAG, "onFillReady() remote error calling onInlineSuggestionsResponse()");
return false;

View File

@@ -37,7 +37,6 @@ import android.service.autofill.ValueFinder;
import android.text.TextUtils;
import android.util.Slog;
import android.view.KeyEvent;
import android.view.SurfaceControl;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.IAutofillWindowPresenter;
@@ -45,7 +44,6 @@ import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.view.inline.IInlineContentCallback;
import com.android.server.LocalServices;
import com.android.server.UiModeManagerInternal;
import com.android.server.UiThread;
@@ -172,36 +170,6 @@ public final class AutoFillUI {
});
}
/**
* TODO(b/137800469): Fill in javadoc.
* TODO(b/137800469): peoperly manage lifecycle of suggestions surfaces.
*/
public void getSuggestionSurfaceForShowing(@NonNull Dataset dataset,
@NonNull FillResponse response, AutofillId autofillId, int width, int height,
IInlineContentCallback cb) {
if (dataset == null) {
Slog.w(TAG, "getSuggestionSurfaceForShowing() called with null dataset");
}
mHandler.post(() -> {
final InlineSuggestionUi inlineSuggestionUi = new InlineSuggestionUi(mContext);
final SurfaceControl suggestionSurface = inlineSuggestionUi.inflate(dataset,
autofillId, width, height, v -> {
Slog.d(TAG, "Inline suggestion clicked");
hideFillUiUiThread(mCallback, true);
if (mCallback != null) {
final int datasetIndex = response.getDatasets().indexOf(dataset);
mCallback.fill(response.getRequestId(), datasetIndex, dataset);
}
});
try {
cb.onContent(suggestionSurface);
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException replying onContent(" + suggestionSurface + "): " + e);
}
});
}
/**
* Shows the fill UI, removing the previous fill UI if the has changed.
*

View File

@@ -28,17 +28,13 @@ import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.drawable.Icon;
import android.os.IBinder;
import android.service.autofill.Dataset;
import android.util.Log;
import android.util.Slog;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import android.widget.ImageView;
import android.widget.TextView;
@@ -69,23 +65,18 @@ public class InlineSuggestionUi {
*/
@MainThread
@Nullable
public SurfaceControl inflate(@NonNull Dataset dataset, @NonNull AutofillId autofillId,
int width, int height, @Nullable View.OnClickListener onClickListener) {
public SurfaceControl inflate(@NonNull Slice slice, int width, int height,
@Nullable View.OnClickListener onClickListener) {
Log.d(TAG, "Inflating the inline suggestion UI");
final int index = dataset.getFieldIds().indexOf(autofillId);
if (index < 0) {
Slog.w(TAG, "inflateInlineSuggestion(): AutofillId=" + autofillId
+ " not found in dataset");
return null;
}
final AutofillValue datasetValue = dataset.getFieldValues().get(index);
//TODO(b/137800469): Pass in inputToken from IME.
final SurfaceControlViewHost wvr = new SurfaceControlViewHost(mContext,
mContext.getDisplay(), (IBinder) null);
final SurfaceControl sc = wvr.getSurfacePackage().getSurfaceControl();
final ViewGroup suggestionView =
(ViewGroup) renderSlice(dataset.getFieldInlinePresentation(index).getSlice());
final ViewGroup suggestionView = (ViewGroup) renderSlice(slice);
if (onClickListener != null) {
suggestionView.setOnClickListener(onClickListener);
}
WindowManager.LayoutParams lp =
new WindowManager.LayoutParams(width, height,