diff options
| author | 2024-07-17 13:04:29 -0700 | |
|---|---|---|
| committer | 2024-07-26 06:29:21 -0700 | |
| commit | 30da6cffd74788704cea27d725b512817fd541b5 (patch) | |
| tree | 961d4f14af28072b17d31887a1718f24d7c2643f | |
| parent | 9e09bca5bf8508dc89d6db2f49174462e7519304 (diff) | |
[Relayout] Part 5: Location based fingerprinting.
Use locations of view for fingerprints
Bug: 238252288
Flag: EXEMPT : DeviceConfig flags used: enable_relayout
exception granted in b/318391032
Test: atest CtsAutoFillServiceTestCases
atest FrameworkCoreTests:AutofillStateFingerprintTest
Change-Id: I79c850b51fad30e6e37e5de210536c19f4bceb24
| -rw-r--r-- | core/java/android/view/autofill/AutofillStateFingerprint.java | 90 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/view/autofill/AutofillStateFingerprintTest.java | 11 |
2 files changed, 82 insertions, 19 deletions
diff --git a/core/java/android/view/autofill/AutofillStateFingerprint.java b/core/java/android/view/autofill/AutofillStateFingerprint.java index eb857e034ec6..2db4285f0820 100644 --- a/core/java/android/view/autofill/AutofillStateFingerprint.java +++ b/core/java/android/view/autofill/AutofillStateFingerprint.java @@ -29,6 +29,7 @@ import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -61,7 +62,11 @@ public final class AutofillStateFingerprint { private static final String TAG = "AutofillStateFingerprint"; - static AutofillStateFingerprint createInstance() { + /** + * Returns an instance of this class + */ + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + public static AutofillStateFingerprint createInstance() { return new AutofillStateFingerprint(); } @@ -92,11 +97,13 @@ public final class AutofillStateFingerprint { if (sDebug) { Log.d(TAG, "Autofillable views count prior to auth:" + autofillableViews.size()); } - ArrayList<Integer> hashes = getFingerprintIds(autofillableViews); - for (int i = 0; i < hashes.size(); i++) { - View view = autofillableViews.get(i); +// ArrayList<Integer> hashes = getFingerprintIds(autofillableViews); + + ArrayMap<Integer, View> hashes = getFingerprintIds(autofillableViews); + for (Map.Entry<Integer, View> entry : hashes.entrySet()) { + View view = entry.getValue(); if (view != null) { - mHashToAutofillIdMap.put(hashes.get(i), view.getAutofillId()); + mHashToAutofillIdMap.put(entry.getKey(), view.getAutofillId()); } else { if (sDebug) { Log.d(TAG, "Encountered null view"); @@ -114,7 +121,7 @@ public final class AutofillStateFingerprint { for (int i = 0; i < autofillIdsArr.length; i++) { View view = views[i]; if (view != null) { - int id = getEphemeralFingerprintId(view); + int id = getEphemeralFingerprintId(view, 0 /* position irrelevant */); AutofillId autofillId = view.getAutofillId(); autofillId.setSessionId(mSessionId); mHashToAutofillIdMap.put(id, autofillId); @@ -159,14 +166,14 @@ public final class AutofillStateFingerprint { dumpCurrentState(); } // For the autofillable views, compute their hashes - ArrayList<Integer> currentHashes = getFingerprintIds(currentAutofillableViews); + ArrayMap<Integer, View> currentHashes = getFingerprintIds(currentAutofillableViews); // For the computed hashes, try to look for the old fingerprints. // If match found, update the new autofill ids of those views Map<AutofillId, View> oldFailedIdsToCurrentViewMap = new HashMap<>(); - for (int i = 0; i < currentAutofillableViews.size(); i++) { - View view = currentAutofillableViews.get(i); - int currentHash = currentHashes.get(i); + for (Map.Entry<Integer, View> entry : currentHashes.entrySet()) { + View view = entry.getValue(); + int currentHash = entry.getKey(); AutofillId currentAutofillId = view.getAutofillId(); currentAutofillId.setSessionId(mSessionId); if (mHashToAutofillIdMap.containsKey(currentHash)) { @@ -219,19 +226,51 @@ public final class AutofillStateFingerprint { /** * Retrieves fingerprint hashes for the views */ - ArrayList<Integer> getFingerprintIds(@NonNull List<View> views) { - ArrayList<Integer> ids = new ArrayList(views.size()); + ArrayMap<Integer, View> getFingerprintIds(@NonNull List<View> views) { + ArrayMap<Integer, View> map = new ArrayMap<>(); + if (mUseRelativePosition) { + Collections.sort(views, (View v1, View v2) -> { + int[] posV1 = v1.getLocationOnScreen(); + int[] posV2 = v2.getLocationOnScreen(); + + int compare = posV1[0] - posV2[0]; // x coordinate + if (compare != 0) { + return compare; + } + compare = posV1[1] - posV2[1]; // y coordinate + if (compare != 0) { + return compare; + } + // Sort on vertical + compare = compareTop(v1, v2); + if (compare != 0) { + return compare; + } + compare = compareBottom(v1, v2); + if (compare != 0) { + return compare; + } + compare = compareLeft(v1, v2); + if (compare != 0) { + return compare; + } + return compareRight(v1, v2); + // Note that if compareRight also returned 0, that means both the views have exact + // same location, so just treat them as equal + }); + } for (int i = 0; i < views.size(); i++) { - ids.add(getEphemeralFingerprintId(views.get(i))); + View view = views.get(i); + map.put(getEphemeralFingerprintId(view, i), view); } - return ids; + return map; } /** * Returns fingerprint hash for the view. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) - public static int getEphemeralFingerprintId(View v) { + public int getEphemeralFingerprintId(View v, int position) { if (v == null) return -1; int inputType = Integer.MIN_VALUE; int imeOptions = Integer.MIN_VALUE; @@ -268,6 +307,9 @@ public final class AutofillStateFingerprint { int hash = Objects.hash(visibility, inputType, imeOptions, isSingleLine, hints, contentDesc, tooltip, autofillType, Arrays.deepHashCode(autofillHints), paddingBottom, paddingTop, paddingRight, paddingLeft); + if (mUseRelativePosition) { + hash = Objects.hash(hash, position); + } if (sDebug) { Log.d(TAG, "Hash: " + hash + " for AutofillId:" + v.getAutofillId() + " visibility:" + visibility @@ -285,8 +327,26 @@ public final class AutofillStateFingerprint { + " paddingRight:" + paddingRight + " paddingTop:" + paddingTop + " paddingBottom:" + paddingBottom + + " mUseRelativePosition" + mUseRelativePosition + + " position:" + position ); } return hash; } + + private int compareTop(View v1, View v2) { + return v1.getTop() - v2.getTop(); + } + + private int compareBottom(View v1, View v2) { + return v1.getBottom() - v2.getBottom(); + } + + private int compareLeft(View v1, View v2) { + return v1.getLeft() - v2.getLeft(); + } + + private int compareRight(View v1, View v2) { + return v1.getRight() - v2.getRight(); + } } diff --git a/core/tests/coretests/src/android/view/autofill/AutofillStateFingerprintTest.java b/core/tests/coretests/src/android/view/autofill/AutofillStateFingerprintTest.java index fb50e988c417..7cbfc40a62f1 100644 --- a/core/tests/coretests/src/android/view/autofill/AutofillStateFingerprintTest.java +++ b/core/tests/coretests/src/android/view/autofill/AutofillStateFingerprintTest.java @@ -38,6 +38,9 @@ public class AutofillStateFingerprintTest { private static final int MAGIC_AUTOFILL_NUMBER = 1000; + private AutofillStateFingerprint mAutofillStateFingerprint = + AutofillStateFingerprint.createInstance(); + @Test public void testSameFingerprintsForTextView() throws Exception { TextView tv = new TextView(sContext); @@ -87,13 +90,13 @@ public class AutofillStateFingerprintTest { } private void assertIdsEqual(View v1, View v2) { - assertEquals(AutofillStateFingerprint.getEphemeralFingerprintId(v1), - AutofillStateFingerprint.getEphemeralFingerprintId(v2)); + assertEquals(mAutofillStateFingerprint.getEphemeralFingerprintId(v1, 0), + mAutofillStateFingerprint.getEphemeralFingerprintId(v2, 0)); } private void assertIdsNotEqual(View v1, View v2) { - assertNotEquals(AutofillStateFingerprint.getEphemeralFingerprintId(v1), - AutofillStateFingerprint.getEphemeralFingerprintId(v2)); + assertNotEquals(mAutofillStateFingerprint.getEphemeralFingerprintId(v1, 0), + mAutofillStateFingerprint.getEphemeralFingerprintId(v2, 0)); } private void fillViewProperties(View view) { |