blob: 8b9d12916595ee1f1b8e0b836acadb1a136618f0 [file] [log] [blame]
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +00001/*
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.view.textclassifier;
18
19import android.annotation.FloatRange;
Abodunrinwa Toki2f19b922018-02-12 19:59:28 +000020import android.annotation.IntDef;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +000021import android.annotation.IntRange;
22import android.annotation.NonNull;
23import android.annotation.Nullable;
Jan Althaus20d346e2018-03-23 14:03:52 +010024import android.app.PendingIntent;
25import android.app.RemoteAction;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +000026import android.content.Context;
27import android.content.Intent;
Abodunrinwa Tokief7cb2c2018-02-07 22:21:08 +000028import android.content.res.Resources;
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +010029import android.graphics.BitmapFactory;
30import android.graphics.drawable.AdaptiveIconDrawable;
Jan Althaus0d9fbb92017-11-28 12:19:33 +010031import android.graphics.drawable.BitmapDrawable;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +000032import android.graphics.drawable.Drawable;
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +010033import android.graphics.drawable.Icon;
Tony Makd6f3fb42018-10-26 15:42:49 +010034import android.os.Bundle;
Abodunrinwa Toki2b6020f2017-10-28 02:28:45 +010035import android.os.LocaleList;
Jan Althaus0d9fbb92017-11-28 12:19:33 +010036import android.os.Parcel;
37import android.os.Parcelable;
Abodunrinwa Toki0f138962018-12-03 22:35:10 +000038import android.text.SpannedString;
Jan Althausbbe43df2017-11-30 15:01:40 +010039import android.util.ArrayMap;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +000040import android.view.View.OnClickListener;
41import android.view.textclassifier.TextClassifier.EntityType;
Abodunrinwa Toki080c8542018-03-27 00:04:06 +010042import android.view.textclassifier.TextClassifier.Utils;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +000043
Abodunrinwa Toki0f138962018-12-03 22:35:10 +000044import com.android.internal.annotations.VisibleForTesting;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +000045import com.android.internal.util.Preconditions;
46
Tony Makfdb35542019-03-22 12:01:50 +000047import com.google.android.textclassifier.AnnotatorModel;
48
Abodunrinwa Toki2f19b922018-02-12 19:59:28 +000049import java.lang.annotation.Retention;
50import java.lang.annotation.RetentionPolicy;
Jan Althausa1652cf2018-03-29 17:51:57 +020051import java.time.ZonedDateTime;
Jan Althaus92d76832017-09-27 18:14:35 +020052import java.util.ArrayList;
Jan Althaus20d346e2018-03-23 14:03:52 +010053import java.util.Collections;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +000054import java.util.List;
Abodunrinwa Toki4d232d62017-11-23 12:22:45 +000055import java.util.Locale;
Jan Althausbbe43df2017-11-30 15:01:40 +010056import java.util.Map;
Abodunrinwa Toki25f7fdc2019-02-19 23:42:30 +000057import java.util.Objects;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +000058
59/**
60 * Information for generating a widget to handle classified text.
Abodunrinwa Toki33ff2002017-10-24 00:49:27 +010061 *
62 * <p>A TextClassification object contains icons, labels, onClickListeners and intents that may
Abodunrinwa Tokiba385622017-11-29 19:30:32 +000063 * be used to build a widget that can be used to act on classified text. There is the concept of a
64 * <i>primary action</i> and other <i>secondary actions</i>.
Abodunrinwa Toki33ff2002017-10-24 00:49:27 +010065 *
66 * <p>e.g. building a view that, when clicked, shares the classified text with the preferred app:
67 *
68 * <pre>{@code
69 * // Called preferably outside the UiThread.
Abodunrinwa Toki4d232d62017-11-23 12:22:45 +000070 * TextClassification classification = textClassifier.classifyText(allText, 10, 25);
Abodunrinwa Toki33ff2002017-10-24 00:49:27 +010071 *
72 * // Called on the UiThread.
73 * Button button = new Button(context);
74 * button.setCompoundDrawablesWithIntrinsicBounds(classification.getIcon(), null, null, null);
75 * button.setText(classification.getLabel());
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +010076 * button.setOnClickListener(v -> classification.getActions().get(0).getActionIntent().send());
Abodunrinwa Toki33ff2002017-10-24 00:49:27 +010077 * }</pre>
78 *
79 * <p>e.g. starting an action mode with menu items that can handle the classified text:
80 *
81 * <pre>{@code
82 * // Called preferably outside the UiThread.
Abodunrinwa Toki4d232d62017-11-23 12:22:45 +000083 * final TextClassification classification = textClassifier.classifyText(allText, 10, 25);
Abodunrinwa Toki33ff2002017-10-24 00:49:27 +010084 *
85 * // Called on the UiThread.
86 * view.startActionMode(new ActionMode.Callback() {
87 *
88 * public boolean onCreateActionMode(ActionMode mode, Menu menu) {
Jan Althaus20d346e2018-03-23 14:03:52 +010089 * for (int i = 0; i < classification.getActions().size(); ++i) {
90 * RemoteAction action = classification.getActions().get(i);
91 * menu.add(Menu.NONE, i, 20, action.getTitle())
92 * .setIcon(action.getIcon());
Abodunrinwa Toki33ff2002017-10-24 00:49:27 +010093 * }
94 * return true;
95 * }
96 *
97 * public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
Jan Althaus20d346e2018-03-23 14:03:52 +010098 * classification.getActions().get(item.getItemId()).getActionIntent().send();
Abodunrinwa Toki33ff2002017-10-24 00:49:27 +010099 * return true;
100 * }
101 *
102 * ...
103 * });
104 * }</pre>
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000105 */
Abodunrinwa Tokid32906c2018-01-18 04:34:44 -0800106public final class TextClassification implements Parcelable {
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000107
108 /**
109 * @hide
110 */
Abodunrinwa Tokiadc19402018-11-22 17:10:25 +0000111 public static final TextClassification EMPTY = new TextClassification.Builder().build();
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000112
Jan Althaus20d346e2018-03-23 14:03:52 +0100113 private static final String LOG_TAG = "TextClassification";
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100114 // TODO(toki): investigate a way to derive this based on device properties.
Jan Althaus20d346e2018-03-23 14:03:52 +0100115 private static final int MAX_LEGACY_ICON_SIZE = 192;
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100116
Abodunrinwa Toki2f19b922018-02-12 19:59:28 +0000117 @Retention(RetentionPolicy.SOURCE)
118 @IntDef(value = {IntentType.UNSUPPORTED, IntentType.ACTIVITY, IntentType.SERVICE})
119 private @interface IntentType {
120 int UNSUPPORTED = -1;
121 int ACTIVITY = 0;
122 int SERVICE = 1;
123 }
124
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000125 @NonNull private final String mText;
Jan Althaus20d346e2018-03-23 14:03:52 +0100126 @Nullable private final Drawable mLegacyIcon;
127 @Nullable private final String mLegacyLabel;
128 @Nullable private final Intent mLegacyIntent;
129 @Nullable private final OnClickListener mLegacyOnClickListener;
130 @NonNull private final List<RemoteAction> mActions;
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100131 @NonNull private final EntityConfidence mEntityConfidence;
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100132 @Nullable private final String mId;
Tony Makd6f3fb42018-10-26 15:42:49 +0100133 @NonNull private final Bundle mExtras;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000134
Abodunrinwa Tokie0b57892017-04-28 19:59:57 +0100135 private TextClassification(
Abodunrinwa Tokid44286f2017-07-12 19:38:54 +0100136 @Nullable String text,
Jan Althaus20d346e2018-03-23 14:03:52 +0100137 @Nullable Drawable legacyIcon,
138 @Nullable String legacyLabel,
139 @Nullable Intent legacyIntent,
140 @Nullable OnClickListener legacyOnClickListener,
141 @NonNull List<RemoteAction> actions,
Tony Makfdb35542019-03-22 12:01:50 +0000142 @NonNull EntityConfidence entityConfidence,
Tony Makd6f3fb42018-10-26 15:42:49 +0100143 @Nullable String id,
144 @NonNull Bundle extras) {
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000145 mText = text;
Jan Althaus20d346e2018-03-23 14:03:52 +0100146 mLegacyIcon = legacyIcon;
147 mLegacyLabel = legacyLabel;
148 mLegacyIntent = legacyIntent;
149 mLegacyOnClickListener = legacyOnClickListener;
150 mActions = Collections.unmodifiableList(actions);
Daulet Zhanguzine1559472019-12-18 14:17:56 +0000151 mEntityConfidence = Objects.requireNonNull(entityConfidence);
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100152 mId = id;
Tony Makd6f3fb42018-10-26 15:42:49 +0100153 mExtras = extras;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000154 }
155
156 /**
157 * Gets the classified text.
158 */
Abodunrinwa Tokid44286f2017-07-12 19:38:54 +0100159 @Nullable
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000160 public String getText() {
161 return mText;
162 }
163
164 /**
165 * Returns the number of entities found in the classified text.
166 */
167 @IntRange(from = 0)
168 public int getEntityCount() {
Jan Althausbbe43df2017-11-30 15:01:40 +0100169 return mEntityConfidence.getEntities().size();
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000170 }
171
172 /**
173 * Returns the entity at the specified index. Entities are ordered from high confidence
174 * to low confidence.
175 *
176 * @throws IndexOutOfBoundsException if the specified index is out of range.
177 * @see #getEntityCount() for the number of entities available.
178 */
179 @NonNull
180 public @EntityType String getEntity(int index) {
Jan Althausbbe43df2017-11-30 15:01:40 +0100181 return mEntityConfidence.getEntities().get(index);
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000182 }
183
184 /**
185 * Returns the confidence score for the specified entity. The value ranges from
186 * 0 (low confidence) to 1 (high confidence). 0 indicates that the entity was not found for the
187 * classified text.
188 */
189 @FloatRange(from = 0.0, to = 1.0)
190 public float getConfidenceScore(@EntityType String entity) {
191 return mEntityConfidence.getConfidenceScore(entity);
192 }
193
194 /**
Jan Althaus20d346e2018-03-23 14:03:52 +0100195 * Returns a list of actions that may be performed on the text. The list is ordered based on
196 * the likelihood that a user will use the action, with the most likely action appearing first.
Jan Althaus92d76832017-09-27 18:14:35 +0200197 */
Jan Althaus20d346e2018-03-23 14:03:52 +0100198 public List<RemoteAction> getActions() {
199 return mActions;
Jan Althaus92d76832017-09-27 18:14:35 +0200200 }
201
202 /**
Jan Althaus20d346e2018-03-23 14:03:52 +0100203 * Returns an icon that may be rendered on a widget used to act on the classified text.
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000204 *
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +0100205 * <p><strong>NOTE: </strong>This field is not parcelable and only represents the icon of the
206 * first {@link RemoteAction} (if one exists) when this object is read from a parcel.
207 *
Jan Althaus20d346e2018-03-23 14:03:52 +0100208 * @deprecated Use {@link #getActions()} instead.
Jan Althaus92d76832017-09-27 18:14:35 +0200209 */
Jan Althaus20d346e2018-03-23 14:03:52 +0100210 @Deprecated
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000211 @Nullable
212 public Drawable getIcon() {
Jan Althaus20d346e2018-03-23 14:03:52 +0100213 return mLegacyIcon;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000214 }
215
216 /**
Jan Althaus20d346e2018-03-23 14:03:52 +0100217 * Returns a label that may be rendered on a widget used to act on the classified text.
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000218 *
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +0100219 * <p><strong>NOTE: </strong>This field is not parcelable and only represents the label of the
220 * first {@link RemoteAction} (if one exists) when this object is read from a parcel.
221 *
Jan Althaus20d346e2018-03-23 14:03:52 +0100222 * @deprecated Use {@link #getActions()} instead.
Jan Althaus92d76832017-09-27 18:14:35 +0200223 */
Jan Althaus20d346e2018-03-23 14:03:52 +0100224 @Deprecated
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000225 @Nullable
226 public CharSequence getLabel() {
Jan Althaus20d346e2018-03-23 14:03:52 +0100227 return mLegacyLabel;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000228 }
229
230 /**
Jan Althaus20d346e2018-03-23 14:03:52 +0100231 * Returns an intent that may be fired to act on the classified text.
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000232 *
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +0100233 * <p><strong>NOTE: </strong>This field is not parcelled and will always return null when this
234 * object is read from a parcel.
235 *
Jan Althaus20d346e2018-03-23 14:03:52 +0100236 * @deprecated Use {@link #getActions()} instead.
Jan Althaus92d76832017-09-27 18:14:35 +0200237 */
Jan Althaus20d346e2018-03-23 14:03:52 +0100238 @Deprecated
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000239 @Nullable
240 public Intent getIntent() {
Jan Althaus20d346e2018-03-23 14:03:52 +0100241 return mLegacyIntent;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000242 }
243
244 /**
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +0100245 * Returns the OnClickListener that may be triggered to act on the classified text.
246 *
247 * <p><strong>NOTE: </strong>This field is not parcelable and only represents the first
248 * {@link RemoteAction} (if one exists) when this object is read from a parcel.
Jan Althaus20d346e2018-03-23 14:03:52 +0100249 *
250 * @deprecated Use {@link #getActions()} instead.
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000251 */
252 @Nullable
253 public OnClickListener getOnClickListener() {
Jan Althaus20d346e2018-03-23 14:03:52 +0100254 return mLegacyOnClickListener;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000255 }
256
Abodunrinwa Toki54486c12017-04-19 21:02:36 +0100257 /**
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100258 * Returns the id, if one exists, for this object.
Abodunrinwa Toki692b1962017-08-15 15:05:11 +0100259 */
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100260 @Nullable
261 public String getId() {
262 return mId;
Abodunrinwa Toki692b1962017-08-15 15:05:11 +0100263 }
264
Tony Makd6f3fb42018-10-26 15:42:49 +0100265 /**
266 * Returns the extended data.
267 *
Tony Mak5a8d8272019-04-08 15:46:13 +0100268 * <p><b>NOTE: </b>Do not modify this bundle.
Tony Makd6f3fb42018-10-26 15:42:49 +0100269 */
270 @NonNull
271 public Bundle getExtras() {
Tony Mak5a8d8272019-04-08 15:46:13 +0100272 return mExtras;
Tony Makd6f3fb42018-10-26 15:42:49 +0100273 }
274
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000275 @Override
276 public String toString() {
Jan Althaus20d346e2018-03-23 14:03:52 +0100277 return String.format(Locale.US,
Abodunrinwa Toki25f7fdc2019-02-19 23:42:30 +0000278 "TextClassification {text=%s, entities=%s, actions=%s, id=%s, extras=%s}",
279 mText, mEntityConfidence, mActions, mId, mExtras);
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000280 }
281
282 /**
Jan Althaus20d346e2018-03-23 14:03:52 +0100283 * Creates an OnClickListener that triggers the specified PendingIntent.
284 *
285 * @hide
286 */
287 public static OnClickListener createIntentOnClickListener(@NonNull final PendingIntent intent) {
Daulet Zhanguzine1559472019-12-18 14:17:56 +0000288 Objects.requireNonNull(intent);
Jan Althaus20d346e2018-03-23 14:03:52 +0100289 return v -> {
290 try {
291 intent.send();
292 } catch (PendingIntent.CanceledException e) {
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100293 Log.e(LOG_TAG, "Error sending PendingIntent", e);
Jan Althaus20d346e2018-03-23 14:03:52 +0100294 }
295 };
296 }
297
298 /**
299 * Creates a PendingIntent for the specified intent.
Abodunrinwa Toki2f19b922018-02-12 19:59:28 +0000300 * Returns null if the intent is not supported for the specified context.
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000301 *
302 * @throws IllegalArgumentException if context or intent is null
303 * @hide
304 */
Jan Althaus20d346e2018-03-23 14:03:52 +0100305 public static PendingIntent createPendingIntent(
Abodunrinwa Toki904a9312018-04-18 21:21:27 +0100306 @NonNull final Context context, @NonNull final Intent intent, int requestCode) {
Tony Makc12035e2019-02-26 17:45:34 +0000307 return PendingIntent.getActivity(
308 context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000309 }
310
311 /**
Abodunrinwa Tokie0b57892017-04-28 19:59:57 +0100312 * Builder for building {@link TextClassification} objects.
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000313 *
314 * <p>e.g.
315 *
316 * <pre>{@code
317 * TextClassification classification = new TextClassification.Builder()
318 * .setText(classifiedText)
319 * .setEntityType(TextClassifier.TYPE_EMAIL, 0.9)
320 * .setEntityType(TextClassifier.TYPE_OTHER, 0.1)
Jan Althaus20d346e2018-03-23 14:03:52 +0100321 * .addAction(remoteAction1)
322 * .addAction(remoteAction2)
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000323 * .build();
324 * }</pre>
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000325 */
326 public static final class Builder {
327
Jan Althaus20d346e2018-03-23 14:03:52 +0100328 @NonNull private List<RemoteAction> mActions = new ArrayList<>();
Tony Makfdb35542019-03-22 12:01:50 +0000329 @NonNull private final Map<String, Float> mTypeScoreMap = new ArrayMap<>();
330 @NonNull
331 private final Map<String, AnnotatorModel.ClassificationResult> mClassificationResults =
332 new ArrayMap<>();
Jan Althaus13a89c92018-04-09 16:14:36 +0200333 @Nullable private String mText;
334 @Nullable private Drawable mLegacyIcon;
335 @Nullable private String mLegacyLabel;
336 @Nullable private Intent mLegacyIntent;
337 @Nullable private OnClickListener mLegacyOnClickListener;
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100338 @Nullable private String mId;
Tony Makd6f3fb42018-10-26 15:42:49 +0100339 @Nullable private Bundle mExtras;
Abodunrinwa Toki520b2f82019-01-27 07:48:02 +0000340 @NonNull private final ArrayList<Intent> mActionIntents = new ArrayList<>();
341 @Nullable private Bundle mForeignLanguageExtra;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000342
343 /**
344 * Sets the classified text.
345 */
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100346 @NonNull
Abodunrinwa Tokid44286f2017-07-12 19:38:54 +0100347 public Builder setText(@Nullable String text) {
348 mText = text;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000349 return this;
350 }
351
352 /**
353 * Sets an entity type for the classification result and assigns a confidence score.
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000354 * If a confidence score had already been set for the specified entity type, this will
355 * override that score.
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000356 *
357 * @param confidenceScore a value from 0 (low confidence) to 1 (high confidence).
358 * 0 implies the entity does not exist for the classified text.
359 * Values greater than 1 are clamped to 1.
360 */
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100361 @NonNull
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000362 public Builder setEntityType(
363 @NonNull @EntityType String type,
Abodunrinwa Tokid44286f2017-07-12 19:38:54 +0100364 @FloatRange(from = 0.0, to = 1.0) float confidenceScore) {
Tony Makfdb35542019-03-22 12:01:50 +0000365 setEntityType(type, confidenceScore, null);
366 return this;
367 }
368
369 /**
370 * @see #setEntityType(String, float)
371 *
372 * @hide
373 */
374 @NonNull
375 public Builder setEntityType(AnnotatorModel.ClassificationResult classificationResult) {
376 setEntityType(
377 classificationResult.getCollection(),
378 classificationResult.getScore(),
379 classificationResult);
380 return this;
381 }
382
383 /**
384 * @see #setEntityType(String, float)
385 *
386 * @hide
387 */
388 @NonNull
389 private Builder setEntityType(
390 @NonNull @EntityType String type,
391 @FloatRange(from = 0.0, to = 1.0) float confidenceScore,
392 @Nullable AnnotatorModel.ClassificationResult classificationResult) {
393 mTypeScoreMap.put(type, confidenceScore);
394 mClassificationResults.put(type, classificationResult);
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000395 return this;
396 }
397
398 /**
Jan Althaus20d346e2018-03-23 14:03:52 +0100399 * Adds an action that may be performed on the classified text. Actions should be added in
400 * order of likelihood that the user will use them, with the most likely action being added
401 * first.
Jan Althaus92d76832017-09-27 18:14:35 +0200402 */
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100403 @NonNull
Jan Althaus20d346e2018-03-23 14:03:52 +0100404 public Builder addAction(@NonNull RemoteAction action) {
Abodunrinwa Toki520b2f82019-01-27 07:48:02 +0000405 return addAction(action, null);
406 }
407
408 /**
409 * @param intent the intent in the remote action.
410 * @see #addAction(RemoteAction)
411 * @hide
412 */
413 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
414 public Builder addAction(RemoteAction action, @Nullable Intent intent) {
Jan Althaus20d346e2018-03-23 14:03:52 +0100415 Preconditions.checkArgument(action != null);
416 mActions.add(action);
Abodunrinwa Toki520b2f82019-01-27 07:48:02 +0000417 mActionIntents.add(intent);
Jan Althaus92d76832017-09-27 18:14:35 +0200418 return this;
419 }
420
421 /**
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000422 * Sets the icon for the <i>primary</i> action that may be rendered on a widget used to act
423 * on the classified text.
424 *
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +0100425 * <p><strong>NOTE: </strong>This field is not parcelled. If read from a parcel, the
426 * returned icon represents the icon of the first {@link RemoteAction} (if one exists).
427 *
Jan Althaus20d346e2018-03-23 14:03:52 +0100428 * @deprecated Use {@link #addAction(RemoteAction)} instead.
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000429 */
Jan Althaus20d346e2018-03-23 14:03:52 +0100430 @Deprecated
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100431 @NonNull
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000432 public Builder setIcon(@Nullable Drawable icon) {
Jan Althaus20d346e2018-03-23 14:03:52 +0100433 mLegacyIcon = icon;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000434 return this;
435 }
436
437 /**
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000438 * Sets the label for the <i>primary</i> action that may be rendered on a widget used to
439 * act on the classified text.
440 *
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +0100441 * <p><strong>NOTE: </strong>This field is not parcelled. If read from a parcel, the
442 * returned label represents the label of the first {@link RemoteAction} (if one exists).
443 *
Jan Althaus20d346e2018-03-23 14:03:52 +0100444 * @deprecated Use {@link #addAction(RemoteAction)} instead.
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000445 */
Jan Althaus20d346e2018-03-23 14:03:52 +0100446 @Deprecated
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100447 @NonNull
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000448 public Builder setLabel(@Nullable String label) {
Jan Althaus20d346e2018-03-23 14:03:52 +0100449 mLegacyLabel = label;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000450 return this;
451 }
452
453 /**
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000454 * Sets the intent for the <i>primary</i> action that may be fired to act on the classified
455 * text.
456 *
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +0100457 * <p><strong>NOTE: </strong>This field is not parcelled.
458 *
Jan Althaus20d346e2018-03-23 14:03:52 +0100459 * @deprecated Use {@link #addAction(RemoteAction)} instead.
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000460 */
Jan Althaus20d346e2018-03-23 14:03:52 +0100461 @Deprecated
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100462 @NonNull
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000463 public Builder setIntent(@Nullable Intent intent) {
Jan Althaus20d346e2018-03-23 14:03:52 +0100464 mLegacyIntent = intent;
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000465 return this;
466 }
467
468 /**
469 * Sets the OnClickListener for the <i>primary</i> action that may be triggered to act on
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +0100470 * the classified text.
471 *
472 * <p><strong>NOTE: </strong>This field is not parcelable. If read from a parcel, the
473 * returned OnClickListener represents the first {@link RemoteAction} (if one exists).
Jan Althaus20d346e2018-03-23 14:03:52 +0100474 *
475 * @deprecated Use {@link #addAction(RemoteAction)} instead.
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000476 */
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100477 @Deprecated
478 @NonNull
Abodunrinwa Tokiba385622017-11-29 19:30:32 +0000479 public Builder setOnClickListener(@Nullable OnClickListener onClickListener) {
Jan Althaus20d346e2018-03-23 14:03:52 +0100480 mLegacyOnClickListener = onClickListener;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000481 return this;
482 }
483
484 /**
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100485 * Sets an id for the TextClassification object.
Abodunrinwa Toki54486c12017-04-19 21:02:36 +0100486 */
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100487 @NonNull
488 public Builder setId(@Nullable String id) {
489 mId = id;
Abodunrinwa Toki692b1962017-08-15 15:05:11 +0100490 return this;
491 }
492
493 /**
Tony Makd6f3fb42018-10-26 15:42:49 +0100494 * Sets the extended data.
495 */
496 @NonNull
497 public Builder setExtras(@Nullable Bundle extras) {
498 mExtras = extras;
499 return this;
500 }
501
502 /**
Abodunrinwa Toki520b2f82019-01-27 07:48:02 +0000503 * @see #setExtras(Bundle)
504 * @hide
505 */
506 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
507 public Builder setForeignLanguageExtra(@Nullable Bundle extra) {
508 mForeignLanguageExtra = extra;
509 return this;
510 }
511
512 /**
Abodunrinwa Tokie0b57892017-04-28 19:59:57 +0100513 * Builds and returns a {@link TextClassification} object.
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000514 */
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100515 @NonNull
Abodunrinwa Tokie0b57892017-04-28 19:59:57 +0100516 public TextClassification build() {
Tony Makfdb35542019-03-22 12:01:50 +0000517 EntityConfidence entityConfidence = new EntityConfidence(mTypeScoreMap);
Jan Althaus20d346e2018-03-23 14:03:52 +0100518 return new TextClassification(mText, mLegacyIcon, mLegacyLabel, mLegacyIntent,
Tony Makfdb35542019-03-22 12:01:50 +0000519 mLegacyOnClickListener, mActions, entityConfidence, mId,
520 buildExtras(entityConfidence));
Abodunrinwa Toki520b2f82019-01-27 07:48:02 +0000521 }
522
Tony Makfdb35542019-03-22 12:01:50 +0000523 private Bundle buildExtras(EntityConfidence entityConfidence) {
Tony Mak74828102019-04-10 17:53:13 +0100524 final Bundle extras = mExtras == null ? new Bundle() : mExtras;
Abodunrinwa Toki25f7fdc2019-02-19 23:42:30 +0000525 if (mActionIntents.stream().anyMatch(Objects::nonNull)) {
Abodunrinwa Toki520b2f82019-01-27 07:48:02 +0000526 ExtrasUtils.putActionsIntents(extras, mActionIntents);
527 }
528 if (mForeignLanguageExtra != null) {
529 ExtrasUtils.putForeignLanguageExtra(extras, mForeignLanguageExtra);
530 }
Tony Makfdb35542019-03-22 12:01:50 +0000531 List<String> sortedTypes = entityConfidence.getEntities();
532 ArrayList<AnnotatorModel.ClassificationResult> sortedEntities = new ArrayList<>();
533 for (String type : sortedTypes) {
534 sortedEntities.add(mClassificationResults.get(type));
535 }
536 ExtrasUtils.putEntities(
537 extras, sortedEntities.toArray(new AnnotatorModel.ClassificationResult[0]));
Abodunrinwa Toki520b2f82019-01-27 07:48:02 +0000538 return extras.isEmpty() ? Bundle.EMPTY : extras;
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000539 }
540 }
Abodunrinwa Toki2b6020f2017-10-28 02:28:45 +0100541
542 /**
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100543 * A request object for generating TextClassification.
Abodunrinwa Toki2b6020f2017-10-28 02:28:45 +0100544 */
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100545 public static final class Request implements Parcelable {
Abodunrinwa Toki2b6020f2017-10-28 02:28:45 +0100546
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100547 private final CharSequence mText;
548 private final int mStartIndex;
549 private final int mEndIndex;
550 @Nullable private final LocaleList mDefaultLocales;
551 @Nullable private final ZonedDateTime mReferenceTime;
Tony Makd6f3fb42018-10-26 15:42:49 +0100552 @NonNull private final Bundle mExtras;
Joanne Chung97d3a452020-03-04 19:03:11 +0800553 @Nullable private SystemTextClassifierMetadata mSystemTcMetadata;
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100554
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100555 private Request(
556 CharSequence text,
557 int startIndex,
558 int endIndex,
559 LocaleList defaultLocales,
Tony Makd6f3fb42018-10-26 15:42:49 +0100560 ZonedDateTime referenceTime,
561 Bundle extras) {
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100562 mText = text;
563 mStartIndex = startIndex;
564 mEndIndex = endIndex;
Abodunrinwa Toki2b6020f2017-10-28 02:28:45 +0100565 mDefaultLocales = defaultLocales;
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100566 mReferenceTime = referenceTime;
Tony Makd6f3fb42018-10-26 15:42:49 +0100567 mExtras = extras;
Abodunrinwa Toki2b6020f2017-10-28 02:28:45 +0100568 }
569
570 /**
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100571 * Returns the text providing context for the text to classify (which is specified
572 * by the sub sequence starting at startIndex and ending at endIndex)
Jan Althaus705b9e92018-01-22 18:22:29 +0100573 */
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100574 @NonNull
575 public CharSequence getText() {
576 return mText;
577 }
578
579 /**
580 * Returns start index of the text to classify.
581 */
582 @IntRange(from = 0)
583 public int getStartIndex() {
584 return mStartIndex;
585 }
586
587 /**
588 * Returns end index of the text to classify.
589 */
590 @IntRange(from = 0)
591 public int getEndIndex() {
592 return mEndIndex;
Jan Althaus705b9e92018-01-22 18:22:29 +0100593 }
594
595 /**
Abodunrinwa Toki2b6020f2017-10-28 02:28:45 +0100596 * @return ordered list of locale preferences that can be used to disambiguate
597 * the provided text.
598 */
599 @Nullable
600 public LocaleList getDefaultLocales() {
601 return mDefaultLocales;
602 }
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100603
Jan Althaus705b9e92018-01-22 18:22:29 +0100604 /**
605 * @return reference time based on which relative dates (e.g. "tomorrow") should be
606 * interpreted.
607 */
608 @Nullable
Jan Althausa1652cf2018-03-29 17:51:57 +0200609 public ZonedDateTime getReferenceTime() {
Jan Althaus705b9e92018-01-22 18:22:29 +0100610 return mReferenceTime;
611 }
612
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100613 /**
Abodunrinwa Toki0f138962018-12-03 22:35:10 +0000614 * Returns the name of the package that sent this request.
615 * This returns {@code null} if no calling package name is set.
616 */
617 @Nullable
618 public String getCallingPackageName() {
Joanne Chung97d3a452020-03-04 19:03:11 +0800619 return mSystemTcMetadata != null ? mSystemTcMetadata.getCallingPackageName() : null;
Abodunrinwa Toki0f138962018-12-03 22:35:10 +0000620 }
621
622 /**
Joanne Chung97d3a452020-03-04 19:03:11 +0800623 * Sets the information about the {@link SystemTextClassifier} that sent this request.
Tony Makc5a74322020-02-04 17:18:15 +0000624 *
625 * @hide
626 */
Joanne Chung97d3a452020-03-04 19:03:11 +0800627 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
628 public void setSystemTextClassifierMetadata(
629 @Nullable SystemTextClassifierMetadata systemTcMetadata) {
630 mSystemTcMetadata = systemTcMetadata;
Tony Makc5a74322020-02-04 17:18:15 +0000631 }
632
633 /**
Joanne Chung97d3a452020-03-04 19:03:11 +0800634 * Returns the information about the {@link SystemTextClassifier} that sent this request.
Tony Makc5a74322020-02-04 17:18:15 +0000635 *
636 * @hide
637 */
Joanne Chung97d3a452020-03-04 19:03:11 +0800638 @Nullable
639 public SystemTextClassifierMetadata getSystemTextClassifierMetadata() {
640 return mSystemTcMetadata;
Tony Makc5a74322020-02-04 17:18:15 +0000641 }
642
643 /**
Tony Makd6f3fb42018-10-26 15:42:49 +0100644 * Returns the extended data.
645 *
Tony Mak5a8d8272019-04-08 15:46:13 +0100646 * <p><b>NOTE: </b>Do not modify this bundle.
Tony Makd6f3fb42018-10-26 15:42:49 +0100647 */
648 @NonNull
649 public Bundle getExtras() {
Tony Mak5a8d8272019-04-08 15:46:13 +0100650 return mExtras;
Tony Makd6f3fb42018-10-26 15:42:49 +0100651 }
652
653 /**
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100654 * A builder for building TextClassification requests.
655 */
656 public static final class Builder {
657
658 private final CharSequence mText;
659 private final int mStartIndex;
660 private final int mEndIndex;
Tony Makd6f3fb42018-10-26 15:42:49 +0100661 private Bundle mExtras;
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100662
663 @Nullable private LocaleList mDefaultLocales;
664 @Nullable private ZonedDateTime mReferenceTime;
665
666 /**
667 * @param text text providing context for the text to classify (which is specified
668 * by the sub sequence starting at startIndex and ending at endIndex)
669 * @param startIndex start index of the text to classify
670 * @param endIndex end index of the text to classify
671 */
672 public Builder(
673 @NonNull CharSequence text,
674 @IntRange(from = 0) int startIndex,
675 @IntRange(from = 0) int endIndex) {
676 Utils.checkArgument(text, startIndex, endIndex);
677 mText = text;
678 mStartIndex = startIndex;
679 mEndIndex = endIndex;
680 }
681
682 /**
683 * @param defaultLocales ordered list of locale preferences that may be used to
684 * disambiguate the provided text. If no locale preferences exist, set this to null
685 * or an empty locale list.
686 *
687 * @return this builder
688 */
689 @NonNull
690 public Builder setDefaultLocales(@Nullable LocaleList defaultLocales) {
691 mDefaultLocales = defaultLocales;
692 return this;
693 }
694
695 /**
696 * @param referenceTime reference time based on which relative dates (e.g. "tomorrow"
697 * should be interpreted. This should usually be the time when the text was
698 * originally composed. If no reference time is set, now is used.
699 *
700 * @return this builder
701 */
702 @NonNull
703 public Builder setReferenceTime(@Nullable ZonedDateTime referenceTime) {
704 mReferenceTime = referenceTime;
705 return this;
706 }
707
708 /**
Tony Makd6f3fb42018-10-26 15:42:49 +0100709 * Sets the extended data.
710 *
711 * @return this builder
712 */
713 @NonNull
714 public Builder setExtras(@Nullable Bundle extras) {
715 mExtras = extras;
716 return this;
717 }
718
719 /**
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100720 * Builds and returns the request object.
721 */
722 @NonNull
723 public Request build() {
Abodunrinwa Toki0f138962018-12-03 22:35:10 +0000724 return new Request(new SpannedString(mText), mStartIndex, mEndIndex,
725 mDefaultLocales, mReferenceTime,
Tony Mak74828102019-04-10 17:53:13 +0100726 mExtras == null ? Bundle.EMPTY : mExtras);
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100727 }
728 }
729
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100730 @Override
731 public int describeContents() {
732 return 0;
733 }
734
735 @Override
736 public void writeToParcel(Parcel dest, int flags) {
Abodunrinwa Toki0f138962018-12-03 22:35:10 +0000737 dest.writeCharSequence(mText);
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100738 dest.writeInt(mStartIndex);
739 dest.writeInt(mEndIndex);
Abodunrinwa Toki0f138962018-12-03 22:35:10 +0000740 dest.writeParcelable(mDefaultLocales, flags);
741 dest.writeString(mReferenceTime == null ? null : mReferenceTime.toString());
Tony Makd6f3fb42018-10-26 15:42:49 +0100742 dest.writeBundle(mExtras);
Joanne Chung97d3a452020-03-04 19:03:11 +0800743 dest.writeParcelable(mSystemTcMetadata, flags);
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100744 }
745
Abodunrinwa Toki0f138962018-12-03 22:35:10 +0000746 private static Request readFromParcel(Parcel in) {
747 final CharSequence text = in.readCharSequence();
748 final int startIndex = in.readInt();
749 final int endIndex = in.readInt();
750 final LocaleList defaultLocales = in.readParcelable(null);
751 final String referenceTimeString = in.readString();
752 final ZonedDateTime referenceTime = referenceTimeString == null
753 ? null : ZonedDateTime.parse(referenceTimeString);
Abodunrinwa Toki0f138962018-12-03 22:35:10 +0000754 final Bundle extras = in.readBundle();
Joanne Chung97d3a452020-03-04 19:03:11 +0800755 final SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null);
Abodunrinwa Toki0f138962018-12-03 22:35:10 +0000756
757 final Request request = new Request(text, startIndex, endIndex,
758 defaultLocales, referenceTime, extras);
Joanne Chung97d3a452020-03-04 19:03:11 +0800759 request.setSystemTextClassifierMetadata(systemTcMetadata);
Abodunrinwa Toki0f138962018-12-03 22:35:10 +0000760 return request;
761 }
762
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700763 public static final @android.annotation.NonNull Parcelable.Creator<Request> CREATOR =
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100764 new Parcelable.Creator<Request>() {
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100765 @Override
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100766 public Request createFromParcel(Parcel in) {
Abodunrinwa Toki0f138962018-12-03 22:35:10 +0000767 return readFromParcel(in);
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100768 }
769
770 @Override
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100771 public Request[] newArray(int size) {
772 return new Request[size];
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100773 }
774 };
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100775 }
776
Abodunrinwa Tokid32906c2018-01-18 04:34:44 -0800777 @Override
778 public int describeContents() {
779 return 0;
780 }
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100781
Abodunrinwa Tokid32906c2018-01-18 04:34:44 -0800782 @Override
783 public void writeToParcel(Parcel dest, int flags) {
784 dest.writeString(mText);
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +0100785 // NOTE: legacy fields are not parcelled.
Jan Althaus20d346e2018-03-23 14:03:52 +0100786 dest.writeTypedList(mActions);
Abodunrinwa Tokid32906c2018-01-18 04:34:44 -0800787 mEntityConfidence.writeToParcel(dest, flags);
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100788 dest.writeString(mId);
Tony Makd6f3fb42018-10-26 15:42:49 +0100789 dest.writeBundle(mExtras);
Abodunrinwa Tokid32906c2018-01-18 04:34:44 -0800790 }
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100791
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700792 public static final @android.annotation.NonNull Parcelable.Creator<TextClassification> CREATOR =
Abodunrinwa Tokid32906c2018-01-18 04:34:44 -0800793 new Parcelable.Creator<TextClassification>() {
794 @Override
795 public TextClassification createFromParcel(Parcel in) {
796 return new TextClassification(in);
797 }
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100798
Abodunrinwa Tokid32906c2018-01-18 04:34:44 -0800799 @Override
800 public TextClassification[] newArray(int size) {
801 return new TextClassification[size];
802 }
803 };
Jan Althaus0d9fbb92017-11-28 12:19:33 +0100804
Abodunrinwa Tokid32906c2018-01-18 04:34:44 -0800805 private TextClassification(Parcel in) {
806 mText = in.readString();
Jan Althaus20d346e2018-03-23 14:03:52 +0100807 mActions = in.createTypedArrayList(RemoteAction.CREATOR);
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +0100808 if (!mActions.isEmpty()) {
809 final RemoteAction action = mActions.get(0);
810 mLegacyIcon = maybeLoadDrawable(action.getIcon());
811 mLegacyLabel = action.getTitle().toString();
812 mLegacyOnClickListener = createIntentOnClickListener(mActions.get(0).getActionIntent());
813 } else {
814 mLegacyIcon = null;
815 mLegacyLabel = null;
816 mLegacyOnClickListener = null;
817 }
818 mLegacyIntent = null; // mLegacyIntent is not parcelled.
Abodunrinwa Tokid32906c2018-01-18 04:34:44 -0800819 mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
Abodunrinwa Toki080c8542018-03-27 00:04:06 +0100820 mId = in.readString();
Tony Makd6f3fb42018-10-26 15:42:49 +0100821 mExtras = in.readBundle();
Abodunrinwa Toki2b6020f2017-10-28 02:28:45 +0100822 }
Abodunrinwa Tokiae82e7a2018-04-03 23:49:16 +0100823
Abodunrinwa Tokiba196c52018-04-20 19:52:21 +0100824 // Best effort attempt to try to load a drawable from the provided icon.
825 @Nullable
826 private static Drawable maybeLoadDrawable(Icon icon) {
827 if (icon == null) {
828 return null;
829 }
830 switch (icon.getType()) {
831 case Icon.TYPE_BITMAP:
832 return new BitmapDrawable(Resources.getSystem(), icon.getBitmap());
833 case Icon.TYPE_ADAPTIVE_BITMAP:
834 return new AdaptiveIconDrawable(null,
835 new BitmapDrawable(Resources.getSystem(), icon.getBitmap()));
836 case Icon.TYPE_DATA:
837 return new BitmapDrawable(
838 Resources.getSystem(),
839 BitmapFactory.decodeByteArray(
840 icon.getDataBytes(), icon.getDataOffset(), icon.getDataLength()));
841 }
842 return null;
843 }
Abodunrinwa Tokif001fef2017-01-04 23:51:42 +0000844}