summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Svet Ganov <svetoslavganov@google.com> 2017-04-26 18:49:30 -0700
committer Svet Ganov <svetoslavganov@google.com> 2017-04-26 19:22:05 -0700
commit48f10a2ab53e415f34d86ac717b4f6412dfc824f (patch)
tree929e53231b593817e83eeb71ce5ce1a3e379ea12
parentf9e5395081b0a4edf2ca1773029c5ab3a1f083e0 (diff)
Handle package changes in autofill manager service
Autofill manager service was not observing package changes thus we did not properly handle the cases of the service being updated, added, and removed. Handling, additions is needed to properly support restore from a backup. Fixed a few missing locks. Test: all autofill CTS tests pass and manually tested update, add, and remove of autofill services. bug:36638606 bug:36978445 Change-Id: Idd47891774ba2a4e562a1952cbb5a048211fd4e3
-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() {