1 /*
2  * Copyright (C) 2018 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 package android.ext.services.autofill;
17 
18 import android.os.Bundle;
19 import android.service.autofill.AutofillFieldClassificationService;
20 import android.util.Log;
21 import android.view.autofill.AutofillValue;
22 
23 import androidx.annotation.NonNull;
24 import androidx.annotation.Nullable;
25 
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 
30 public class AutofillFieldClassificationServiceImpl extends AutofillFieldClassificationService {
31 
32     private static final String TAG = "AutofillFieldClassificationServiceImpl";
33 
34     private static final String DEFAULT_ALGORITHM = REQUIRED_ALGORITHM_EDIT_DISTANCE;
35 
36     @Nullable
37     @Override
38     /** @hide */
onCalculateScores(@ullable List<AutofillValue> actualValues, @Nullable List<String> userDataValues, @NonNull List<String> categoryIds, @Nullable String defaultAlgorithm, @Nullable Bundle defaultArgs, @Nullable Map algorithms, @Nullable Map args)39     public float[][] onCalculateScores(@Nullable List<AutofillValue> actualValues,
40             @Nullable List<String> userDataValues, @NonNull List<String> categoryIds,
41             @Nullable String defaultAlgorithm, @Nullable Bundle defaultArgs,
42             @Nullable Map algorithms, @Nullable Map args) {
43         if (actualValues == null || userDataValues == null ||
44             actualValues.isEmpty() || userDataValues.isEmpty()) {
45             Log.w(TAG, "calculateScores(): empty currentvalues (" + actualValues
46                     + ") or userValues (" + userDataValues + ")");
47             return null;
48         }
49 
50         return calculateScores(actualValues, userDataValues, categoryIds, defaultAlgorithm,
51                 defaultArgs, (HashMap<String, String>) algorithms,
52                 (HashMap<String, Bundle>) args);
53     }
54 
55     /** @hide */
calculateScores(@onNull List<AutofillValue> actualValues, @NonNull List<String> userDataValues, @NonNull List<String> categoryIds, @Nullable String defaultAlgorithm, @Nullable Bundle defaultArgs, @Nullable HashMap<String, String> algorithms, @Nullable HashMap<String, Bundle> args)56     public float[][] calculateScores(@NonNull List<AutofillValue> actualValues,
57             @NonNull List<String> userDataValues, @NonNull List<String> categoryIds,
58             @Nullable String defaultAlgorithm, @Nullable Bundle defaultArgs,
59             @Nullable HashMap<String, String> algorithms,
60             @Nullable HashMap<String, Bundle> args) {
61         final int actualValuesSize = actualValues.size();
62         final int userDataValuesSize = userDataValues.size();
63         final float[][] scores = new float[actualValuesSize][userDataValuesSize];
64 
65         for (int j = 0; j < userDataValuesSize; j++) {
66             final String categoryId = categoryIds.get(j);
67             String algorithmName = defaultAlgorithm;
68             Bundle arg = defaultArgs;
69             if (algorithms != null && algorithms.containsKey(categoryId)) {
70                 algorithmName = algorithms.get(categoryId);
71             }
72             if (args != null && args.containsKey(categoryId)) {
73                 arg = args.get(categoryId);
74             }
75 
76             if (algorithmName == null || !(algorithmName.equals(DEFAULT_ALGORITHM)
77                     || algorithmName.equals(REQUIRED_ALGORITHM_EXACT_MATCH)
78                     || algorithmName.equals(REQUIRED_ALGORITHM_CREDIT_CARD))) {
79                 Log.w(TAG, "algorithmName is " + algorithmName + ", defaulting to "
80                         + DEFAULT_ALGORITHM);
81                 algorithmName = DEFAULT_ALGORITHM;
82             }
83 
84             for (int i = 0; i < actualValuesSize; i++) {
85                 if (algorithmName.equals(REQUIRED_ALGORITHM_EDIT_DISTANCE)) {
86                     scores[i][j] = EditDistanceScorer.calculateScore(actualValues.get(i),
87                             userDataValues.get(j), arg);
88                 } else if (algorithmName.equals(REQUIRED_ALGORITHM_EXACT_MATCH)) {
89                     scores[i][j] = ExactMatch.calculateScore(actualValues.get(i),
90                             userDataValues.get(j), arg);
91                 } else {
92                     scores[i][j] = CreditCardMatcher.calculateScore(actualValues.get(i),
93                             userDataValues.get(j), arg);
94                 }
95             }
96         }
97         return scores;
98     }
99 }
100