FieldClassification.java revision 329d04097e1db9b6f801972d94f56c5b56c09e8a
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.service.autofill;
18
19import static android.view.autofill.Helper.sDebug;
20
21import android.annotation.NonNull;
22import android.annotation.TestApi;
23import android.os.Parcel;
24import android.os.Parcelable;
25import android.view.autofill.Helper;
26
27import com.android.internal.util.Preconditions;
28
29import com.google.android.collect.Lists;
30
31import java.util.List;
32
33/**
34 * Gets the <a href="#FieldsClassification">fields classification</a> results for a given field.
35 *
36 * TODO(b/67867469):
37 * - improve javadoc
38 * - unhide / remove testApi
39 *
40 * @hide
41 */
42@TestApi
43public final class FieldClassification implements Parcelable {
44
45    private final Match mMatch;
46
47    /** @hide */
48    public FieldClassification(@NonNull Match match) {
49        mMatch = Preconditions.checkNotNull(match);
50    }
51
52    /**
53     * Gets the {@link Match matches} with the highest {@link Match#getScore() scores}.
54     *
55     * <p><b>Note:</b> There's no guarantee of how many matches will be returned. In fact,
56     * the Android System might return just the top match to minimize the impact of field
57     * classification in the device's health.
58     */
59    @NonNull
60    public List<Match> getMatches() {
61        return Lists.newArrayList(mMatch);
62    }
63
64    @Override
65    public String toString() {
66        if (!sDebug) return super.toString();
67
68        return "FieldClassification: " + mMatch;
69    }
70
71    /////////////////////////////////////
72    // Parcelable "contract" methods. //
73    /////////////////////////////////////
74
75    @Override
76    public int describeContents() {
77        return 0;
78    }
79
80    @Override
81    public void writeToParcel(Parcel parcel, int flags) {
82        parcel.writeParcelable(mMatch, flags);
83    }
84
85    public static final Parcelable.Creator<FieldClassification> CREATOR =
86            new Parcelable.Creator<FieldClassification>() {
87
88        @Override
89        public FieldClassification createFromParcel(Parcel parcel) {
90            return new FieldClassification(parcel.readParcelable(null));
91        }
92
93        @Override
94        public FieldClassification[] newArray(int size) {
95            return new FieldClassification[size];
96        }
97    };
98
99    /**
100     * Gets the score of a {@link UserData} entry for the field.
101     *
102     * TODO(b/67867469):
103     * - improve javadoc
104     * - unhide / remove testApi
105     *
106     * @hide
107     */
108    @TestApi
109    public static final class Match implements Parcelable {
110
111        private final String mRemoteId;
112        private final float mScore;
113
114        /** @hide */
115        public Match(String remoteId, float score) {
116            mRemoteId = Preconditions.checkNotNull(remoteId);
117            mScore = score;
118        }
119
120        /**
121         * Gets the remote id of the {@link UserData} entry.
122         */
123        @NonNull
124        public String getRemoteId() {
125            return mRemoteId;
126        }
127
128        /**
129         * Gets a score between the value of this field and the value of the {@link UserData} entry.
130         *
131         * <p>The score is based in a case-insensitive comparisson of all characters from both the
132         * field value and the user data entry, and it ranges from {@code 0} to {@code 1000000}:
133         * <ul>
134         *   <li>{@code 1.0} represents a full match ({@code 100%}).
135         *   <li>{@code 0.0} represents a full mismatch ({@code 0%}).
136         *   <li>Any other value is a partial match.
137         * </ul>
138         *
139         * <p>How the score is calculated depends on the algorithm used by the Android System.
140         * For example, if the user  data is {@code "abc"} and the field value us {@code " abc"},
141         * the result could be:
142         * <ul>
143         *   <li>{@code 1.0} if the algorithm trims the values.
144         *   <li>{@code 0.0} if the algorithm compares the values sequentially.
145         *   <li>{@code 0.75} if the algorithm consideres that 3/4 (75%) of the characters match.
146         * </ul>
147         *
148         * <p>Currently, the autofill service cannot configure the algorithm.
149         */
150        public float getScore() {
151            return mScore;
152        }
153
154        @Override
155        public String toString() {
156            if (!sDebug) return super.toString();
157
158            final StringBuilder string = new StringBuilder("Match: remoteId=");
159            Helper.appendRedacted(string, mRemoteId);
160            return string.append(", score=").append(mScore).toString();
161        }
162
163        /////////////////////////////////////
164        // Parcelable "contract" methods. //
165        /////////////////////////////////////
166
167        @Override
168        public int describeContents() {
169            return 0;
170        }
171
172        @Override
173        public void writeToParcel(Parcel parcel, int flags) {
174            parcel.writeString(mRemoteId);
175            parcel.writeFloat(mScore);
176        }
177
178        @SuppressWarnings("hiding")
179        public static final Parcelable.Creator<Match> CREATOR = new Parcelable.Creator<Match>() {
180
181            @Override
182            public Match createFromParcel(Parcel parcel) {
183                return new Match(parcel.readString(), parcel.readFloat());
184            }
185
186            @Override
187            public Match[] newArray(int size) {
188                return new Match[size];
189            }
190        };
191    }
192}
193