summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/View.java3
-rw-r--r--core/java/android/view/autofill/AutofillManager.java37
-rw-r--r--core/java/android/view/autofill/IAutoFillManagerClient.aidl2
-rw-r--r--core/java/android/widget/TextView.java9
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java84
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java57
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java195
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() {