/* * Copyright (C) 2018 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.FloatRange; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.icu.util.ULocale; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.util.ArrayMap; import com.android.internal.annotations.VisibleForTesting; import java.util.Locale; import java.util.Map; import java.util.Objects; /** * Represents the result of language detection of a piece of text. *

* This contains a list of locales, each paired with a confidence score, sorted in decreasing * order of those scores. E.g., for a given input text, the model may return * {@code [<"en", 0.85>, <"fr", 0.15>]}. This sample result means the model reports that it is * 85% likely that the entire text is in English and 15% likely that the entire text is in French, * etc. It does not mean that 85% of the input is in English and 15% is in French. */ public final class TextLanguage implements Parcelable { public static final @android.annotation.NonNull Creator CREATOR = new Creator() { @Override public TextLanguage createFromParcel(Parcel in) { return readFromParcel(in); } @Override public TextLanguage[] newArray(int size) { return new TextLanguage[size]; } }; static final TextLanguage EMPTY = new Builder().build(); @Nullable private final String mId; private final EntityConfidence mEntityConfidence; private final Bundle mBundle; private TextLanguage( @Nullable String id, EntityConfidence entityConfidence, Bundle bundle) { mId = id; mEntityConfidence = entityConfidence; mBundle = bundle; } /** * Returns the id, if one exists, for this object. */ @Nullable public String getId() { return mId; } /** * Returns the number of possible locales for the processed text. */ @IntRange(from = 0) public int getLocaleHypothesisCount() { return mEntityConfidence.getEntities().size(); } /** * Returns the language locale at the specified index. Locales are ordered from high * confidence to low confidence. *

* See {@link #getLocaleHypothesisCount()} for the number of locales available. * * @throws IndexOutOfBoundsException if the specified index is out of range. */ @NonNull public ULocale getLocale(int index) { return ULocale.forLanguageTag(mEntityConfidence.getEntities().get(index)); } /** * Returns the confidence score for the specified language locale. The value ranges from * 0 (low confidence) to 1 (high confidence). 0 indicates that the locale was not found for * the processed text. */ @FloatRange(from = 0.0, to = 1.0) public float getConfidenceScore(@NonNull ULocale locale) { return mEntityConfidence.getConfidenceScore(locale.toLanguageTag()); } /** * Returns a bundle containing non-structured extra information about this result. What is * returned in the extras is specific to the {@link TextClassifier} implementation. * *

NOTE: Do not modify this bundle. */ @NonNull public Bundle getExtras() { return mBundle; } @Override public String toString() { return String.format( Locale.US, "TextLanguage {id=%s, locales=%s, bundle=%s}", mId, mEntityConfidence, mBundle); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mId); mEntityConfidence.writeToParcel(dest, flags); dest.writeBundle(mBundle); } private static TextLanguage readFromParcel(Parcel in) { return new TextLanguage( in.readString(), EntityConfidence.CREATOR.createFromParcel(in), in.readBundle()); } /** * Builder used to build TextLanguage objects. */ public static final class Builder { @Nullable private String mId; private final Map mEntityConfidenceMap = new ArrayMap<>(); @Nullable private Bundle mBundle; /** * Sets a language locale for the processed text and assigns a confidence score. If the * locale has already been set, this updates it. * * @param confidenceScore a value from 0 (low confidence) to 1 (high confidence). * 0 implies the locale does not exist for the processed text. * Values greater than 1 are clamped to 1. */ @NonNull public Builder putLocale( @NonNull ULocale locale, @FloatRange(from = 0.0, to = 1.0) float confidenceScore) { Objects.requireNonNull(locale); mEntityConfidenceMap.put(locale.toLanguageTag(), confidenceScore); return this; } /** * Sets an optional id for the TextLanguage object. */ @NonNull public Builder setId(@Nullable String id) { mId = id; return this; } /** * Sets a bundle containing non-structured extra information about the TextLanguage object. */ @NonNull public Builder setExtras(@NonNull Bundle bundle) { mBundle = Objects.requireNonNull(bundle); return this; } /** * Builds and returns a new TextLanguage object. *

* If necessary, this method will verify fields, clamp them, and make them immutable. */ @NonNull public TextLanguage build() { mBundle = mBundle == null ? Bundle.EMPTY : mBundle; return new TextLanguage( mId, new EntityConfidence(mEntityConfidenceMap), mBundle); } } /** * A request object for detecting the language of a piece of text. */ public static final class Request implements Parcelable { public static final @android.annotation.NonNull Creator CREATOR = new Creator() { @Override public Request createFromParcel(Parcel in) { return readFromParcel(in); } @Override public Request[] newArray(int size) { return new Request[size]; } }; private final CharSequence mText; private final Bundle mExtra; @Nullable private SystemTextClassifierMetadata mSystemTcMetadata; private Request(CharSequence text, Bundle bundle) { mText = text; mExtra = bundle; } /** * Returns the text to process. */ @NonNull public CharSequence getText() { return mText; } /** * Returns the name of the package that sent this request. * This returns null if no calling package name is set. */ @Nullable public String getCallingPackageName() { return mSystemTcMetadata != null ? mSystemTcMetadata.getCallingPackageName() : null; } /** * Sets the information about the {@link SystemTextClassifier} that sent this request. * * @hide */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public void setSystemTextClassifierMetadata( @Nullable SystemTextClassifierMetadata systemTcMetadata) { mSystemTcMetadata = systemTcMetadata; } /** * Returns the information about the {@link SystemTextClassifier} that sent this request. * * @hide */ @Nullable public SystemTextClassifierMetadata getSystemTextClassifierMetadata() { return mSystemTcMetadata; } /** * Returns a bundle containing non-structured extra information about this request. * *

NOTE: Do not modify this bundle. */ @NonNull public Bundle getExtras() { return mExtra; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeCharSequence(mText); dest.writeBundle(mExtra); dest.writeParcelable(mSystemTcMetadata, flags); } private static Request readFromParcel(Parcel in) { final CharSequence text = in.readCharSequence(); final Bundle extra = in.readBundle(); final SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null, android.view.textclassifier.SystemTextClassifierMetadata.class); final Request request = new Request(text, extra); request.setSystemTextClassifierMetadata(systemTcMetadata); return request; } /** * A builder for building TextLanguage requests. */ public static final class Builder { private final CharSequence mText; @Nullable private Bundle mBundle; /** * Creates a builder to build TextLanguage requests. * * @param text the text to process. */ public Builder(@NonNull CharSequence text) { mText = Objects.requireNonNull(text); } /** * Sets a bundle containing non-structured extra information about the request. */ @NonNull public Builder setExtras(@NonNull Bundle bundle) { mBundle = Objects.requireNonNull(bundle); return this; } /** * Builds and returns a new TextLanguage request object. *

* If necessary, this method will verify fields, clamp them, and make them immutable. */ @NonNull public Request build() { return new Request(mText.toString(), mBundle == null ? Bundle.EMPTY : mBundle); } } } }