summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2017-03-16 01:33:41 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2017-03-16 01:33:46 +0000
commit5bf03b76408f4e527fc475a793c366583de8896a (patch)
tree5df09b1e52f4343f1370a71cbd68ce387328d167 /core/java
parent78ccde1c9d91c7833824970ec73c49214f072a7d (diff)
parent2ac463e3f5c3b757ecbc7e30e0fc1e8e0d878272 (diff)
Merge "Allow users to manually request Autofill."
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/service/autofill/AutofillService.java26
-rw-r--r--core/java/android/service/autofill/FillCallback.java4
-rw-r--r--core/java/android/service/autofill/FillResponse.java6
-rw-r--r--core/java/android/service/autofill/IAutoFillService.aidl2
-rw-r--r--core/java/android/service/autofill/SaveInfo.java1
-rw-r--r--core/java/android/view/ViewStructure.java6
-rw-r--r--core/java/android/view/autofill/AutofillManager.java92
-rw-r--r--core/java/android/view/autofill/IAutoFillManager.aidl2
-rw-r--r--core/java/android/widget/Editor.java11
-rw-r--r--core/java/android/widget/TextView.java21
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;
}