File: ExtrasUtils.java

package info (click to toggle)
android-platform-frameworks-base 1%3A10.0.0%2Br36-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 321,788 kB
  • sloc: java: 962,234; cpp: 274,314; xml: 242,770; python: 5,060; sh: 1,432; ansic: 494; makefile: 47; sed: 19
file content (335 lines) | stat: -rw-r--r-- 11,837 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view.textclassifier;

import android.annotation.Nullable;
import android.app.RemoteAction;
import android.content.Intent;
import android.icu.util.ULocale;
import android.os.Bundle;

import com.android.internal.util.ArrayUtils;

import com.google.android.textclassifier.AnnotatorModel;

import java.util.ArrayList;
import java.util.List;

/**
 * Utility class for inserting and retrieving data in TextClassifier request/response extras.
 * @hide
 */
// TODO: Make this a TestApi for CTS testing.
public final class ExtrasUtils {

    // Keys for response objects.
    private static final String SERIALIZED_ENTITIES_DATA = "serialized-entities-data";
    private static final String ENTITIES_EXTRAS = "entities-extras";
    private static final String ACTION_INTENT = "action-intent";
    private static final String ACTIONS_INTENTS = "actions-intents";
    private static final String FOREIGN_LANGUAGE = "foreign-language";
    private static final String ENTITY_TYPE = "entity-type";
    private static final String SCORE = "score";
    private static final String MODEL_VERSION = "model-version";
    private static final String MODEL_NAME = "model-name";
    private static final String TEXT_LANGUAGES = "text-languages";
    private static final String ENTITIES = "entities";

    // Keys for request objects.
    private static final String IS_SERIALIZED_ENTITY_DATA_ENABLED =
            "is-serialized-entity-data-enabled";

    private ExtrasUtils() {}

    /**
     * Bundles and returns foreign language detection information for TextClassifier responses.
     */
    static Bundle createForeignLanguageExtra(
            String language, float score, int modelVersion) {
        final Bundle bundle = new Bundle();
        bundle.putString(ENTITY_TYPE, language);
        bundle.putFloat(SCORE, score);
        bundle.putInt(MODEL_VERSION, modelVersion);
        bundle.putString(MODEL_NAME, "langId_v" + modelVersion);
        return bundle;
    }

    /**
     * Stores {@code extra} as foreign language information in TextClassifier response object's
     * extras {@code container}.
     *
     * @see #getForeignLanguageExtra(TextClassification)
     */
    static void putForeignLanguageExtra(Bundle container, Bundle extra) {
        container.putParcelable(FOREIGN_LANGUAGE, extra);
    }

    /**
     * Returns foreign language detection information contained in the TextClassification object.
     * responses.
     *
     * @see #putForeignLanguageExtra(Bundle, Bundle)
     */
    @Nullable
    public static Bundle getForeignLanguageExtra(@Nullable TextClassification classification) {
        if (classification == null) {
            return null;
        }
        return classification.getExtras().getBundle(FOREIGN_LANGUAGE);
    }

    /**
     * @see #getTopLanguage(Intent)
     */
    static void putTopLanguageScores(Bundle container, EntityConfidence languageScores) {
        final int maxSize = Math.min(3, languageScores.getEntities().size());
        final String[] languages = languageScores.getEntities().subList(0, maxSize)
                .toArray(new String[0]);
        final float[] scores = new float[languages.length];
        for (int i = 0; i < languages.length; i++) {
            scores[i] = languageScores.getConfidenceScore(languages[i]);
        }
        container.putStringArray(ENTITY_TYPE, languages);
        container.putFloatArray(SCORE, scores);
    }

    /**
     * @see #putTopLanguageScores(Bundle, EntityConfidence)
     */
    @Nullable
    public static ULocale getTopLanguage(@Nullable Intent intent) {
        if (intent == null) {
            return null;
        }
        final Bundle tcBundle = intent.getBundleExtra(TextClassifier.EXTRA_FROM_TEXT_CLASSIFIER);
        if (tcBundle == null) {
            return null;
        }
        final Bundle textLanguagesExtra = tcBundle.getBundle(TEXT_LANGUAGES);
        if (textLanguagesExtra == null) {
            return null;
        }
        final String[] languages = textLanguagesExtra.getStringArray(ENTITY_TYPE);
        final float[] scores = textLanguagesExtra.getFloatArray(SCORE);
        if (languages == null || scores == null
                || languages.length == 0 || languages.length != scores.length) {
            return null;
        }
        int highestScoringIndex = 0;
        for (int i = 1; i < languages.length; i++) {
            if (scores[highestScoringIndex] < scores[i]) {
                highestScoringIndex = i;
            }
        }
        return ULocale.forLanguageTag(languages[highestScoringIndex]);
    }

    public static void putTextLanguagesExtra(Bundle container, Bundle extra) {
        container.putBundle(TEXT_LANGUAGES, extra);
    }

    /**
     * Stores {@code actionIntents} information in TextClassifier response object's extras
     * {@code container}.
     */
    static void putActionsIntents(Bundle container, ArrayList<Intent> actionsIntents) {
        container.putParcelableArrayList(ACTIONS_INTENTS, actionsIntents);
    }

    /**
     * Stores {@code actionIntents} information in TextClassifier response object's extras
     * {@code container}.
     */
    public static void putActionIntent(Bundle container, @Nullable Intent actionIntent) {
        container.putParcelable(ACTION_INTENT, actionIntent);
    }

    /**
     * Returns {@code actionIntent} information contained in a TextClassifier response object.
     */
    @Nullable
    public static Intent getActionIntent(Bundle container) {
        return container.getParcelable(ACTION_INTENT);
    }

    /**
     * Stores serialized entity data information in TextClassifier response object's extras
     * {@code container}.
     */
    public static void putSerializedEntityData(
            Bundle container, @Nullable byte[] serializedEntityData) {
        container.putByteArray(SERIALIZED_ENTITIES_DATA, serializedEntityData);
    }

    /**
     * Returns serialized entity data information contained in a TextClassifier response
     * object.
     */
    @Nullable
    public static byte[] getSerializedEntityData(Bundle container) {
        return container.getByteArray(SERIALIZED_ENTITIES_DATA);
    }

    /**
     * Stores {@code entities} information in TextClassifier response object's extras
     * {@code container}.
     *
     * @see {@link #getCopyText(Bundle)}
     */
    public static void putEntitiesExtras(Bundle container, @Nullable Bundle entitiesExtras) {
        container.putParcelable(ENTITIES_EXTRAS, entitiesExtras);
    }

    /**
     * Returns {@code entities} information contained in a TextClassifier response object.
     *
     * @see {@link #putEntitiesExtras(Bundle, Bundle)}
     */
    @Nullable
    public static String getCopyText(Bundle container) {
        Bundle entitiesExtras = container.getParcelable(ENTITIES_EXTRAS);
        if (entitiesExtras == null) {
            return null;
        }
        return entitiesExtras.getString("text");
    }

    /**
     * Returns {@code actionIntents} information contained in the TextClassification object.
     */
    @Nullable
    public static ArrayList<Intent> getActionsIntents(@Nullable TextClassification classification) {
        if (classification == null) {
            return null;
        }
        return classification.getExtras().getParcelableArrayList(ACTIONS_INTENTS);
    }

    /**
     * Returns the first action found in the {@code classification} object with an intent
     * action string, {@code intentAction}.
     */
    @Nullable
    public static RemoteAction findAction(
            @Nullable TextClassification classification, @Nullable String intentAction) {
        if (classification == null || intentAction == null) {
            return null;
        }
        final ArrayList<Intent> actionIntents = getActionsIntents(classification);
        if (actionIntents != null) {
            final int size = actionIntents.size();
            for (int i = 0; i < size; i++) {
                final Intent intent = actionIntents.get(i);
                if (intent != null && intentAction.equals(intent.getAction())) {
                    return classification.getActions().get(i);
                }
            }
        }
        return null;
    }

    /**
     * Returns the first "translate" action found in the {@code classification} object.
     */
    @Nullable
    public static RemoteAction findTranslateAction(@Nullable TextClassification classification) {
        return findAction(classification, Intent.ACTION_TRANSLATE);
    }

    /**
     * Returns the entity type contained in the {@code extra}.
     */
    @Nullable
    public static String getEntityType(@Nullable Bundle extra) {
        if (extra == null) {
            return null;
        }
        return extra.getString(ENTITY_TYPE);
    }

    /**
     * Returns the score contained in the {@code extra}.
     */
    @Nullable
    public static float getScore(Bundle extra) {
        final int defaultValue = -1;
        if (extra == null) {
            return defaultValue;
        }
        return extra.getFloat(SCORE, defaultValue);
    }

    /**
     * Returns the model name contained in the {@code extra}.
     */
    @Nullable
    public static String getModelName(@Nullable Bundle extra) {
        if (extra == null) {
            return null;
        }
        return extra.getString(MODEL_NAME);
    }

    /**
     * Stores the entities from {@link AnnotatorModel.ClassificationResult} in {@code container}.
     */
    public static void putEntities(
            Bundle container,
            @Nullable AnnotatorModel.ClassificationResult[] classifications) {
        if (ArrayUtils.isEmpty(classifications)) {
            return;
        }
        ArrayList<Bundle> entitiesBundle = new ArrayList<>();
        for (AnnotatorModel.ClassificationResult classification : classifications) {
            if (classification == null) {
                continue;
            }
            Bundle entityBundle = new Bundle();
            entityBundle.putString(ENTITY_TYPE, classification.getCollection());
            entityBundle.putByteArray(
                    SERIALIZED_ENTITIES_DATA,
                    classification.getSerializedEntityData());
            entitiesBundle.add(entityBundle);
        }
        if (!entitiesBundle.isEmpty()) {
            container.putParcelableArrayList(ENTITIES, entitiesBundle);
        }
    }

    /**
     * Returns a list of entities contained in the {@code extra}.
     */
    @Nullable
    public static List<Bundle> getEntities(Bundle container) {
        return container.getParcelableArrayList(ENTITIES);
    }

    /**
     * Whether the annotator should populate serialized entity data into the result object.
     */
    public static boolean isSerializedEntityDataEnabled(TextLinks.Request request) {
        return request.getExtras().getBoolean(IS_SERIALIZED_ENTITY_DATA_ENABLED);
    }

    /**
     * To indicate whether the annotator should populate serialized entity data in the result
     * object.
     */
    public static void putIsSerializedEntityDataEnabled(Bundle bundle, boolean isEnabled) {
        bundle.putBoolean(IS_SERIALIZED_ENTITY_DATA_ENABLED, isEnabled);
    }
}