From 4bcb01a3b588fe17717cb95ed1aa1ddd297c6ad0 Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Tue, 21 Nov 2017 16:47:13 -0800 Subject: [PATCH] New Autofill API: SaveCallback.onSuccess(IntentSender). This overloaded method is useful for cases where the service needs to launch an activity (for example, to unlock the user's vault), in which case it's launched from the context of the activity being filled. Test: atest CtsAutoFillServiceTestCases:SimpleSaveActivityTest#testSave_launchIntent Test: atest CtsAutoFillServiceTestCases Fixes: 69458616 Change-Id: I41bf5fd4954c38051e3275f2e8500a00dcf24724 --- api/current.txt | 1 + .../service/autofill/ISaveCallback.aidl | 4 +- .../service/autofill/SaveCallback.java | 39 ++++++++++++++----- proto/src/metrics_constants.proto | 3 +- .../server/autofill/RemoteFillService.java | 14 ++++--- .../com/android/server/autofill/Session.java | 9 ++++- 6 files changed, 51 insertions(+), 19 deletions(-) diff --git a/api/current.txt b/api/current.txt index c1188dcd330b3..93b6b424458f9 100644 --- a/api/current.txt +++ b/api/current.txt @@ -37499,6 +37499,7 @@ package android.service.autofill { public final class SaveCallback { method public void onFailure(java.lang.CharSequence); method public void onSuccess(); + method public void onSuccess(android.content.IntentSender); } public final class SaveInfo implements android.os.Parcelable { diff --git a/core/java/android/service/autofill/ISaveCallback.aidl b/core/java/android/service/autofill/ISaveCallback.aidl index e260c7375cc57..a9364fe5ccba3 100644 --- a/core/java/android/service/autofill/ISaveCallback.aidl +++ b/core/java/android/service/autofill/ISaveCallback.aidl @@ -16,12 +16,14 @@ package android.service.autofill; +import android.content.IntentSender; + /** * Interface to receive the result of a save request. * * @hide */ interface ISaveCallback { - void onSuccess(); + void onSuccess(in IntentSender intentSender); void onFailure(CharSequence message); } diff --git a/core/java/android/service/autofill/SaveCallback.java b/core/java/android/service/autofill/SaveCallback.java index 7207f1df3ee56..855981a544fd7 100644 --- a/core/java/android/service/autofill/SaveCallback.java +++ b/core/java/android/service/autofill/SaveCallback.java @@ -16,9 +16,14 @@ package android.service.autofill; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.Activity; +import android.content.IntentSender; import android.os.RemoteException; +import com.android.internal.util.Preconditions; + /** * Handles save requests from the {@link AutofillService} into the {@link Activity} being * autofilled. @@ -36,18 +41,33 @@ public final class SaveCallback { * Notifies the Android System that an * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} was successfully handled * by the service. - * - *

If the service could not handle the request right away—for example, because it must - * launch an activity asking the user to authenticate first or because the network is - * down—it should still call {@link #onSuccess()}. - * - * @throws RuntimeException if an error occurred while calling the Android System. */ public void onSuccess() { + onSuccessInternal(null); + } + + /** + * Notifies the Android System that an + * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} was successfully handled + * by the service. + * + *

This method is useful when the service requires extra work—for example, launching an + * activity asking the user to authenticate first —before it can process the request, + * as the intent will be launched from the context of the activity being autofilled and hence + * will be part of that activity's stack. + * + * @param intentSender intent that will be launched from the context of activity being + * autofilled. + */ + public void onSuccess(@NonNull IntentSender intentSender) { + onSuccessInternal(Preconditions.checkNotNull(intentSender)); + } + + private void onSuccessInternal(@Nullable IntentSender intentSender) { assertNotCalled(); mCalled = true; try { - mCallback.onSuccess(); + mCallback.onSuccess(intentSender); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } @@ -63,11 +83,10 @@ public final class SaveCallback { * the {@link SaveRequest} and call {@link #onSuccess()} instead. * *

Note: The Android System displays an UI with the supplied error message; if - * you prefer to show your own message, call {@link #onSuccess()} instead. + * you prefer to show your own message, call {@link #onSuccess()} or + * {@link #onSuccess(IntentSender)} instead. * * @param message error message to be displayed to the user. - * - * @throws RuntimeException if an error occurred while calling the Android System. */ public void onFailure(CharSequence message) { assertNotCalled(); diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 98efd522970b7..83a1158edcee1 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -3761,7 +3761,8 @@ message MetricsEvent { FIELD_AUTOFILL_NUM_IDS = 917; // ACTION: An autofill service was reqiested to save data - // Type TYPE_SUCCESS: The request succeeded + // Type TYPE_SUCCESS: The request succeeded right away + // Type TYPE_OPEN: The request succeeded but the service launched an IntentSender // Type TYPE_FAILURE: The request failed // Package: Package of app that was autofilled // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index af55807ff1f04..831c488e95b27 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -26,6 +26,7 @@ import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentSender; import android.content.ServiceConnection; import android.os.Handler; import android.os.IBinder; @@ -100,7 +101,8 @@ final class RemoteFillService implements DeathRecipient { @NonNull String servicePackageName); void onFillRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName); - void onSaveRequestSuccess(@NonNull String servicePackageName); + void onSaveRequestSuccess(@NonNull String servicePackageName, + @Nullable IntentSender intentSender); void onSaveRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName); void onServiceDied(RemoteFillService service); @@ -308,10 +310,11 @@ final class RemoteFillService implements DeathRecipient { }); } - private void dispatchOnSaveRequestSuccess(PendingRequest pendingRequest) { + private void dispatchOnSaveRequestSuccess(PendingRequest pendingRequest, + IntentSender intentSender) { mHandler.getHandler().post(() -> { if (handleResponseCallbackCommon(pendingRequest)) { - mCallbacks.onSaveRequestSuccess(mComponentName.getPackageName()); + mCallbacks.onSaveRequestSuccess(mComponentName.getPackageName(), intentSender); } }); } @@ -624,12 +627,13 @@ final class RemoteFillService implements DeathRecipient { mCallback = new ISaveCallback.Stub() { @Override - public void onSuccess() { + public void onSuccess(IntentSender intentSender) { if (!finish()) return; final RemoteFillService remoteService = getService(); if (remoteService != null) { - remoteService.dispatchOnSaveRequestSuccess(PendingSaveRequest.this); + remoteService.dispatchOnSaveRequestSuccess(PendingSaveRequest.this, + intentSender); } } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 974148623b003..99b92b9c9cd46 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -561,7 +561,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // FillServiceCallbacks @Override - public void onSaveRequestSuccess(@NonNull String servicePackageName) { + public void onSaveRequestSuccess(@NonNull String servicePackageName, + @Nullable IntentSender intentSender) { synchronized (mLock) { mIsSaving = false; @@ -572,8 +573,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST, servicePackageName) - .setType(MetricsEvent.TYPE_SUCCESS); + .setType(intentSender == null ? MetricsEvent.TYPE_SUCCESS : MetricsEvent.TYPE_OPEN); mMetricsLogger.write(log); + if (intentSender != null) { + if (sDebug) Slog.d(TAG, "Starting intent sender on save()"); + startIntentSender(intentSender); + } // Nothing left to do... removeSelf();