summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2017-05-10 06:18:47 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2017-05-10 06:18:56 +0000
commit90bcc1c8bcf1d716993feafe9a510285a1d2dbc2 (patch)
tree9e3b0328f3d6b9cbd5cd4e1dd599a7a04e2ffdbd /core/java
parent8926f1bb11063f32b25e3db1bd796e55ac4842fb (diff)
parenta9379d0b44ca1f68a0036d2b65218e17fa348514 (diff)
Merge "Allow null fill values to support authentication case" into oc-dev
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/Activity.java7
-rw-r--r--core/java/android/service/autofill/Dataset.java35
-rw-r--r--core/java/android/service/autofill/FillResponse.java3
-rw-r--r--core/java/android/view/autofill/AutofillManager.java61
-rw-r--r--core/java/android/view/autofill/IAutoFillManager.aidl2
-rw-r--r--core/java/android/view/autofill/IAutoFillManagerClient.aidl3
6 files changed, 85 insertions, 26 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 37c287eebf18..26ac6adce95d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -7261,7 +7261,7 @@ public class Activity extends ContextThemeWrapper
}
} else if (who.startsWith(AUTO_FILL_AUTH_WHO_PREFIX)) {
Intent resultData = (resultCode == Activity.RESULT_OK) ? data : null;
- getAutofillManager().onAuthenticationResult(resultData);
+ getAutofillManager().onAuthenticationResult(requestCode, resultData);
} else {
Fragment frag = mFragments.findFragmentByWho(who);
if (frag != null) {
@@ -7406,10 +7406,11 @@ public class Activity extends ContextThemeWrapper
/** @hide */
@Override
- final public void autofillCallbackAuthenticate(IntentSender intent, Intent fillInIntent) {
+ final public void autofillCallbackAuthenticate(int authenticationId, IntentSender intent,
+ Intent fillInIntent) {
try {
startIntentSenderForResultInner(intent, AUTO_FILL_AUTH_WHO_PREFIX,
- 0, fillInIntent, 0, 0, null);
+ authenticationId, fillInIntent, 0, 0, null);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "authenticate() failed for intent:" + intent, e);
}
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index 69f3f6723244..af2eb34f8751 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -162,14 +162,18 @@ public final class Dataset implements Parcelable {
*
* <p>When a user triggers autofill, the system launches the provided intent
* whose extras will have the {@link
- * android.view.autofill.AutofillManager#EXTRA_ASSIST_STRUCTURE screen content}. Once
- * you complete your authentication flow you should set the activity result to {@link
- * android.app.Activity#RESULT_OK} and provide the fully populated {@link Dataset
- * dataset} by setting it to the {@link
- * android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra. For example,
- * if you provided credit card information without the CVV for the data set in the
- * {@link FillResponse response} then the returned data set should contain the
- * CVV entry.</p>
+ * android.view.autofill.AutofillManager#EXTRA_ASSIST_STRUCTURE screen content},
+ * and your {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE client
+ * state}. Once you complete your authentication flow you should set the activity
+ * result to {@link android.app.Activity#RESULT_OK} and provide the fully populated
+ * {@link Dataset dataset} or a fully-populated {@link FillResponse response} by
+ * setting it to the {@link
+ * android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra. If you
+ * provide a dataset in the result, it will replace the authenticated dataset and
+ * will be immediately filled in. If you provide a response, it will replace the
+ * current response and the UI will be refreshed. For example, if you provided
+ * credit card information without the CVV for the data set in the {@link FillResponse
+ * response} then the returned data set should contain the CVV entry.
*
* <p></><strong>Note:</strong> Do not make the provided pending intent
* immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the
@@ -210,12 +214,15 @@ public final class Dataset implements Parcelable {
*
* @param id id returned by {@link
* android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
- * @param value value to be auto filled.
+ * @param value value to be auto filled. Pass {@code null} if you do not have the value
+ * but the target view is a logical part of the dataset. For example, if
+ * the dataset needs an authentication and you have no access to the value.
+ * Filtering matches any user typed string to {@code null} values.
* @return This builder.
* @throws IllegalStateException if the builder was constructed without a presentation
* ({@link RemoteViews}).
*/
- public @NonNull Builder setValue(@NonNull AutofillId id, @NonNull AutofillValue value) {
+ public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value) {
throwIfDestroyed();
if (mPresentation == null) {
throw new IllegalStateException("Dataset presentation not set on constructor");
@@ -229,11 +236,14 @@ public final class Dataset implements Parcelable {
*
* @param id id returned by {@link
* android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
- * @param value value to be auto filled.
+ * @param value value to be auto filled. Pass {@code null} if you do not have the value
+ * but the target view is a logical part of the dataset. For example, if
+ * the dataset needs an authentication and you have no access to the value.
+ * Filtering matches any user typed string to {@code null} values.
* @param presentation The presentation used to visualize this field.
* @return This builder.
*/
- public @NonNull Builder setValue(@NonNull AutofillId id, @NonNull AutofillValue value,
+ public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value,
@NonNull RemoteViews presentation) {
throwIfDestroyed();
Preconditions.checkNotNull(presentation, "presentation cannot be null");
@@ -244,7 +254,6 @@ public final class Dataset implements Parcelable {
private void setValueAndPresentation(AutofillId id, AutofillValue value,
RemoteViews presentation) {
Preconditions.checkNotNull(id, "id cannot be null");
- Preconditions.checkNotNull(value, "value cannot be null");
if (mFieldIds != null) {
final int existingIdx = mFieldIds.indexOf(id);
if (existingIdx >= 0) {
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 1914db9eb438..bc96e439811f 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -236,7 +236,8 @@ public final class FillResponse implements Parcelable {
*
* <p>When a user triggers autofill, the system launches the provided intent
* whose extras will have the {@link AutofillManager#EXTRA_ASSIST_STRUCTURE screen
- * content}. Once you complete your authentication flow you should set the activity
+ * content} and your {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE
+ * client state}. Once you complete your authentication flow you should set the activity
* result to {@link android.app.Activity#RESULT_OK} and provide the fully populated
* {@link FillResponse response} by setting it to the {@link
* AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra.
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index c7151db3cb5c..75a9965e32a8 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -117,6 +117,48 @@ public final class AutofillManager {
/** @hide */ public static final int FLAG_ADD_CLIENT_DEBUG = 0x2;
/** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4;
+ /** Which bits in an authentication id are used for the dataset id */
+ private static final int AUTHENTICATION_ID_DATASET_ID_MASK = 0xFFFF;
+ /** How many bits in an authentication id are used for the dataset id */
+ private static final int AUTHENTICATION_ID_DATASET_ID_SHIFT = 16;
+ /** @hide The index for an undefined data set */
+ public static final int AUTHENTICATION_ID_DATASET_ID_UNDEFINED = 0xFFFF;
+
+ /**
+ * Makes an authentication id from a request id and a dataset id.
+ *
+ * @param requestId The request id.
+ * @param datasetId The dataset id.
+ * @return The authentication id.
+ * @hide
+ */
+ public static int makeAuthenticationId(int requestId, int datasetId) {
+ return (requestId << AUTHENTICATION_ID_DATASET_ID_SHIFT)
+ | (datasetId & AUTHENTICATION_ID_DATASET_ID_MASK);
+ }
+
+ /**
+ * Gets the request id from an authentication id.
+ *
+ * @param authRequestId The authentication id.
+ * @return The request id.
+ * @hide
+ */
+ public static int getRequestIdFromAuthenticationId(int authRequestId) {
+ return (authRequestId >> AUTHENTICATION_ID_DATASET_ID_SHIFT);
+ }
+
+ /**
+ * Gets the dataset id from an authentication id.
+ *
+ * @param authRequestId The authentication id.
+ * @return The dataset id.
+ * @hide
+ */
+ public static int getDatasetIdFromAuthenticationId(int authRequestId) {
+ return (authRequestId & AUTHENTICATION_ID_DATASET_ID_MASK);
+ }
+
private final MetricsLogger mMetricsLogger = new MetricsLogger();
/**
@@ -156,10 +198,12 @@ public final class AutofillManager {
/**
* Asks the client to start an authentication flow.
*
+ * @param authenticationId A unique id of the authentication operation.
* @param intent The authentication intent.
* @param fillInIntent The authentication fill-in intent.
*/
- void autofillCallbackAuthenticate(IntentSender intent, Intent fillInIntent);
+ void autofillCallbackAuthenticate(int authenticationId, IntentSender intent,
+ Intent fillInIntent);
/**
* Tells the client this manager has state to be reset.
@@ -675,7 +719,7 @@ public final class AutofillManager {
}
/** @hide */
- public void onAuthenticationResult(Intent data) {
+ public void onAuthenticationResult(int authenticationId, Intent data) {
if (!hasAutofillFeature()) {
return;
}
@@ -694,7 +738,8 @@ public final class AutofillManager {
final Bundle responseData = new Bundle();
responseData.putParcelable(EXTRA_AUTHENTICATION_RESULT, result);
try {
- mService.setAuthenticationResult(responseData, mSessionId, mContext.getUserId());
+ mService.setAuthenticationResult(responseData, mSessionId, authenticationId,
+ mContext.getUserId());
} catch (RemoteException e) {
Log.e(TAG, "Error delivering authentication result", e);
}
@@ -870,12 +915,13 @@ public final class AutofillManager {
}
}
- private void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) {
+ private void authenticate(int sessionId, int authenticationId, IntentSender intent,
+ Intent fillInIntent) {
synchronized (mLock) {
if (sessionId == mSessionId) {
AutofillClient client = getClientLocked();
if (client != null) {
- client.autofillCallbackAuthenticate(intent, fillInIntent);
+ client.autofillCallbackAuthenticate(authenticationId, intent, fillInIntent);
}
}
}
@@ -1393,11 +1439,12 @@ public final class AutofillManager {
}
@Override
- public void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) {
+ public void authenticate(int sessionId, int authenticationId, IntentSender intent,
+ Intent fillInIntent) {
final AutofillManager afm = mAfm.get();
if (afm != null) {
afm.mContext.getMainThreadHandler().post(
- () -> afm.authenticate(sessionId, intent, fillInIntent));
+ () -> afm.authenticate(sessionId, authenticationId, intent, fillInIntent));
}
}
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 4193a3cbf51c..a12e9560115a 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -41,7 +41,7 @@ interface IAutoFillManager {
in AutofillValue value, int action, int flags, int userId);
void finishSession(int sessionId, int userId);
void cancelSession(int sessionId, int userId);
- void setAuthenticationResult(in Bundle data, int sessionId, int userId);
+ void setAuthenticationResult(in Bundle data, int sessionId, int authenticationId, int userId);
void setHasCallback(int sessionId, int userId, boolean hasIt);
void disableOwnedAutofillServices(int userId);
boolean isServiceSupported(int userId);
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 825d311a5b3b..1d66f7f7f463 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -45,7 +45,8 @@ oneway interface IAutoFillManagerClient {
/**
* Authenticates a fill response or a data set.
*/
- void authenticate(int sessionId, in IntentSender intent, in Intent fillInIntent);
+ void authenticate(int sessionId, int authenticationId, in IntentSender intent,
+ in Intent fillInIntent);
/**
* Sets the views to track. If saveOnAllViewsInvisible is set and all these view are invisible