diff options
| author | TreeHugger Robot <treehugger-gerrit@google.com> | 2017-03-16 01:33:41 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-03-16 01:33:46 +0000 |
| commit | 5bf03b76408f4e527fc475a793c366583de8896a (patch) | |
| tree | 5df09b1e52f4343f1370a71cbd68ce387328d167 /core/java | |
| parent | 78ccde1c9d91c7833824970ec73c49214f072a7d (diff) | |
| parent | 2ac463e3f5c3b757ecbc7e30e0fc1e8e0d878272 (diff) | |
Merge "Allow users to manually request Autofill."
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/service/autofill/AutofillService.java | 26 | ||||
| -rw-r--r-- | core/java/android/service/autofill/FillCallback.java | 4 | ||||
| -rw-r--r-- | core/java/android/service/autofill/FillResponse.java | 6 | ||||
| -rw-r--r-- | core/java/android/service/autofill/IAutoFillService.aidl | 2 | ||||
| -rw-r--r-- | core/java/android/service/autofill/SaveInfo.java | 1 | ||||
| -rw-r--r-- | core/java/android/view/ViewStructure.java | 6 | ||||
| -rw-r--r-- | core/java/android/view/autofill/AutofillManager.java | 92 | ||||
| -rw-r--r-- | core/java/android/view/autofill/IAutoFillManager.aidl | 2 | ||||
| -rw-r--r-- | core/java/android/widget/Editor.java | 11 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 21 |
10 files changed, 143 insertions, 28 deletions
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java index 29e207358e70..709e5f9e7ef7 100644 --- a/core/java/android/service/autofill/AutofillService.java +++ b/core/java/android/service/autofill/AutofillService.java @@ -30,6 +30,7 @@ import android.os.IBinder; import android.os.ICancellationSignal; import android.os.Looper; import android.util.Log; +import android.view.autofill.AutofillManager; import com.android.internal.os.SomeArgs; @@ -90,6 +91,8 @@ public abstract class AutofillService extends Service { private static final int MSG_ON_FILL_REQUEST = 3; private static final int MSG_ON_SAVE_REQUEST = 4; + private static final int UNUSED_ARG = -1; + private final IAutoFillService mInterface = new IAutoFillService.Stub() { @Override public void onInit(IAutoFillServiceConnection connection) { @@ -102,14 +105,14 @@ public abstract class AutofillService extends Service { @Override public void onFillRequest(AssistStructure structure, Bundle extras, - IFillCallback callback) { + IFillCallback callback, int flags) { ICancellationSignal transport = CancellationSignal.createTransport(); try { callback.onCancellable(transport); } catch (RemoteException e) { e.rethrowFromSystemServer(); } - mHandlerCaller.obtainMessageOOOO(MSG_ON_FILL_REQUEST, structure, + mHandlerCaller.obtainMessageIIOOOO(MSG_ON_FILL_REQUEST, flags, UNUSED_ARG, structure, CancellationSignal.fromTransport(transport), extras, callback) .sendToTarget(); } @@ -135,8 +138,9 @@ public abstract class AutofillService extends Service { final Bundle extras = (Bundle) args.arg3; final IFillCallback callback = (IFillCallback) args.arg4; final FillCallback fillCallback = new FillCallback(callback); + final int flags = msg.arg1; args.recycle(); - onFillRequest(structure, extras, cancellation, fillCallback); + onFillRequest(structure, extras, flags, cancellation, fillCallback); break; } case MSG_ON_SAVE_REQUEST: { final SomeArgs args = (SomeArgs) msg.obj; @@ -188,7 +192,6 @@ public abstract class AutofillService extends Service { * <p>You should generally do initialization here rather than in {@link #onCreate}. */ public void onConnected() { - //TODO(b/33197203): is not called anymore, fix it! } /** @@ -206,11 +209,25 @@ public abstract class AutofillService extends Service { * as well as when filling different sections of the UI as the system will try to * aggressively unbind from the service to conserve resources. See {@link * FillResponse} Javadoc for examples of multiple-sections requests. + * @param flags either {@code 0} or {@link AutofillManager#FLAG_MANUAL_REQUEST}. * @param cancellationSignal signal for observing cancellation requests. The system will use * this to notify you that the fill result is no longer needed and you should stop * handling this fill request in order to save resources. * @param callback object used to notify the result of the request. */ + public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data, int flags, + @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) { + //TODO(b/33197203): make non-abstract once older method is removed + onFillRequest(structure, data, cancellationSignal, callback); + } + + /** + * @hide + * @deprecated - use {@link #onFillRequest(AssistStructure, Bundle, int, + * CancellationSignal, FillCallback)} instead + */ + //TODO(b/33197203): remove once clients are not using anymore + @Deprecated public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data, @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback); @@ -238,7 +255,6 @@ public abstract class AutofillService extends Service { * <p> At this point this service may no longer be an active {@link AutofillService}. */ public void onDisconnected() { - //TODO(b/33197203): is not called anymore, fix it! } /** diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java index 00b206c23ba9..e8ad14f55261 100644 --- a/core/java/android/service/autofill/FillCallback.java +++ b/core/java/android/service/autofill/FillCallback.java @@ -37,7 +37,7 @@ public final class FillCallback { /** * Notifies the Android System that an * {@link AutofillService#onFillRequest(android.app.assist.AssistStructure, Bundle, - * android.os.CancellationSignal, FillCallback)} was successfully fulfilled by the service. + * int, android.os.CancellationSignal, FillCallback)} was successfully fulfilled by the service. * * @param response autofill information for that activity, or {@code null} when the activity * cannot be autofilled (for example, if it only contains read-only fields). See @@ -56,7 +56,7 @@ public final class FillCallback { /** * Notifies the Android System that an * {@link AutofillService#onFillRequest(android.app.assist.AssistStructure, - * Bundle, android.os.CancellationSignal, FillCallback)} + * Bundle, int, android.os.CancellationSignal, FillCallback)} * could not be fulfilled by the service. * * @param message error message to be displayed to the user. diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java index b808de7f7feb..c43019dc297d 100644 --- a/core/java/android/service/autofill/FillResponse.java +++ b/core/java/android/service/autofill/FillResponse.java @@ -31,7 +31,7 @@ import java.util.ArrayList; /** * Response for a {@link * AutofillService#onFillRequest(android.app.assist.AssistStructure, - * Bundle, android.os.CancellationSignal, FillCallback)}. + * Bundle, int, android.os.CancellationSignal, FillCallback)}. * * <p>The response typically contains one or more {@link Dataset}s, each representing a set of * fields that can be autofilled together, and the Android system displays a dataset picker UI @@ -269,8 +269,8 @@ public final class FillResponse implements Parcelable { * Sets a {@link Bundle} that will be passed to subsequent APIs that * manipulate this response. For example, they are passed to subsequent * calls to {@link AutofillService#onFillRequest( - * android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal, - * FillCallback)} and {@link AutofillService#onSaveRequest( + * android.app.assist.AssistStructure, Bundle, int, + * android.os.CancellationSignal, FillCallback)} and {@link AutofillService#onSaveRequest( * android.app.assist.AssistStructure, Bundle, SaveCallback)}. * * @param extras The response extras. diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl index 80685d87a788..9f296c60c6d4 100644 --- a/core/java/android/service/autofill/IAutoFillService.aidl +++ b/core/java/android/service/autofill/IAutoFillService.aidl @@ -31,7 +31,7 @@ import com.android.internal.os.IResultReceiver; oneway interface IAutoFillService { void onInit(in IAutoFillServiceConnection connection); void onFillRequest(in AssistStructure structure, in Bundle extras, - in IFillCallback callback); + in IFillCallback callback, int flags); void onSaveRequest(in AssistStructure structure, in Bundle extras, in ISaveCallback callback); } diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java index 6d368b573fc6..6663f03a6383 100644 --- a/core/java/android/service/autofill/SaveInfo.java +++ b/core/java/android/service/autofill/SaveInfo.java @@ -119,7 +119,6 @@ public final class SaveInfo implements Parcelable { */ public static final int SAVE_DATA_TYPE_PASSWORD = 1; - /** * Type used on when the {@link FillResponse} represents a physical address (such as street, * city, state, etc). diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java index a71b8999987c..38c7738b4bac 100644 --- a/core/java/android/view/ViewStructure.java +++ b/core/java/android/view/ViewStructure.java @@ -350,7 +350,7 @@ public abstract class ViewStructure { * Sets whether the data on this node is sensitive; if it is, then its content (text, autofill * value, etc..) is striped before calls to {@link * android.service.autofill.AutofillService#onFillRequest(android.app.assist.AssistStructure, - * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)}. + * Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback)}. * * <p>By default, all nodes are assumed to be sensitive, and only nodes that does not have PII * (Personally Identifiable Information - sensitive data such as email addresses, credit card @@ -360,8 +360,8 @@ public abstract class ViewStructure { * <p>Notice that the content of even sensitive nodes are sent to the service (through the * {@link * android.service.autofill.AutofillService#onSaveRequest(android.app.assist.AssistStructure, - * Bundle, android.service.autofill.SaveCallback)} call) when the user consented to save the - * data, so it is important to set the content of sensitive nodes as well, but mark them as + * Bundle, android.service.autofill.SaveCallback)} call) when the user consented to save + * thedata, so it is important to set the content of sensitive nodes as well, but mark them as * sensitive. * * <p>Should only be set when the node is used for autofill purposes - it will be ignored diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index c4f90dcbaf3c..f036b9cddec4 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -71,10 +71,17 @@ public final class AutofillManager { public static final String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT"; - /** @hide */ public static final int FLAG_START_SESSION = 0x1; - /** @hide */ public static final int FLAG_VIEW_ENTERED = 0x2; - /** @hide */ public static final int FLAG_VIEW_EXITED = 0x4; - /** @hide */ public static final int FLAG_VALUE_CHANGED = 0x8; + // Public flags start from the lowest bit + /** + * Indicates autofill was explicitly requested by the user. + */ + public static final int FLAG_MANUAL_REQUEST = 0x1; + + // Private flags start from the highest bit + /** @hide */ public static final int FLAG_START_SESSION = 0x80000000; + /** @hide */ public static final int FLAG_VIEW_ENTERED = 0x40000000; + /** @hide */ public static final int FLAG_VIEW_EXITED = 0x20000000; + /** @hide */ public static final int FLAG_VALUE_CHANGED = 0x10000000; private final Rect mTempRect = new Rect(); @@ -121,6 +128,66 @@ public final class AutofillManager { } /** + * Checkes whether autofill is enabled for the current user. + * + * <p>Typically used to determine whether the option to explicitly request autofill should + * be offered - see {@link #requestAutofill(View)}. + * + * @return whether autofill is enabled for the current user. + */ + public boolean isEnabled() { + ensureServiceClientAddedIfNeeded(); + return mEnabled; + } + + /** + * Explicitly requests a new autofill context. + * + * <p>Normally, the autofill context is automatically started when autofillable views are + * focused, but this method should be used in the cases where it must be explicitly requested, + * like a view that provides a contextual menu allowing users to autofill the activity. + * + * @param view view requesting the new autofill context. + */ + public void requestAutofill(@NonNull View view) { + ensureServiceClientAddedIfNeeded(); + + if (!mEnabled) { + return; + } + + final Rect bounds = mTempRect; + view.getBoundsOnScreen(bounds); + final AutofillId id = getAutofillId(view); + final AutofillValue value = view.getAutofillValue(); + + startSession(id, view.getWindowToken(), bounds, value, FLAG_MANUAL_REQUEST); + } + + /** + * Explicitly requests a new autofill context for virtual views. + * + * <p>Normally, the autofill context is automatically started when autofillable views are + * focused, but this method should be used in the cases where it must be explicitly requested, + * like a virtual view that provides a contextual menu allowing users to autofill the activity. + * + * @param view the {@link View} whose descendant is the virtual view. + * @param childId id identifying the virtual child inside the view. + * @param bounds child boundaries, relative to the top window. + */ + public void requestAutofill(@NonNull View view, int childId, @NonNull Rect bounds) { + ensureServiceClientAddedIfNeeded(); + + if (!mEnabled) { + return; + } + + final AutofillId id = getAutofillId(view, childId); + startSession(id, view.getWindowToken(), bounds, null, FLAG_MANUAL_REQUEST); + } + + + /** * Called when a {@link View} that supports autofill is entered. * * @param view {@link View} that was entered. @@ -139,7 +206,7 @@ public final class AutofillManager { if (!mHasSession) { // Starts new session. - startSession(id, view.getWindowToken(), bounds, value); + startSession(id, view.getWindowToken(), bounds, value, 0); } else { // Update focus on existing session. updateSession(id, bounds, value, FLAG_VIEW_ENTERED); @@ -181,7 +248,7 @@ public final class AutofillManager { if (!mHasSession) { // Starts new session. - startSession(id, view.getWindowToken(), bounds, null); + startSession(id, view.getWindowToken(), bounds, null, 0); } else { // Update focus on existing session. updateSession(id, bounds, null, FLAG_VIEW_ENTERED); @@ -224,16 +291,16 @@ public final class AutofillManager { /** * Called to indicate the value of an autofillable virtual {@link View} changed. * - * @param parent parent view whose value changed. + * @param view the {@link View} whose descendant is the virtual view. * @param childId id identifying the virtual child inside the parent view. * @param value new value of the child. */ - public void notifyVirtualValueChanged(View parent, int childId, AutofillValue value) { + public void notifyVirtualValueChanged(View view, int childId, AutofillValue value) { if (!mEnabled || !mHasSession) { return; } - final AutofillId id = getAutofillId(parent, childId); + final AutofillId id = getAutofillId(view, childId); updateSession(id, null, value, FLAG_VALUE_CHANGED); } @@ -305,15 +372,16 @@ public final class AutofillManager { } private void startSession(AutofillId id, IBinder windowToken, Rect bounds, - AutofillValue value) { + AutofillValue value, int flags) { if (DEBUG) { - Log.d(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value); + Log.d(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value + + ", flags=" + flags); } try { mService.startSession(mContext.getActivityToken(), windowToken, mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), - mCallback != null); + mCallback != null, flags); final AutofillClient client = getClient(); if (client != null) { client.resetableStateAvailable(); diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl index 86a49653d367..85b05e585318 100644 --- a/core/java/android/view/autofill/IAutoFillManager.aidl +++ b/core/java/android/view/autofill/IAutoFillManager.aidl @@ -32,7 +32,7 @@ interface IAutoFillManager { boolean addClient(in IAutoFillManagerClient client, int userId); oneway void startSession(in IBinder activityToken, IBinder windowToken, in IBinder appCallback, in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId, - boolean hasCallback); + boolean hasCallback, int flags); oneway void updateSession(in IBinder activityToken, in AutofillId id, in Rect bounds, in AutofillValue value, int flags, int userId); oneway void finishSession(in IBinder activityToken, int userId); diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index ade03e1b7fb4..faa23106e920 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -157,6 +157,7 @@ public class Editor { private static final int MENU_ITEM_ORDER_SELECT_ALL = 9; private static final int MENU_ITEM_ORDER_REPLACE = 10; private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 11; + private static final int MENU_ITEM_ORDER_AUTOFILL = 12; // Each Editor manages its own undo stack. private final UndoManager mUndoManager = new UndoManager(); @@ -2644,6 +2645,10 @@ public class Editor { .setAlphabeticShortcut('a') .setEnabled(mTextView.canSelectAllText()) .setOnMenuItemClickListener(mOnContextMenuItemClickListener); + menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL, + com.android.internal.R.string.autofill) + .setEnabled(mTextView.canRequestAutofill()) + .setOnMenuItemClickListener(mOnContextMenuItemClickListener); mPreserveSelection = true; } @@ -3828,6 +3833,12 @@ public class Editor { .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); } + if (mTextView.canRequestAutofill()) { + menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL, + com.android.internal.R.string.autofill) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + } + updateSelectAllItem(menu); updateReplaceItem(menu); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index d04f70febabb..c5c317d671ef 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -10012,6 +10012,21 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // TODO(b/33197203): add unit/CTS tests for autofill methods + boolean canRequestAutofill() { + final AutofillManager afm = mContext.getSystemService(AutofillManager.class); + if (afm != null) { + return afm.isEnabled(); + } + return false; + } + + private void requestAutofill() { + final AutofillManager afm = mContext.getSystemService(AutofillManager.class); + if (afm != null) { + afm.requestAutofill(this); + } + } + @Override public void autofill(AutofillValue value) { if (value.isText()) { @@ -10481,6 +10496,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener static final int ID_PASTE_AS_PLAIN_TEXT = android.R.id.pasteAsPlainText; static final int ID_REPLACE = android.R.id.replaceText; static final int ID_ASSIST = android.R.id.textAssist; + static final int ID_AUTOFILL = android.R.id.autofill; /** * Called when a context menu option for the text view is selected. Currently @@ -10545,6 +10561,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener case ID_SHARE: shareSelectedText(); return true; + + case ID_AUTOFILL: + requestAutofill(); + stopTextActionMode(); + return true; } return false; } |
