diff options
7 files changed, 337 insertions, 50 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 34aecdc88bac..695efddc726e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -7642,7 +7642,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return mContext.getSystemService(AutofillManager.class); } - private boolean isAutofillable() { + /** @hide */ + public boolean isAutofillable() { return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutofillBlocked(); } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 6e02a844c022..9ee0cb1f811e 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -400,7 +400,6 @@ public final class AutofillManager { } } - /** * Called when a {@link View} that supports autofill is entered. * @@ -780,8 +779,12 @@ public final class AutofillManager { throw e.rethrowFromSystemServer(); } - mTrackedViews = null; + resetSessionLocked(); + } + + private void resetSessionLocked() { mSessionId = NO_SESSION; + mTrackedViews = null; } private void updateSessionLocked(AutofillId id, Rect bounds, AutofillValue value, int flags) { @@ -903,9 +906,17 @@ public final class AutofillManager { } } - private void setState(boolean enabled) { + private void setState(boolean enabled, boolean resetSession, boolean resetClient) { synchronized (mLock) { mEnabled = enabled; + if (!mEnabled || resetSession) { + // Reset the session state + resetSessionLocked(); + } + if (resetClient) { + // Reset connection to system + mServiceClient = null; + } } } @@ -1025,13 +1036,14 @@ public final class AutofillManager { AutofillCallback callback = null; synchronized (mLock) { - if (mSessionId == sessionId) { - AutofillClient client = getClientLocked(); - - if (client != null) { - if (client.autofillCallbackRequestHideFillUi() && mCallback != null) { - callback = mCallback; - } + // We do not check the session id for two reasons: + // 1. If local and remote session id are off sync the UI would be stuck shown + // 2. There is a race between the user state being destroyed due the fill + // service being uninstalled and the UI being dismissed. + AutofillClient client = getClientLocked(); + if (client != null) { + if (client.autofillCallbackRequestHideFillUi() && mCallback != null) { + callback = mCallback; } } } @@ -1343,10 +1355,11 @@ public final class AutofillManager { } @Override - public void setState(boolean enabled) { + public void setState(boolean enabled, boolean resetSession, boolean resetClient) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.mContext.getMainThreadHandler().post(() -> afm.setState(enabled)); + afm.mContext.getMainThreadHandler().post( + () -> afm.setState(enabled, resetSession, resetClient)); } } diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl index 1a6bad2d1cd6..aef98b706aea 100644 --- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl +++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl @@ -35,7 +35,7 @@ oneway interface IAutoFillManagerClient { /** * Notifies the client when the autofill enabled state changed. */ - void setState(boolean enabled); + void setState(boolean enabled, boolean resetSession, boolean resetClient); /** * Autofills the activity with the contents of a dataset. diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 399cfac441a9..406386aa97d0 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -5337,7 +5337,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener sendAfterTextChanged((Editable) text); } else { // Always notify AutoFillManager - it will return right away if autofill is disabled. - notifyAutoFillManagerAfterTextChanged(); + notifyAutoFillManagerAfterTextChangedIfNeeded(); } // SelectionModifierCursorController depends on textCanBeSelected, which depends on text @@ -9280,12 +9280,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } // Always notify AutoFillManager - it will return right away if autofill is disabled. - notifyAutoFillManagerAfterTextChanged(); + notifyAutoFillManagerAfterTextChangedIfNeeded(); hideErrorIfUnchanged(); } - private void notifyAutoFillManagerAfterTextChanged() { + private void notifyAutoFillManagerAfterTextChangedIfNeeded() { + if (!isAutofillable()) { + return; + } final AutofillManager afm = mContext.getSystemService(AutofillManager.class); if (afm != null) { if (DEBUG_AUTOFILL) { diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index d424d38b44ce..f61edc5e28ac 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -28,6 +28,7 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -49,6 +50,7 @@ import android.os.UserManager; import android.os.UserManagerInternal; import android.provider.Settings; import android.service.autofill.FillEventHistory; +import android.text.TextUtils; import android.util.LocalLog; import android.util.Log; import android.util.Slog; @@ -60,6 +62,7 @@ import android.view.autofill.IAutoFillManager; import android.view.autofill.IAutoFillManagerClient; import com.android.internal.annotations.GuardedBy; +import com.android.internal.content.PackageMonitor; import com.android.internal.os.BackgroundThread; import com.android.internal.os.IResultReceiver; import com.android.internal.util.DumpUtils; @@ -161,6 +164,84 @@ public final class AutofillManagerService extends SystemService { updateCachedServiceLocked(userId, disabledNow); } }); + startTrackingPackageChanges(); + } + + + private void startTrackingPackageChanges() { + PackageMonitor monitor = new PackageMonitor() { + @Override + public void onSomePackagesChanged() { + synchronized (mLock) { + updateCachedServiceLocked(getChangingUserId()); + } + } + + @Override + public void onPackageUpdateFinished(String packageName, int uid) { + synchronized (mLock) { + final String activePackageName = getActiveAutofillServicePackageName(); + if (packageName.equals(activePackageName)) { + removeCachedServiceLocked(getChangingUserId()); + } + } + } + + @Override + public void onPackageRemoved(String packageName, int uid) { + synchronized (mLock) { + final int userId = getChangingUserId(); + final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId); + if (userState != null) { + final ComponentName componentName = userState.getServiceComponentName(); + if (componentName != null) { + if (packageName.equals(componentName.getPackageName())) { + handleActiveAutofillServiceRemoved(userId); + } + } + } + } + } + + @Override + public boolean onHandleForceStop(Intent intent, String[] packages, + int uid, boolean doit) { + synchronized (mLock) { + final String activePackageName = getActiveAutofillServicePackageName(); + for (String pkg : packages) { + if (pkg.equals(activePackageName)) { + if (!doit) { + return true; + } + handleActiveAutofillServiceRemoved(getChangingUserId()); + } + } + } + return false; + } + + private void handleActiveAutofillServiceRemoved(int userId) { + removeCachedServiceLocked(userId); + Settings.Secure.putStringForUser(mContext.getContentResolver(), + Settings.Secure.AUTOFILL_SERVICE, null, userId); + } + + private String getActiveAutofillServicePackageName() { + final int userId = getChangingUserId(); + final AutofillManagerServiceImpl userState = peekServiceForUserLocked(userId); + if (userState == null) { + return null; + } + final ComponentName serviceComponent = userState.getServiceComponentName(); + if (serviceComponent == null) { + return null; + } + return serviceComponent.getPackageName(); + } + }; + + // package changes + monitor.register(mContext, null, UserHandle.ALL, true); } @Override @@ -312,6 +393,9 @@ public final class AutofillManagerService extends SystemService { AutofillManagerServiceImpl service = peekServiceForUserLocked(userId); if (service != null) { service.updateLocked(disabled); + if (!service.isEnabled()) { + removeCachedServiceLocked(userId); + } } } diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 238cdd5efd5f..ae782f0aa8da 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -53,6 +53,7 @@ import android.util.PrintWriterPrinter; import android.util.Slog; import android.util.SparseArray; import android.view.autofill.AutofillId; +import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; import android.view.autofill.IAutoFillManagerClient; @@ -146,11 +147,20 @@ final class AutofillManagerServiceImpl { } String getPackageName() { - if (mInfo == null) { - return null; + final ComponentName serviceComponent = getServiceComponentName(); + if (serviceComponent != null) { + return serviceComponent.getPackageName(); + } + return null; + } + + ComponentName getServiceComponentName() { + synchronized (mLock) { + if (mInfo == null) { + return null; + } + return mInfo.getServiceInfo().getComponentName(); } - final ComponentName serviceComponent = mInfo.getServiceInfo().getComponentName(); - return serviceComponent.getPackageName(); } private String getComponentNameFromSettings() { @@ -189,7 +199,7 @@ final class AutofillManagerServiceImpl { session.removeSelfLocked(); } } - sendStateToClients(); + sendStateToClients(false); } } catch (PackageManager.NameNotFoundException e) { Slog.e(TAG, "Bad autofill service name " + componentName + ": " + e); @@ -240,7 +250,9 @@ final class AutofillManagerServiceImpl { } final Session session = mSessions.get(sessionId); if (session != null && uid == session.uid) { - session.setHasCallback(hasIt); + synchronized (mLock) { + session.setHasCallbackLocked(hasIt); + } } } @@ -259,14 +271,14 @@ final class AutofillManagerServiceImpl { } final String historyItem = - "id=" + newSession.id + " uid=" + uid + " s=" + mInfo.getServiceInfo().packageName + "id=" + newSession.getId() + " uid=" + uid + " s=" + mInfo.getServiceInfo().packageName + " u=" + mUserId + " i=" + autofillId + " b=" + virtualBounds + " hc=" + hasCallback + " f=" + flags; mRequestsHistory.log(historyItem); newSession.updateLocked(autofillId, virtualBounds, value, FLAG_START_SESSION); - return newSession.id; + return newSession.getId(); } void finishSessionLocked(int sessionId, int uid) { @@ -285,7 +297,7 @@ final class AutofillManagerServiceImpl { Log.d(TAG, "finishSessionLocked(): session finished on save? " + finished); } if (finished) { - session.removeSelf(); + session.removeSelfLocked(); } } @@ -340,7 +352,7 @@ final class AutofillManagerServiceImpl { final Session newSession = new Session(this, mUi, mContext, mHandlerCaller, mUserId, mLock, sessionId, uid, activityToken, windowToken, appCallbackToken, hasCallback, flags, mInfo.getServiceInfo().getComponentName(), packageName); - mSessions.put(newSession.id, newSession); + mSessions.put(newSession.getId(), newSession); return newSession; } @@ -423,6 +435,8 @@ final class AutofillManagerServiceImpl { mSessions.valueAt(i).destroyLocked(); } mSessions.clear(); + + sendStateToClients(true); } CharSequence getServiceLabel() { @@ -540,7 +554,7 @@ final class AutofillManagerServiceImpl { void destroySessionsLocked() { while (mSessions.size() > 0) { - mSessions.valueAt(0).removeSelf(); + mSessions.valueAt(0).removeSelfLocked(); } } @@ -552,7 +566,7 @@ final class AutofillManagerServiceImpl { } } - private void sendStateToClients() { + private void sendStateToClients(boolean resetClient) { final RemoteCallbackList<IAutoFillManagerClient> clients; final int userClientCount; synchronized (mLock) { @@ -566,7 +580,11 @@ final class AutofillManagerServiceImpl { for (int i = 0; i < userClientCount; i++) { final IAutoFillManagerClient client = clients.getBroadcastItem(i); try { - client.setState(isEnabled()); + final boolean resetSession; + synchronized (mLock) { + resetSession = resetClient || isClientSessionDestroyedLocked(client); + } + client.setState(isEnabled(), resetSession, resetClient); } catch (RemoteException re) { /* ignore */ } @@ -576,7 +594,18 @@ final class AutofillManagerServiceImpl { } } - private boolean isEnabled() { + private boolean isClientSessionDestroyedLocked(IAutoFillManagerClient client) { + final int sessionCount = mSessions.size(); + for (int i = 0; i < sessionCount; i++) { + final Session session = mSessions.valueAt(i); + if (session.getClient().equals(client)) { + return session.isDestroyed(); + } + } + return true; + } + + boolean isEnabled() { return mInfo != null && !mDisabled; } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index ac1f34d90b07..0687f6da022e 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.android.server.autofill; import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; @@ -109,7 +108,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private static AtomicInteger sIdCounter = new AtomicInteger(); /** Id of the session */ - public final int id; + private final int mId; /** uid the session is for */ public final int uid; @@ -171,6 +170,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @GuardedBy("mLock") private Bundle mClientState; + @GuardedBy("mLock") + private boolean mDestroyed; + /** * Flags used to start the session. */ @@ -333,7 +335,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @NonNull Object lock, int sessionId, int uid, @NonNull IBinder activityToken, @Nullable IBinder windowToken, @NonNull IBinder client, boolean hasCallback, int flags, @NonNull ComponentName componentName, @NonNull String packageName) { - id = sessionId; + mId = sessionId; this.uid = uid; mService = service; mLock = lock; @@ -355,7 +357,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * * @return The activity token */ - public IBinder getActivityTokenLocked() { + IBinder getActivityTokenLocked() { return mActivityToken; } @@ -367,6 +369,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState */ void switchWindow(@NonNull IBinder newWindow) { synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#switchWindow() rejected - session: " + + mId + " destroyed"); + return; + } mWindowToken = newWindow; } } @@ -379,6 +386,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState */ void switchActivity(@NonNull IBinder newActivity, @NonNull IBinder newClient) { synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#switchActivity() rejected - session: " + + mId + " destroyed"); + return; + } mActivityToken = newActivity; mClient = IAutoFillManagerClient.Stub.asInterface(newClient); @@ -391,6 +403,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void onFillRequestSuccess(@Nullable FillResponse response, int serviceUid, @NonNull String servicePackageName) { + synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#onFillRequestSuccess() rejected - session: " + + mId + " destroyed"); + return; + } + } if (response == null) { if ((mFlags & FLAG_MANUAL_REQUEST) != 0) { getUiForShowing().showError(R.string.autofill_error_cannot_autofill); @@ -430,6 +449,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void onFillRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName) { + synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#onFillRequestFailure() rejected - session: " + + mId + " destroyed"); + return; + } + } LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST)) .setType(MetricsEvent.TYPE_FAILURE) .setPackageName(mPackageName) @@ -443,6 +469,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // FillServiceCallbacks @Override public void onSaveRequestSuccess(@NonNull String servicePackageName) { + synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#onSaveRequestSuccess() rejected - session: " + + mId + " destroyed"); + return; + } + } LogMaker log = (new LogMaker( MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST)) .setType(MetricsEvent.TYPE_SUCCESS) @@ -458,6 +491,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void onSaveRequestFailure(@Nullable CharSequence message, @NonNull String servicePackageName) { + synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#onSaveRequestFailure() rejected - session: " + + mId + " destroyed"); + return; + } + } LogMaker log = (new LogMaker( MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST)) .setType(MetricsEvent.TYPE_FAILURE) @@ -498,6 +538,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState public void authenticate(int requestId, IntentSender intent, Bundle extras) { final Intent fillInIntent; synchronized (mLock) { + synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#authenticate() rejected - session: " + + mId + " destroyed"); + return; + } + } fillInIntent = createAuthFillInIntent( getFillContextByRequestIdLocked(requestId).getStructure(), extras); } @@ -517,19 +564,41 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void fill(int requestId, Dataset dataset) { mHandlerCaller.getHandler().post(() -> autoFill(requestId, dataset)); + synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#fill() rejected - session: " + + mId + " destroyed"); + return; + } + } + mHandlerCaller.getHandler().post(() -> autoFill(requestId, dataset)); } // AutoFillUiCallback @Override public void save() { + synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#save() rejected - session: " + + mId + " destroyed"); + return; + } + } mHandlerCaller.getHandler() - .obtainMessage(AutofillManagerServiceImpl.MSG_SERVICE_SAVE, id, 0) + .obtainMessage(AutofillManagerServiceImpl.MSG_SERVICE_SAVE, mId, 0) .sendToTarget(); } // AutoFillUiCallback @Override public void cancelSave() { + synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#cancelSave() rejected - session: " + + mId + " destroyed"); + return; + } + } mHandlerCaller.getHandler().post(() -> removeSelf()); } @@ -538,10 +607,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState public void requestShowFillUi(AutofillId id, int width, int height, IAutofillWindowPresenter presenter) { synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#requestShowFillUi() rejected - session: " + + mId + " destroyed"); + return; + } if (id.equals(mCurrentViewId)) { try { final ViewState view = mViewStates.get(id); - mClient.requestShowFillUi(this.id, mWindowToken, id, width, height, + mClient.requestShowFillUi(mId, mWindowToken, id, width, height, view.getVirtualBounds(), presenter); } catch (RemoteException e) { Slog.e(TAG, "Error requesting to show fill UI", e); @@ -559,8 +633,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void requestHideFillUi(AutofillId id) { synchronized (mLock) { + // NOTE: We allow this call in a destroyed state as the UI is + // asked to go away after we get destroyed, so let it do that. try { - mClient.requestHideFillUi(this.id, mWindowToken, id); + mClient.requestHideFillUi(mId, mWindowToken, id); } catch (RemoteException e) { Slog.e(TAG, "Error requesting to hide fill UI", e); } @@ -571,6 +647,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void startIntentSender(IntentSender intentSender) { synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#startIntentSender() rejected - session: " + + mId + " destroyed"); + return; + } removeSelfLocked(); } mHandlerCaller.getHandler().post(() -> { @@ -584,7 +665,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState }); } - public void setAuthenticationResultLocked(Bundle data) { + void setAuthenticationResultLocked(Bundle data) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#setAuthenticationResultLocked() rejected - session: " + + mId + " destroyed"); + return; + } if ((mResponseWaitingAuth == null && mDatasetWaitingAuth == null) || data == null) { removeSelf(); } else { @@ -619,7 +705,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } - public void setHasCallback(boolean hasIt) { + void setHasCallbackLocked(boolean hasIt) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#setHasCallbackLocked() rejected - session: " + + mId + " destroyed"); + return; + } mHasCallback = hasIt; } @@ -629,6 +720,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * @return {@code true} if session is done, or {@code false} if it's pending user action. */ public boolean showSaveLocked() { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#showSaveLocked() rejected - session: " + + mId + " destroyed"); + return false; + } if (mContexts == null) { Slog.d(TAG, "showSaveLocked(): no contexts"); return true; @@ -748,6 +844,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * Calls service when user requested save. */ void callSaveLocked() { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#callSaveLocked() rejected - session: " + + mId + " destroyed"); + return; + } + if (DEBUG) { Slog.d(TAG, "callSaveLocked(): mViewStates=" + mViewStates); } @@ -844,6 +946,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int flags) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#updateLocked() rejected - session: " + + mId + " destroyed"); + return; + } ViewState viewState = mViewStates.get(id); if (viewState == null) { @@ -933,6 +1040,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @Override public void onFillReady(FillResponse response, AutofillId filledId, @Nullable AutofillValue value) { + synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#onFillReady() rejected - session: " + + mId + " destroyed"); + return; + } + } + String filterText = null; if (value != null && value.isText()) { filterText = value.getTextValue().toString(); @@ -941,15 +1056,31 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState getUiForShowing().showFillUi(filledId, response, filterText, mPackageName); } - String getFlagAsString(int flag) { + static String getFlagAsString(int flag) { return DebugUtils.flagsToString(AutofillManager.class, "FLAG_", flag); } + int getId() { + return mId; + } + + boolean isDestroyed() { + synchronized (mLock) { + return mDestroyed; + } + } + + IAutoFillManagerClient getClient() { + synchronized (mLock) { + return mClient; + } + } + private void notifyUnavailableToClient() { synchronized (mLock) { if (!mHasCallback) return; try { - mClient.notifyNoFillUi(id, mWindowToken, mCurrentViewId); + mClient.notifyNoFillUi(mId, mWindowToken, mCurrentViewId); } catch (RemoteException e) { Slog.e(TAG, "Error notifying client no fill UI: windowToken=" + mWindowToken + " id=" + mCurrentViewId, e); @@ -984,7 +1115,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } try { - mClient.setTrackedViews(id, trackedViews, saveOnAllViewsInvisible); + mClient.setTrackedViews(mId, trackedViews, saveOnAllViewsInvisible); } catch (RemoteException e) { Slog.w(TAG, "Cannot set tracked ids", e); } @@ -1102,6 +1233,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState void autoFill(int requestId, Dataset dataset) { synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#autoFill() rejected - session: " + + mId + " destroyed"); + return; + } // Autofill it directly... if (dataset.getAuthentication() == null) { mService.setDatasetSelected(dataset.getId()); @@ -1122,11 +1258,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } CharSequence getServiceName() { - return mService.getServiceName(); + synchronized (mLock) { + return mService.getServiceName(); + } } FillResponse getResponseWaitingAuth() { - return mResponseWaitingAuth; + synchronized (mLock) { + return mResponseWaitingAuth; + } } private Intent createAuthFillInIntent(AssistStructure structure, Bundle extras) { @@ -1141,7 +1281,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private void startAuthentication(IntentSender intent, Intent fillInIntent) { try { synchronized (mLock) { - mClient.authenticate(id, intent, fillInIntent); + mClient.authenticate(mId, intent, fillInIntent); } } catch (RemoteException e) { Slog.e(TAG, "Error launching auth intent", e); @@ -1149,7 +1289,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } void dumpLocked(String prefix, PrintWriter pw) { - pw.print(prefix); pw.print("id: "); pw.println(id); + pw.print(prefix); pw.print("id: "); pw.println(mId); pw.print(prefix); pw.print("uid: "); pw.println(uid); pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken); pw.print(prefix); pw.print("mFlags: "); pw.println(mFlags); @@ -1158,6 +1298,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState pw.print(prefix); pw.print("mDatasetWaitingAuth: "); pw.println(mDatasetWaitingAuth); pw.print(prefix); pw.print("mCurrentViewId: "); pw.println(mCurrentViewId); pw.print(prefix); pw.print("mViewStates size: "); pw.println(mViewStates.size()); + pw.print(prefix); pw.print("mDestroyed: "); pw.println(mDestroyed); final String prefix2 = prefix + " "; for (Map.Entry<AutofillId, ViewState> entry : mViewStates.entrySet()) { pw.print(prefix); pw.print("State for id "); pw.println(entry.getKey()); @@ -1190,11 +1331,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState void autoFillApp(Dataset dataset) { synchronized (mLock) { + if (mDestroyed) { + Slog.w(TAG, "Call to Session#autoFillApp() rejected - session: " + + mId + " destroyed"); + return; + } try { if (DEBUG) { Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset); } - mClient.autofill(id, mWindowToken, dataset.getFieldIds(), dataset.getFieldValues()); + mClient.autofill(mId, mWindowToken, dataset.getFieldIds(), + dataset.getFieldValues()); setViewStatesLocked(null, dataset, ViewState.STATE_AUTOFILLED); } catch (RemoteException e) { Slog.w(TAG, "Error autofilling activity: " + e); @@ -1210,12 +1357,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } void destroyLocked() { + if (mDestroyed) { + return; + } mRemoteFillService.destroy(); + mUi.hideAll(); mUi.setCallback(null); + mDestroyed = true; mMetricsLogger.action(MetricsEvent.AUTOFILL_SESSION_FINISHED, mPackageName); } - void removeSelf() { + private void removeSelf() { synchronized (mLock) { removeSelfLocked(); } @@ -1225,8 +1377,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (VERBOSE) { Slog.v(TAG, "removeSelfLocked()"); } + if (mDestroyed) { + Slog.w(TAG, "Call to Session#removeSelfLocked() rejected - session: " + + mId + " destroyed"); + return; + } destroyLocked(); - mService.removeSessionLocked(id); + mService.removeSessionLocked(mId); } private int getLastResponseIndex() { |