From 7f33cd350be4278ce5d4ef460c11e4dbaf9c473b Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Thu, 11 May 2017 10:10:49 -0700 Subject: [PATCH] Start a new session on manual request after session is "gone". When the autofill service returns a null FillResponse, the session is marked "gone" because the service cannot autofill it. But there might be cases where the view structure change and it's now autofillable, so need to allow users to manually request autofill again in such cases. Fixes: 38205945 Test: CtsAutoFillServiceTestCases pass Test: LoginActivityTest.testAutofillManuallyAfterServiceReturnedNoDatasets() Test: LoginActivityTest.testAutofillManuallyAndSaveAfterServiceReturnedNoDatasets() Change-Id: I9b23c255e563dd0646bf266d31ddb10dcc4f7f6d --- .../android/app/assist/AssistStructure.java | 6 ++-- .../view/autofill/AutofillManager.java | 21 ++++++++++++-- .../view/autofill/IAutoFillManager.aidl | 3 ++ .../autofill/AutofillManagerService.java | 28 ++++++++++++++++--- .../autofill/AutofillManagerServiceImpl.java | 27 ++++++++++++------ 5 files changed, 68 insertions(+), 17 deletions(-) diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 861c73d45284a..c613d9706e645 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -862,10 +862,10 @@ public class AssistStructure implements Parcelable { out.writeInt(mAutofillType); out.writeStringArray(mAutofillHints); final AutofillValue sanitizedValue; - if (mAutofillOverlay != null && mAutofillOverlay.value != null) { - sanitizedValue = mAutofillOverlay.value; - } else if (writeSensitive) { + if (writeSensitive) { sanitizedValue = mAutofillValue; + } else if (mAutofillOverlay != null && mAutofillOverlay.value != null) { + sanitizedValue = mAutofillOverlay.value; } else { sanitizedValue = null; } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 68c74da6a7c4e..39ac39951d23e 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -804,9 +804,26 @@ public final class AutofillManager { + ", value=" + value + ", action=" + action + ", flags=" + flags); } + boolean restartIfNecessary = (flags & FLAG_MANUAL_REQUEST) != 0; + try { - mService.updateSession(mSessionId, id, bounds, value, action, flags, - mContext.getUserId()); + if (restartIfNecessary) { + final int newId = mService.updateOrRestartSession(mContext.getActivityToken(), + mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), + mCallback != null, flags, mContext.getOpPackageName(), mSessionId, action); + if (newId != mSessionId) { + if (sDebug) Log.d(TAG, "Session restarted: " + mSessionId + "=>" + newId); + mSessionId = newId; + final AutofillClient client = getClientLocked(); + if (client != null) { + client.autofillCallbackResetableStateAvailable(); + } + } + } else { + mService.updateSession(mSessionId, id, bounds, value, action, flags, + mContext.getUserId()); + } + } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl index a12e9560115a9..627afa7f83649 100644 --- a/core/java/android/view/autofill/IAutoFillManager.aidl +++ b/core/java/android/view/autofill/IAutoFillManager.aidl @@ -39,6 +39,9 @@ interface IAutoFillManager { boolean restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback); void updateSession(int sessionId, in AutofillId id, in Rect bounds, in AutofillValue value, int action, int flags, int userId); + int updateOrRestartSession(IBinder activityToken, in IBinder appCallback, + in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId, + boolean hasCallback, int flags, String packageName, int sessionId, int action); void finishSession(int sessionId, int userId); void cancelSession(int sessionId, int userId); void setAuthenticationResult(in Bundle data, int sessionId, int authenticationId, int userId); diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index cbeaa3e20f34b..93b5ed5e23d7c 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -172,7 +172,6 @@ public final class AutofillManagerService extends SystemService { startTrackingPackageChanges(); } - private void startTrackingPackageChanges() { PackageMonitor monitor = new PackageMonitor() { @Override @@ -559,17 +558,38 @@ public final class AutofillManagerService extends SystemService { } @Override - public void updateSession(int sessionId, AutofillId id, Rect bounds, + public void updateSession(int sessionId, AutofillId autoFillId, Rect bounds, AutofillValue value, int action, int flags, int userId) { synchronized (mLock) { final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); if (service != null) { - service.updateSessionLocked(sessionId, getCallingUid(), id, bounds, value, - action, flags); + service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds, + value, action, flags); } } } + @Override + public int updateOrRestartSession(IBinder activityToken, IBinder appCallback, + AutofillId autoFillId, Rect bounds, AutofillValue value, int userId, + boolean hasCallback, int flags, String packageName, int sessionId, int action) { + boolean restart = false; + synchronized (mLock) { + final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); + if (service != null) { + restart = service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, + bounds, value, action, flags); + } + } + if (restart) { + return startSession(activityToken, appCallback, autoFillId, bounds, value, userId, + hasCallback, flags, packageName); + } + + // Nothing changed... + return sessionId; + } + @Override public void finishSession(int sessionId, int userId) { synchronized (mLock) { diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 35371a746b6d3..2cb0bd5d1064a 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -16,6 +16,7 @@ package com.android.server.autofill; +import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; import static android.view.autofill.AutofillManager.ACTION_START_SESSION; import static android.view.autofill.AutofillManager.NO_SESSION; @@ -275,7 +276,7 @@ final class AutofillManagerServiceImpl { pruneAbandonedSessionsLocked(); final Session newSession = createSessionByTokenLocked(activityToken, uid, appCallbackToken, - hasCallback, flags, packageName); + hasCallback, packageName); if (newSession == null) { return NO_SESSION; } @@ -359,8 +360,7 @@ final class AutofillManagerServiceImpl { } private Session createSessionByTokenLocked(@NonNull IBinder activityToken, int uid, - @NonNull IBinder appCallbackToken, boolean hasCallback, int flags, - @NonNull String packageName) { + @NonNull IBinder appCallbackToken, boolean hasCallback, @NonNull String packageName) { // use random ids so that one app cannot know that another app creates sessions int sessionId; int tries = 0; @@ -402,18 +402,29 @@ final class AutofillManagerServiceImpl { } } - void updateSessionLocked(int sessionId, int uid, AutofillId autofillId, Rect virtualBounds, + /** + * Updates a session and returns whether it should be restarted. + */ + boolean updateSessionLocked(int sessionId, int uid, AutofillId autofillId, Rect virtualBounds, AutofillValue value, int action, int flags) { final Session session = mSessions.get(sessionId); if (session == null || session.uid != uid) { - if (sVerbose) { - Slog.v(TAG, "updateSessionLocked(): session gone for " + sessionId + "(" + uid - + ")"); + if ((flags & FLAG_MANUAL_REQUEST) != 0) { + if (sDebug) { + Slog.d(TAG, "restarting session " + sessionId + " due to manual request on " + + autofillId); + } + return true; } - return; + if (sVerbose) { + Slog.v(TAG, "updateSessionLocked(): session gone for " + sessionId + + "(" + uid + ")"); + } + return false; } session.updateLocked(autofillId, virtualBounds, value, action, flags); + return false; } void removeSessionLocked(int sessionId) {