1bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme/* 2bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * Copyright (C) 2017 The Android Open Source Project 3bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * 4bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * Licensed under the Apache License, Version 2.0 (the "License"); 5bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * you may not use this file except in compliance with the License. 6bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * You may obtain a copy of the License at 7bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * 8bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * http://www.apache.org/licenses/LICENSE-2.0 9bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * 10bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * Unless required by applicable law or agreed to in writing, software 11bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * distributed under the License is distributed on an "AS IS" BASIS, 12bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * See the License for the specific language governing permissions and 14bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * limitations under the License. 15bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme */ 16bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 17bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Lemepackage android.service.autofill; 18bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 19bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Lemeimport static android.view.autofill.Helper.sDebug; 20bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 21bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Lemeimport android.annotation.NonNull; 22bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Lemeimport android.os.Parcel; 23bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Lemeimport android.view.autofill.Helper; 24bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 25bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Lemeimport com.android.internal.util.Preconditions; 26bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 2751f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Lemeimport java.util.ArrayList; 2851f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Lemeimport java.util.Collections; 2951f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Lemeimport java.util.Comparator; 30329d04097e1db9b6f801972d94f56c5b56c09e8aFelipe Lemeimport java.util.List; 31329d04097e1db9b6f801972d94f56c5b56c09e8aFelipe Leme 32bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme/** 3378172e70f4c5d776678551965db7c167ee11703eFelipe Leme * Represents the <a href="AutofillService.html#FieldClassification">field classification</a> 3478172e70f4c5d776678551965db7c167ee11703eFelipe Leme * results for a given field. 35bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme */ 36f1141c00411296b59b59376182083685248f69c8Felipe Lemepublic final class FieldClassification { 37bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 3851f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme private final ArrayList<Match> mMatches; 39bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 40bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme /** @hide */ 4151f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme public FieldClassification(@NonNull ArrayList<Match> matches) { 4251f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme mMatches = Preconditions.checkNotNull(matches); 4351f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme Collections.sort(mMatches, new Comparator<Match>() { 4451f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme @Override 4551f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme public int compare(Match o1, Match o2) { 4651f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme if (o1.mScore > o2.mScore) return -1; 4751f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme if (o1.mScore < o2.mScore) return 1; 4851f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme return 0; 4951f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme }} 5051f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme ); 51bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 52bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 53bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme /** 5451f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme * Gets the {@link Match matches} with the highest {@link Match#getScore() scores} (sorted in 5551f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme * descending order). 56329d04097e1db9b6f801972d94f56c5b56c09e8aFelipe Leme * 57329d04097e1db9b6f801972d94f56c5b56c09e8aFelipe Leme * <p><b>Note:</b> There's no guarantee of how many matches will be returned. In fact, 58329d04097e1db9b6f801972d94f56c5b56c09e8aFelipe Leme * the Android System might return just the top match to minimize the impact of field 59329d04097e1db9b6f801972d94f56c5b56c09e8aFelipe Leme * classification in the device's health. 60bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme */ 61bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme @NonNull 62329d04097e1db9b6f801972d94f56c5b56c09e8aFelipe Leme public List<Match> getMatches() { 6351f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme return mMatches; 64bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 65bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 66bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme @Override 67bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme public String toString() { 68bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme if (!sDebug) return super.toString(); 69bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 7051f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme return "FieldClassification: " + mMatches; 71bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 72bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 73f1141c00411296b59b59376182083685248f69c8Felipe Leme private void writeToParcel(Parcel parcel) { 7451f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme parcel.writeInt(mMatches.size()); 7551f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme for (int i = 0; i < mMatches.size(); i++) { 7651f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme mMatches.get(i).writeToParcel(parcel); 7751f6cd70316cdd0662e40ad7b0109effab9cd9adFelipe Leme } 78bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 79bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 80f1141c00411296b59b59376182083685248f69c8Felipe Leme private static FieldClassification readFromParcel(Parcel parcel) { 81f1141c00411296b59b59376182083685248f69c8Felipe Leme final int size = parcel.readInt(); 82f1141c00411296b59b59376182083685248f69c8Felipe Leme final ArrayList<Match> matches = new ArrayList<>(); 83f1141c00411296b59b59376182083685248f69c8Felipe Leme for (int i = 0; i < size; i++) { 84f1141c00411296b59b59376182083685248f69c8Felipe Leme matches.add(i, Match.readFromParcel(parcel)); 85f1141c00411296b59b59376182083685248f69c8Felipe Leme } 86bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 87f1141c00411296b59b59376182083685248f69c8Felipe Leme return new FieldClassification(matches); 88f1141c00411296b59b59376182083685248f69c8Felipe Leme } 89f1141c00411296b59b59376182083685248f69c8Felipe Leme 90f1141c00411296b59b59376182083685248f69c8Felipe Leme static FieldClassification[] readArrayFromParcel(Parcel parcel) { 91f1141c00411296b59b59376182083685248f69c8Felipe Leme final int length = parcel.readInt(); 92f1141c00411296b59b59376182083685248f69c8Felipe Leme final FieldClassification[] fcs = new FieldClassification[length]; 93f1141c00411296b59b59376182083685248f69c8Felipe Leme for (int i = 0; i < length; i++) { 94f1141c00411296b59b59376182083685248f69c8Felipe Leme fcs[i] = readFromParcel(parcel); 95bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 96f1141c00411296b59b59376182083685248f69c8Felipe Leme return fcs; 97f1141c00411296b59b59376182083685248f69c8Felipe Leme } 98bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 99f1141c00411296b59b59376182083685248f69c8Felipe Leme static void writeArrayToParcel(@NonNull Parcel parcel, @NonNull FieldClassification[] fcs) { 100f1141c00411296b59b59376182083685248f69c8Felipe Leme parcel.writeInt(fcs.length); 101f1141c00411296b59b59376182083685248f69c8Felipe Leme for (int i = 0; i < fcs.length; i++) { 102f1141c00411296b59b59376182083685248f69c8Felipe Leme fcs[i].writeToParcel(parcel); 103bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 104f1141c00411296b59b59376182083685248f69c8Felipe Leme } 105bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 106bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme /** 10778172e70f4c5d776678551965db7c167ee11703eFelipe Leme * Represents the score of a {@link UserData} entry for the field. 108bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme */ 10978172e70f4c5d776678551965db7c167ee11703eFelipe Leme public static final class Match { 110bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 111febb733c1b170ccba0668e50beef1e230dc51edaFelipe Leme private final String mCategoryId; 112329d04097e1db9b6f801972d94f56c5b56c09e8aFelipe Leme private final float mScore; 113bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 114bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme /** @hide */ 115febb733c1b170ccba0668e50beef1e230dc51edaFelipe Leme public Match(String categoryId, float score) { 116febb733c1b170ccba0668e50beef1e230dc51edaFelipe Leme mCategoryId = Preconditions.checkNotNull(categoryId); 117bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme mScore = score; 118bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 119bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 120bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme /** 121febb733c1b170ccba0668e50beef1e230dc51edaFelipe Leme * Gets the category id of the {@link UserData} entry. 122bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme */ 123bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme @NonNull 124febb733c1b170ccba0668e50beef1e230dc51edaFelipe Leme public String getCategoryId() { 125febb733c1b170ccba0668e50beef1e230dc51edaFelipe Leme return mCategoryId; 126bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 127bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 128bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme /** 12978172e70f4c5d776678551965db7c167ee11703eFelipe Leme * Gets a classification score for the value of this field compared to the value of the 13078172e70f4c5d776678551965db7c167ee11703eFelipe Leme * {@link UserData} entry. 131bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * 13278172e70f4c5d776678551965db7c167ee11703eFelipe Leme * <p>The score is based in a comparison of the field value and the user data entry, and it 13378172e70f4c5d776678551965db7c167ee11703eFelipe Leme * ranges from {@code 0.0F} to {@code 1.0F}: 134bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * <ul> 13578172e70f4c5d776678551965db7c167ee11703eFelipe Leme * <li>{@code 1.0F} represents a full match ({@code 100%}). 13678172e70f4c5d776678551965db7c167ee11703eFelipe Leme * <li>{@code 0.0F} represents a full mismatch ({@code 0%}). 137bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * <li>Any other value is a partial match. 138bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * </ul> 139bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme * 14027f4573d136949abeacb00f7246ff9911e9cb105Felipe Leme * <p>How the score is calculated depends on the 14127f4573d136949abeacb00f7246ff9911e9cb105Felipe Leme * {@link UserData.Builder#setFieldClassificationAlgorithm(String, android.os.Bundle) 14227f4573d136949abeacb00f7246ff9911e9cb105Felipe Leme * algorithm} used. 143bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme */ 144329d04097e1db9b6f801972d94f56c5b56c09e8aFelipe Leme public float getScore() { 145bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme return mScore; 146bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 147bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 148bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme @Override 149bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme public String toString() { 150bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme if (!sDebug) return super.toString(); 151bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 152febb733c1b170ccba0668e50beef1e230dc51edaFelipe Leme final StringBuilder string = new StringBuilder("Match: categoryId="); 153febb733c1b170ccba0668e50beef1e230dc51edaFelipe Leme Helper.appendRedacted(string, mCategoryId); 154d11a66220c424c030542aca5c47de059d4a308ccFelipe Leme return string.append(", score=").append(mScore).toString(); 155bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 156bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 15778172e70f4c5d776678551965db7c167ee11703eFelipe Leme private void writeToParcel(@NonNull Parcel parcel) { 158febb733c1b170ccba0668e50beef1e230dc51edaFelipe Leme parcel.writeString(mCategoryId); 159329d04097e1db9b6f801972d94f56c5b56c09e8aFelipe Leme parcel.writeFloat(mScore); 160bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 161bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme 16278172e70f4c5d776678551965db7c167ee11703eFelipe Leme private static Match readFromParcel(@NonNull Parcel parcel) { 163d11a66220c424c030542aca5c47de059d4a308ccFelipe Leme return new Match(parcel.readString(), parcel.readFloat()); 16478172e70f4c5d776678551965db7c167ee11703eFelipe Leme } 165bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme } 166bb6bfea6801cff5b50c990bdcfbd2df93ddf9023Felipe Leme} 167