summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/Activity.java2
-rw-r--r--core/java/android/app/assist/AssistStructure.java13
-rw-r--r--core/java/android/view/View.java15
-rw-r--r--core/java/android/view/autofill/AutofillId.java34
-rw-r--r--core/java/android/view/autofill/AutofillManager.java28
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java1
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java46
7 files changed, 108 insertions, 31 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index bf2d86096773..041a5b071032 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1461,7 +1461,7 @@ public class Activity extends ContextThemeWrapper
*/
@Override
public AutofillId autofillClientGetNextAutofillId() {
- return new AutofillId(getNextAutofillId());
+ return new AutofillId(getAutofillManager(), getNextAutofillId());
}
/**
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 173b7667897e..ee6a81d9b6e1 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -32,6 +32,7 @@ import android.view.ViewStructure.HtmlInfo.Builder;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
import com.android.internal.util.Preconditions;
@@ -72,6 +73,8 @@ public class AssistStructure implements Parcelable {
boolean mHaveData;
ComponentName mActivityComponent;
+ // Not written to parcel, only used to set session id on virtual node children
+ private final int mAutofillSessionId;
private boolean mIsHomeActivity;
private int mFlags;
@@ -1846,11 +1849,13 @@ public class AssistStructure implements Parcelable {
@Override
public void setAutofillId(@NonNull AutofillId id) {
mNode.mAutofillId = id;
+ mNode.mAutofillId.setSessionId(mAssist.mAutofillSessionId);
}
@Override
public void setAutofillId(@NonNull AutofillId parentId, int virtualId) {
mNode.mAutofillId = new AutofillId(parentId, virtualId);
+ mNode.mAutofillId.setSessionId(mAssist.mAutofillSessionId);
}
@Override
@@ -2040,6 +2045,8 @@ public class AssistStructure implements Parcelable {
public AssistStructure(Activity activity, boolean forAutoFill, int flags) {
mHaveData = true;
mActivityComponent = activity.getComponentName();
+ final AutofillManager afm = activity.getSystemService(AutofillManager.class);
+ mAutofillSessionId = afm == null ? AutofillManager.NO_SESSION : afm.getSessionId();
mFlags = flags;
ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
activity.getActivityToken());
@@ -2056,6 +2063,7 @@ public class AssistStructure implements Parcelable {
public AssistStructure() {
mHaveData = true;
mActivityComponent = null;
+ mAutofillSessionId = AutofillManager.NO_SESSION;
mFlags = 0;
}
@@ -2063,6 +2071,7 @@ public class AssistStructure implements Parcelable {
public AssistStructure(Parcel in) {
mIsHomeActivity = in.readInt() == 1;
mReceiveChannel = in.readStrongBinder();
+ mAutofillSessionId = AutofillManager.NO_SESSION;
}
/**
@@ -2082,6 +2091,10 @@ public class AssistStructure implements Parcelable {
ensureData();
}
Log.i(TAG, "Activity: " + mActivityComponent.flattenToShortString());
+ if (mAutofillSessionId != AutofillManager.NO_SESSION) {
+ Log.i(TAG, "Autofill Session ID: " + mAutofillSessionId);
+ }
+
Log.i(TAG, "Sanitize on write: " + mSanitizeOnWrite);
Log.i(TAG, "Flags: " + mFlags);
final int N = getWindowNodeCount();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9bc53ed5a851..4a619062765f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8251,7 +8251,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mAutofillId == null) {
// The autofill id needs to be unique, but its value doesn't matter,
// so it's better to reuse the accessibility id to save space.
- mAutofillId = new AutofillId(getAutofillViewId());
+ mAutofillId = new AutofillId(getAutofillManager(), getAutofillViewId());
}
return mAutofillId;
}
@@ -8313,11 +8313,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Ignore reset because it was never explicitly set before.
return;
}
- mAutofillId = id;
if (id != null) {
+ // Must create a new id so the session id is preserved.
+ final int oldSessionId = mAutofillId.getSessionId();
mAutofillViewId = id.getViewId();
+ mAutofillId = new AutofillId(mAutofillViewId);
+ mAutofillId.setSessionId(oldSessionId);
mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET;
} else {
+ mAutofillId = null;
mAutofillViewId = NO_ID;
mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET;
}
@@ -8607,8 +8611,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
structure.setContextClickable(true);
}
if (forAutofill) {
- structure.setAutofillId(new AutofillId(getAutofillId(),
- AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId())));
+ final AutofillId autofillId = new AutofillId(getAutofillId(),
+ AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()));
+ final AutofillManager afm = getAutofillManager();
+ autofillId.setSessionId(afm == null ? AutofillManager.NO_SESSION : afm.getSessionId());
+ structure.setAutofillId(autofillId);
}
CharSequence cname = info.getClassName();
structure.setClassName(cname != null ? cname.toString() : null);
diff --git a/core/java/android/view/autofill/AutofillId.java b/core/java/android/view/autofill/AutofillId.java
index cb1d89c54d9a..5ae91a543a52 100644
--- a/core/java/android/view/autofill/AutofillId.java
+++ b/core/java/android/view/autofill/AutofillId.java
@@ -15,6 +15,10 @@
*/
package android.view.autofill;
+import static android.view.autofill.Helper.sDebug;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -28,6 +32,7 @@ public final class AutofillId implements Parcelable {
private final int mViewId;
private final boolean mVirtual;
private final int mVirtualId;
+ private int mSessionId = AutofillManager.NO_SESSION;
/** @hide */
@TestApi
@@ -38,18 +43,26 @@ public final class AutofillId implements Parcelable {
}
/** @hide */
+ // NOTE: caller must set sessionId
@TestApi
- public AutofillId(AutofillId parent, int virtualChildId) {
+ public AutofillId(@NonNull AutofillId parent, int virtualChildId) {
mVirtual = true;
mViewId = parent.mViewId;
mVirtualId = virtualChildId;
}
/** @hide */
- public AutofillId(int parentId, int virtualChildId) {
+ public AutofillId(int sessionId, int parentId, int virtualChildId) {
mVirtual = true;
mViewId = parentId;
mVirtualId = virtualChildId;
+ mSessionId = sessionId;
+ }
+
+ /** @hide */
+ public AutofillId(@Nullable AutofillManager afm, int id) {
+ this(id);
+ mSessionId = afm == null ? AutofillManager.NO_SESSION : afm.getSessionId();
}
/** @hide */
@@ -67,6 +80,16 @@ public final class AutofillId implements Parcelable {
return mVirtual;
}
+ /** @hide */
+ public int getSessionId() {
+ return mSessionId;
+ }
+
+ /** @hide */
+ public void setSessionId(int sessionId) {
+ this.mSessionId = sessionId;
+ }
+
/////////////////////////////////
// Object "contract" methods. //
/////////////////////////////////
@@ -77,6 +100,7 @@ public final class AutofillId implements Parcelable {
int result = 1;
result = prime * result + mViewId;
result = prime * result + mVirtualId;
+ result = prime * result + mSessionId;
return result;
}
@@ -88,6 +112,7 @@ public final class AutofillId implements Parcelable {
final AutofillId other = (AutofillId) obj;
if (mViewId != other.mViewId) return false;
if (mVirtualId != other.mVirtualId) return false;
+ if (mSessionId != other.mSessionId) return false;
return true;
}
@@ -97,6 +122,9 @@ public final class AutofillId implements Parcelable {
if (mVirtual) {
builder.append(':').append(mVirtualId);
}
+ if (mSessionId != AutofillManager.NO_SESSION && sDebug) {
+ builder.append('<').append(mSessionId).append('>');
+ }
return builder.toString();
}
@@ -110,12 +138,14 @@ public final class AutofillId implements Parcelable {
parcel.writeInt(mViewId);
parcel.writeInt(mVirtual ? 1 : 0);
parcel.writeInt(mVirtualId);
+ parcel.writeInt(mSessionId);
}
private AutofillId(Parcel parcel) {
mViewId = parcel.readInt();
mVirtual = parcel.readInt() == 1;
mVirtualId = parcel.readInt();
+ mSessionId = parcel.readInt();
}
public static final Parcelable.Creator<AutofillId> CREATOR =
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 9419e93d0066..612888ef7eca 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -916,7 +916,7 @@ public final class AutofillManager {
boolean isVisible, boolean virtual) {
synchronized (mLock) {
if (mEnabled && isActiveLocked()) {
- final AutofillId id = virtual ? getAutofillId(view, virtualId)
+ final AutofillId id = virtual ? getAutofillIdLocked(view, virtualId)
: view.getAutofillId();
if (sVerbose) Log.v(TAG, "visibility changed for " + id + ": " + isVisible);
if (!isVisible && mFillableIds != null) {
@@ -976,7 +976,7 @@ public final class AutofillManager {
@GuardedBy("mLock")
private AutofillCallback notifyViewEnteredLocked(View view, int virtualId, Rect bounds,
int flags) {
- final AutofillId id = getAutofillId(view, virtualId);
+ final AutofillId id = getAutofillIdLocked(view, virtualId);
AutofillCallback callback = null;
if (shouldIgnoreViewEnteredLocked(id, flags)) return callback;
@@ -1033,7 +1033,7 @@ public final class AutofillManager {
if (mEnabled && isActiveLocked()) {
// don't notify exited when Activity is already in background
if (!isClientDisablingEnterExitEvent()) {
- final AutofillId id = getAutofillId(view, virtualId);
+ final AutofillId id = getAutofillIdLocked(view, virtualId);
// Update focus on existing session.
updateSessionLocked(id, null, null, ACTION_VIEW_EXITED, 0);
@@ -1116,7 +1116,7 @@ public final class AutofillManager {
return;
}
- final AutofillId id = getAutofillId(view, virtualId);
+ final AutofillId id = getAutofillIdLocked(view, virtualId);
updateSessionLocked(id, null, value, ACTION_VALUE_CHANGED, 0);
}
}
@@ -1137,7 +1137,11 @@ public final class AutofillManager {
* @param virtualId id identifying the virtual child inside the parent view.
*/
public void notifyViewClicked(@NonNull View view, int virtualId) {
- notifyViewClicked(getAutofillId(view, virtualId));
+ final AutofillId id;
+ synchronized (mLock) {
+ id = getAutofillIdLocked(view, virtualId);
+ }
+ notifyViewClicked(id);
}
private void notifyViewClicked(AutofillId id) {
@@ -1534,8 +1538,9 @@ public final class AutofillManager {
return id;
}
- private static AutofillId getAutofillId(View parent, int virtualId) {
- return new AutofillId(parent.getAutofillViewId(), virtualId);
+ @GuardedBy("mLock")
+ private AutofillId getAutofillIdLocked(View parent, int virtualId) {
+ return new AutofillId(mSessionId, parent.getAutofillViewId(), virtualId);
}
@GuardedBy("mLock")
@@ -1566,6 +1571,8 @@ public final class AutofillManager {
mSessionId = receiver.getIntResult();
if (mSessionId != NO_SESSION) {
mState = STATE_ACTIVE;
+ // Need to update the view's autofill id with the session
+ id.setSessionId(mSessionId);
}
client.autofillClientResetableStateAvailable();
} catch (RemoteException e) {
@@ -2210,6 +2217,13 @@ public final class AutofillManager {
return getStateAsString(mState);
}
+ /** @hide */
+ public int getSessionId() {
+ synchronized (mLock) {
+ return mSessionId;
+ }
+ }
+
@NonNull
private static String getStateAsString(int state) {
switch (state) {
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 8c8352f81df5..c612c888d733 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -378,6 +378,7 @@ final class AutofillManagerServiceImpl {
if (newSession == null) {
return NO_SESSION;
}
+ autofillId.setSessionId(newSession.id);
final String historyItem =
"id=" + newSession.id + " uid=" + uid + " a=" + shortComponentName
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index c9eb2d2a386f..a9257f65c025 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -23,6 +23,7 @@ import static android.view.autofill.AutofillManager.ACTION_START_SESSION;
import static android.view.autofill.AutofillManager.ACTION_VALUE_CHANGED;
import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED;
import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
+import static android.view.autofill.AutofillManager.NO_SESSION;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static com.android.server.autofill.Helper.getNumericValue;
@@ -75,7 +76,6 @@ import android.service.autofill.ValueFinder;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LocalLog;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -128,7 +128,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private final MetricsLogger mMetricsLogger = new MetricsLogger();
- private static AtomicInteger sIdCounter = new AtomicInteger();
+ private static AtomicInteger sIdCounter = new AtomicInteger(1);
/** ID of the session */
public final int id;
@@ -385,6 +385,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
@Override
public AutofillValue findRawValueByAutofillId(AutofillId id) {
+ if (id == null) return null;
synchronized (mLock) {
return findValueLocked(id);
}
@@ -397,39 +398,50 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
@GuardedBy("mLock")
@Nullable
private AutofillValue findValueLocked(@NonNull AutofillId autofillId) {
- final AutofillValue value = findValueFromThisSessionOnlyLocked(autofillId);
- if (value != null) return value;
-
- // TODO(b/113281366): rather than explicitly look for previous session, it might be better
- // to merge the sessions when created (see note on mergePreviousSessionLocked())
- final ArrayList<Session> previousSessions = mService.getPreviousSessionsLocked(this);
- if (previousSessions != null) {
+ // TODO(b/113281366): rather than explicitly look for previous session, it might be
+ // better to merge the sessions when created (see note on mergePreviousSessionLocked())
+ final int requiredId = autofillId.getSessionId();
+ Session rightSession = null;
+ if (requiredId == NO_SESSION || requiredId == id) {
+ rightSession = this;
+ } else {
+ final ArrayList<Session> previousSessions = mService.getPreviousSessionsLocked(this);
+ if (previousSessions == null) {
+ if (sVerbose) Slog.v(TAG, "findValue(): no previous sessions");
+ return null;
+ }
if (sDebug) {
- Slog.d(TAG, "findValueLocked(): looking on " + previousSessions.size()
+ Slog.d(TAG, "findValue(): looking on " + previousSessions.size()
+ " previous sessions for autofillId " + autofillId);
}
for (int i = 0; i < previousSessions.size(); i++) {
final Session previousSession = previousSessions.get(i);
- final AutofillValue previousValue = previousSession
- .findValueFromThisSessionOnlyLocked(autofillId);
- if (previousValue != null) {
- return previousValue;
+ if (previousSession.id == requiredId) {
+ rightSession = previousSession;
+ break;
}
}
}
- return null;
+ if (rightSession == null) {
+ Slog.w(TAG, "findValue(): no session with id" + requiredId);
+ return null;
+ }
+ return rightSession.findValueFromThisSessionOnlyLocked(autofillId);
}
+ @GuardedBy("mLock")
@Nullable
private AutofillValue findValueFromThisSessionOnlyLocked(@NonNull AutofillId autofillId) {
final ViewState state = mViewStates.get(autofillId);
if (state == null) {
- if (sDebug) Slog.d(TAG, "findValueLocked(): no view state for " + autofillId);
+ if (sDebug) {
+ Slog.d(TAG, "findValueLocked(): no view state for " + autofillId + " on " + id);
+ }
return null;
}
AutofillValue value = state.getCurrentValue();
if (value == null) {
- if (sDebug) Slog.d(TAG, "findValueLocked(): no current value for " + autofillId);
+ Slog.d(TAG, "findValueLocked(): no current value for " + autofillId + " on " + id);
value = getValueFromContextsLocked(autofillId);
}
return value;