summaryrefslogtreecommitdiff
path: root/jni
diff options
context:
space:
mode:
authorTony Mak <tonymak@google.com>2019-08-13 20:02:00 +0100
committerTony Mak <tonymak@google.com>2019-09-02 11:28:55 +0100
commit608b1ae3ec66e3ecf5716614fc98de6318e35cc0 (patch)
tree3abc2576780304f27c97be3707b23972c935b2ea /jni
parent482594b2ec66deccf820718e411af73743cb1fe0 (diff)
downloadlibtextclassifier-608b1ae3ec66e3ecf5716614fc98de6318e35cc0.tar.gz
Check-in initial version of TextClassifierService in external/libtc
1. Move existing native codes to native folder. 2. Move existing jni java codes to jni. 3. Copy TextClassifierService java codes to java Three build targets are introduced: 1. TextClassifierServiceLibNoManifest:All the java codes without AndroidManifest, will be used by ExtServices. 2. TextClassifierServiceLib: All the java codes with AndroidManifest, used by our test and our own APK. 3. TextClassifierService: Our standalone TCS APK, mostly for our own testing. Test: atest TextClassifierServiceTest Test: Install the apk, try smart selection. Bug: 135110855 Change-Id: I17173769bc20cc36d6d16bd8ea511ecbaac4bb5d
Diffstat (limited to 'jni')
-rw-r--r--jni/Android.bp19
-rw-r--r--jni/com/google/android/textclassifier/ActionsSuggestionsModel.java265
-rw-r--r--jni/com/google/android/textclassifier/AnnotatorModel.java591
-rw-r--r--jni/com/google/android/textclassifier/LangIdModel.java119
-rw-r--r--jni/com/google/android/textclassifier/NamedVariant.java115
-rw-r--r--jni/com/google/android/textclassifier/RemoteActionTemplate.java91
6 files changed, 1200 insertions, 0 deletions
diff --git a/jni/Android.bp b/jni/Android.bp
new file mode 100644
index 0000000..569368e
--- /dev/null
+++ b/jni/Android.bp
@@ -0,0 +1,19 @@
+// 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.
+
+java_library_static {
+ name: "libtextclassifier-java",
+ sdk_version: "core_current",
+ srcs: ["**/*.java"],
+} \ No newline at end of file
diff --git a/jni/com/google/android/textclassifier/ActionsSuggestionsModel.java b/jni/com/google/android/textclassifier/ActionsSuggestionsModel.java
new file mode 100644
index 0000000..9132b1f
--- /dev/null
+++ b/jni/com/google/android/textclassifier/ActionsSuggestionsModel.java
@@ -0,0 +1,265 @@
+/*
+ * 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 com.google.android.textclassifier;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Java wrapper for ActionsSuggestions native library interface. This library is used to suggest
+ * actions and replies in a given conversation.
+ *
+ * @hide
+ */
+public final class ActionsSuggestionsModel implements AutoCloseable {
+ private final AtomicBoolean isClosed = new AtomicBoolean(false);
+
+ static {
+ System.loadLibrary("textclassifier");
+ }
+
+ private long actionsModelPtr;
+
+ /**
+ * Creates a new instance of Actions predictor, using the provided model image, given as a file
+ * descriptor.
+ */
+ public ActionsSuggestionsModel(int fileDescriptor, byte[] serializedPreconditions) {
+ actionsModelPtr = nativeNewActionsModel(fileDescriptor, serializedPreconditions);
+ if (actionsModelPtr == 0L) {
+ throw new IllegalArgumentException("Couldn't initialize actions model from file descriptor.");
+ }
+ }
+
+ public ActionsSuggestionsModel(int fileDescriptor) {
+ this(fileDescriptor, /* serializedPreconditions= */ null);
+ }
+
+ /**
+ * Creates a new instance of Actions predictor, using the provided model image, given as a file
+ * path.
+ */
+ public ActionsSuggestionsModel(String path, byte[] serializedPreconditions) {
+ actionsModelPtr = nativeNewActionsModelFromPath(path, serializedPreconditions);
+ if (actionsModelPtr == 0L) {
+ throw new IllegalArgumentException("Couldn't initialize actions model from given file.");
+ }
+ }
+
+ public ActionsSuggestionsModel(String path) {
+ this(path, /* serializedPreconditions= */ null);
+ }
+
+ /** Suggests actions / replies to the given conversation. */
+ public ActionSuggestion[] suggestActions(
+ Conversation conversation, ActionSuggestionOptions options, AnnotatorModel annotator) {
+ return nativeSuggestActions(
+ actionsModelPtr,
+ conversation,
+ options,
+ (annotator != null ? annotator.getNativeAnnotator() : 0),
+ /* appContext= */ null,
+ /* deviceLocales= */ null,
+ /* generateAndroidIntents= */ false);
+ }
+
+ public ActionSuggestion[] suggestActionsWithIntents(
+ Conversation conversation,
+ ActionSuggestionOptions options,
+ Object appContext,
+ String deviceLocales,
+ AnnotatorModel annotator) {
+ return nativeSuggestActions(
+ actionsModelPtr,
+ conversation,
+ options,
+ (annotator != null ? annotator.getNativeAnnotator() : 0),
+ appContext,
+ deviceLocales,
+ /* generateAndroidIntents= */ true);
+ }
+
+ /** Frees up the allocated memory. */
+ @Override
+ public void close() {
+ if (isClosed.compareAndSet(false, true)) {
+ nativeCloseActionsModel(actionsModelPtr);
+ actionsModelPtr = 0L;
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /** Returns a comma separated list of locales supported by the model as BCP 47 tags. */
+ public static String getLocales(int fd) {
+ return nativeGetLocales(fd);
+ }
+
+ /** Returns the version of the model. */
+ public static int getVersion(int fd) {
+ return nativeGetVersion(fd);
+ }
+
+ /** Returns the name of the model. */
+ public static String getName(int fd) {
+ return nativeGetName(fd);
+ }
+
+ /** Action suggestion that contains a response text and the type of the response. */
+ public static final class ActionSuggestion {
+ private final String responseText;
+ private final String actionType;
+ private final float score;
+ private final NamedVariant[] entityData;
+ private final byte[] serializedEntityData;
+ private final RemoteActionTemplate[] remoteActionTemplates;
+
+ public ActionSuggestion(
+ String responseText,
+ String actionType,
+ float score,
+ NamedVariant[] entityData,
+ byte[] serializedEntityData,
+ RemoteActionTemplate[] remoteActionTemplates) {
+ this.responseText = responseText;
+ this.actionType = actionType;
+ this.score = score;
+ this.entityData = entityData;
+ this.serializedEntityData = serializedEntityData;
+ this.remoteActionTemplates = remoteActionTemplates;
+ }
+
+ public String getResponseText() {
+ return responseText;
+ }
+
+ public String getActionType() {
+ return actionType;
+ }
+
+ /** Confidence score between 0 and 1 */
+ public float getScore() {
+ return score;
+ }
+
+ public NamedVariant[] getEntityData() {
+ return entityData;
+ }
+
+ public byte[] getSerializedEntityData() {
+ return serializedEntityData;
+ }
+
+ public RemoteActionTemplate[] getRemoteActionTemplates() {
+ return remoteActionTemplates;
+ }
+ }
+
+ /** Represents a single message in the conversation. */
+ public static final class ConversationMessage {
+ private final int userId;
+ private final String text;
+ private final long referenceTimeMsUtc;
+ private final String referenceTimezone;
+ private final String detectedTextLanguageTags;
+
+ public ConversationMessage(
+ int userId,
+ String text,
+ long referenceTimeMsUtc,
+ String referenceTimezone,
+ String detectedTextLanguageTags) {
+ this.userId = userId;
+ this.text = text;
+ this.referenceTimeMsUtc = referenceTimeMsUtc;
+ this.referenceTimezone = referenceTimezone;
+ this.detectedTextLanguageTags = detectedTextLanguageTags;
+ }
+
+ /** The identifier of the sender */
+ public int getUserId() {
+ return userId;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Return the reference time of the message, for example, it could be compose time or send time.
+ * {@code 0} means unspecified.
+ */
+ public long getReferenceTimeMsUtc() {
+ return referenceTimeMsUtc;
+ }
+
+ public String getReferenceTimezone() {
+ return referenceTimezone;
+ }
+
+ /** Returns a comma separated list of BCP 47 language tags. */
+ public String getDetectedTextLanguageTags() {
+ return detectedTextLanguageTags;
+ }
+ }
+
+ /** Represents conversation between multiple users. */
+ public static final class Conversation {
+ public final ConversationMessage[] conversationMessages;
+
+ public Conversation(ConversationMessage[] conversationMessages) {
+ this.conversationMessages = conversationMessages;
+ }
+
+ public ConversationMessage[] getConversationMessages() {
+ return conversationMessages;
+ }
+ }
+
+ /** Represents options for the SuggestActions call. */
+ public static final class ActionSuggestionOptions {
+ public ActionSuggestionOptions() {}
+ }
+
+ private static native long nativeNewActionsModel(int fd, byte[] serializedPreconditions);
+
+ private static native long nativeNewActionsModelFromPath(
+ String path, byte[] preconditionsOverwrite);
+
+ private static native String nativeGetLocales(int fd);
+
+ private static native int nativeGetVersion(int fd);
+
+ private static native String nativeGetName(int fd);
+
+ private native ActionSuggestion[] nativeSuggestActions(
+ long context,
+ Conversation conversation,
+ ActionSuggestionOptions options,
+ long annotatorPtr,
+ Object appContext,
+ String deviceLocales,
+ boolean generateAndroidIntents);
+
+ private native void nativeCloseActionsModel(long ptr);
+}
diff --git a/jni/com/google/android/textclassifier/AnnotatorModel.java b/jni/com/google/android/textclassifier/AnnotatorModel.java
new file mode 100644
index 0000000..5f99f74
--- /dev/null
+++ b/jni/com/google/android/textclassifier/AnnotatorModel.java
@@ -0,0 +1,591 @@
+/*
+ * 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 com.google.android.textclassifier;
+
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Java wrapper for Annotator native library interface. This library is used for detecting entities
+ * in text.
+ *
+ * @hide
+ */
+public final class AnnotatorModel implements AutoCloseable {
+ private final AtomicBoolean isClosed = new AtomicBoolean(false);
+
+ static {
+ System.loadLibrary("textclassifier");
+ }
+
+ // Keep these in sync with the constants defined in AOSP.
+ static final String TYPE_UNKNOWN = "";
+ static final String TYPE_OTHER = "other";
+ static final String TYPE_EMAIL = "email";
+ static final String TYPE_PHONE = "phone";
+ static final String TYPE_ADDRESS = "address";
+ static final String TYPE_URL = "url";
+ static final String TYPE_DATE = "date";
+ static final String TYPE_DATE_TIME = "datetime";
+ static final String TYPE_FLIGHT_NUMBER = "flight";
+
+ private long annotatorPtr;
+
+ /** Enumeration for specifying the usecase of the annotations. */
+ public static enum AnnotationUsecase {
+ /** Results are optimized for Smart{Select,Share,Linkify}. */
+ SMART(0),
+
+ /**
+ * Results are optimized for using TextClassifier as an infrastructure that annotates as much as
+ * possible.
+ */
+ RAW(1);
+
+ private final int value;
+
+ AnnotationUsecase(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+ };
+
+ /**
+ * Creates a new instance of SmartSelect predictor, using the provided model image, given as a
+ * file descriptor.
+ */
+ public AnnotatorModel(int fileDescriptor) {
+ annotatorPtr = nativeNewAnnotator(fileDescriptor);
+ if (annotatorPtr == 0L) {
+ throw new IllegalArgumentException("Couldn't initialize TC from file descriptor.");
+ }
+ }
+
+ /**
+ * Creates a new instance of SmartSelect predictor, using the provided model image, given as a
+ * file path.
+ */
+ public AnnotatorModel(String path) {
+ annotatorPtr = nativeNewAnnotatorFromPath(path);
+ if (annotatorPtr == 0L) {
+ throw new IllegalArgumentException("Couldn't initialize TC from given file.");
+ }
+ }
+
+ /** Initializes the knowledge engine, passing the given serialized config to it. */
+ public void initializeKnowledgeEngine(byte[] serializedConfig) {
+ if (!nativeInitializeKnowledgeEngine(annotatorPtr, serializedConfig)) {
+ throw new IllegalArgumentException("Couldn't initialize the KG engine");
+ }
+ }
+
+ /** Initializes the contact engine, passing the given serialized config to it. */
+ public void initializeContactEngine(byte[] serializedConfig) {
+ if (!nativeInitializeContactEngine(annotatorPtr, serializedConfig)) {
+ throw new IllegalArgumentException("Couldn't initialize the contact engine");
+ }
+ }
+
+ /** Initializes the installed app engine, passing the given serialized config to it. */
+ public void initializeInstalledAppEngine(byte[] serializedConfig) {
+ if (!nativeInitializeInstalledAppEngine(annotatorPtr, serializedConfig)) {
+ throw new IllegalArgumentException("Couldn't initialize the installed app engine");
+ }
+ }
+
+ /**
+ * Given a string context and current selection, computes the selection suggestion.
+ *
+ * <p>The begin and end are character indices into the context UTF8 string. selectionBegin is the
+ * character index where the selection begins, and selectionEnd is the index of one character past
+ * the selection span.
+ *
+ * <p>The return value is an array of two ints: suggested selection beginning and end, with the
+ * same semantics as the input selectionBeginning and selectionEnd.
+ */
+ public int[] suggestSelection(
+ String context, int selectionBegin, int selectionEnd, SelectionOptions options) {
+ return nativeSuggestSelection(annotatorPtr, context, selectionBegin, selectionEnd, options);
+ }
+
+ /**
+ * Given a string context and current selection, classifies the type of the selected text.
+ *
+ * <p>The begin and end params are character indices in the context string.
+ *
+ * <p>Returns an array of ClassificationResult objects with the probability scores for different
+ * collections.
+ */
+ public ClassificationResult[] classifyText(
+ String context, int selectionBegin, int selectionEnd, ClassificationOptions options) {
+ return classifyText(
+ context,
+ selectionBegin,
+ selectionEnd,
+ options,
+ /*appContext=*/ null,
+ /*deviceLocales=*/ null);
+ }
+
+ public ClassificationResult[] classifyText(
+ String context,
+ int selectionBegin,
+ int selectionEnd,
+ ClassificationOptions options,
+ Object appContext,
+ String deviceLocales) {
+ return nativeClassifyText(
+ annotatorPtr, context, selectionBegin, selectionEnd, options, appContext, deviceLocales);
+ }
+
+ /**
+ * Annotates given input text. The annotations should cover the whole input context except for
+ * whitespaces, and are sorted by their position in the context string.
+ */
+ public AnnotatedSpan[] annotate(String text, AnnotationOptions options) {
+ return nativeAnnotate(annotatorPtr, text, options);
+ }
+
+ /**
+ * Looks up a knowledge entity by its identifier. Returns null if the entity is not found or on
+ * error.
+ */
+ public byte[] lookUpKnowledgeEntity(String id) {
+ return nativeLookUpKnowledgeEntity(annotatorPtr, id);
+ }
+
+ /** Frees up the allocated memory. */
+ @Override
+ public void close() {
+ if (isClosed.compareAndSet(false, true)) {
+ nativeCloseAnnotator(annotatorPtr);
+ annotatorPtr = 0L;
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /** Returns a comma separated list of locales supported by the model as BCP 47 tags. */
+ public static String getLocales(int fd) {
+ return nativeGetLocales(fd);
+ }
+
+ /** Returns the version of the model. */
+ public static int getVersion(int fd) {
+ return nativeGetVersion(fd);
+ }
+
+ /** Returns the name of the model. */
+ public static String getName(int fd) {
+ return nativeGetName(fd);
+ }
+
+ /** Information about a parsed time/date. */
+ public static final class DatetimeResult {
+
+ public static final int GRANULARITY_YEAR = 0;
+ public static final int GRANULARITY_MONTH = 1;
+ public static final int GRANULARITY_WEEK = 2;
+ public static final int GRANULARITY_DAY = 3;
+ public static final int GRANULARITY_HOUR = 4;
+ public static final int GRANULARITY_MINUTE = 5;
+ public static final int GRANULARITY_SECOND = 6;
+
+ private final long timeMsUtc;
+ private final int granularity;
+
+ public DatetimeResult(long timeMsUtc, int granularity) {
+ this.timeMsUtc = timeMsUtc;
+ this.granularity = granularity;
+ }
+
+ public long getTimeMsUtc() {
+ return timeMsUtc;
+ }
+
+ public int getGranularity() {
+ return granularity;
+ }
+ }
+
+ /** Classification result for classifyText method. */
+ public static final class ClassificationResult {
+ private final String collection;
+ private final float score;
+ private final DatetimeResult datetimeResult;
+ private final byte[] serializedKnowledgeResult;
+ private final String contactName;
+ private final String contactGivenName;
+ private final String contactNickname;
+ private final String contactEmailAddress;
+ private final String contactPhoneNumber;
+ private final String contactId;
+ private final String appName;
+ private final String appPackageName;
+ private final NamedVariant[] entityData;
+ private final byte[] serializedEntityData;
+ private final RemoteActionTemplate[] remoteActionTemplates;
+ private final long durationMs;
+ private final long numericValue;
+
+ public ClassificationResult(
+ String collection,
+ float score,
+ DatetimeResult datetimeResult,
+ byte[] serializedKnowledgeResult,
+ String contactName,
+ String contactGivenName,
+ String contactNickname,
+ String contactEmailAddress,
+ String contactPhoneNumber,
+ String contactId,
+ String appName,
+ String appPackageName,
+ NamedVariant[] entityData,
+ byte[] serializedEntityData,
+ RemoteActionTemplate[] remoteActionTemplates,
+ long durationMs,
+ long numericValue) {
+ this.collection = collection;
+ this.score = score;
+ this.datetimeResult = datetimeResult;
+ this.serializedKnowledgeResult = serializedKnowledgeResult;
+ this.contactName = contactName;
+ this.contactGivenName = contactGivenName;
+ this.contactNickname = contactNickname;
+ this.contactEmailAddress = contactEmailAddress;
+ this.contactPhoneNumber = contactPhoneNumber;
+ this.contactId = contactId;
+ this.appName = appName;
+ this.appPackageName = appPackageName;
+ this.entityData = entityData;
+ this.serializedEntityData = serializedEntityData;
+ this.remoteActionTemplates = remoteActionTemplates;
+ this.durationMs = durationMs;
+ this.numericValue = numericValue;
+ }
+
+ /** Returns the classified entity type. */
+ public String getCollection() {
+ return collection;
+ }
+
+ /** Confidence score between 0 and 1. */
+ public float getScore() {
+ return score;
+ }
+
+ public DatetimeResult getDatetimeResult() {
+ return datetimeResult;
+ }
+
+ public byte[] getSerializedKnowledgeResult() {
+ return serializedKnowledgeResult;
+ }
+
+ public String getContactName() {
+ return contactName;
+ }
+
+ public String getContactGivenName() {
+ return contactGivenName;
+ }
+
+ public String getContactNickname() {
+ return contactNickname;
+ }
+
+ public String getContactEmailAddress() {
+ return contactEmailAddress;
+ }
+
+ public String getContactPhoneNumber() {
+ return contactPhoneNumber;
+ }
+
+ public String getContactId() {
+ return contactId;
+ }
+
+ public String getAppName() {
+ return appName;
+ }
+
+ public String getAppPackageName() {
+ return appPackageName;
+ }
+
+ public NamedVariant[] getEntityData() {
+ return entityData;
+ }
+
+ public byte[] getSerializedEntityData() {
+ return serializedEntityData;
+ }
+
+ public RemoteActionTemplate[] getRemoteActionTemplates() {
+ return remoteActionTemplates;
+ }
+
+ public long getDurationMs() {
+ return durationMs;
+ }
+
+ public long getNumericValue() {
+ return numericValue;
+ }
+ }
+
+ /** Represents a result of Annotate call. */
+ public static final class AnnotatedSpan {
+ private final int startIndex;
+ private final int endIndex;
+ private final ClassificationResult[] classification;
+
+ AnnotatedSpan(int startIndex, int endIndex, ClassificationResult[] classification) {
+ this.startIndex = startIndex;
+ this.endIndex = endIndex;
+ this.classification = classification;
+ }
+
+ public int getStartIndex() {
+ return startIndex;
+ }
+
+ public int getEndIndex() {
+ return endIndex;
+ }
+
+ public ClassificationResult[] getClassification() {
+ return classification;
+ }
+ }
+
+ /** Represents options for the suggestSelection call. */
+ public static final class SelectionOptions {
+ private final String locales;
+ private final String detectedTextLanguageTags;
+ private final int annotationUsecase;
+
+ public SelectionOptions(
+ String locales, String detectedTextLanguageTags, int annotationUsecase) {
+ this.locales = locales;
+ this.detectedTextLanguageTags = detectedTextLanguageTags;
+ this.annotationUsecase = annotationUsecase;
+ }
+
+ public SelectionOptions(String locales, String detectedTextLanguageTags) {
+ this(locales, detectedTextLanguageTags, AnnotationUsecase.SMART.getValue());
+ }
+
+ public String getLocales() {
+ return locales;
+ }
+
+ /** Returns a comma separated list of BCP 47 language tags. */
+ public String getDetectedTextLanguageTags() {
+ return detectedTextLanguageTags;
+ }
+
+ public int getAnnotationUsecase() {
+ return annotationUsecase;
+ }
+ }
+
+ /** Represents options for the classifyText call. */
+ public static final class ClassificationOptions {
+ private final long referenceTimeMsUtc;
+ private final String referenceTimezone;
+ private final String locales;
+ private final String detectedTextLanguageTags;
+ private final int annotationUsecase;
+
+ public ClassificationOptions(
+ long referenceTimeMsUtc,
+ String referenceTimezone,
+ String locales,
+ String detectedTextLanguageTags,
+ int annotationUsecase) {
+ this.referenceTimeMsUtc = referenceTimeMsUtc;
+ this.referenceTimezone = referenceTimezone;
+ this.locales = locales;
+ this.detectedTextLanguageTags = detectedTextLanguageTags;
+ this.annotationUsecase = annotationUsecase;
+ }
+
+ public ClassificationOptions(
+ long referenceTimeMsUtc,
+ String referenceTimezone,
+ String locales,
+ String detectedTextLanguageTags) {
+ this(
+ referenceTimeMsUtc,
+ referenceTimezone,
+ locales,
+ detectedTextLanguageTags,
+ AnnotationUsecase.SMART.getValue());
+ }
+
+ public long getReferenceTimeMsUtc() {
+ return referenceTimeMsUtc;
+ }
+
+ public String getReferenceTimezone() {
+ return referenceTimezone;
+ }
+
+ public String getLocale() {
+ return locales;
+ }
+
+ /** Returns a comma separated list of BCP 47 language tags. */
+ public String getDetectedTextLanguageTags() {
+ return detectedTextLanguageTags;
+ }
+
+ public int getAnnotationUsecase() {
+ return annotationUsecase;
+ }
+ }
+
+ /** Represents options for the annotate call. */
+ public static final class AnnotationOptions {
+ private final long referenceTimeMsUtc;
+ private final String referenceTimezone;
+ private final String locales;
+ private final String detectedTextLanguageTags;
+ private final String[] entityTypes;
+ private final int annotationUsecase;
+ private final boolean isSerializedEntityDataEnabled;
+
+ public AnnotationOptions(
+ long referenceTimeMsUtc,
+ String referenceTimezone,
+ String locales,
+ String detectedTextLanguageTags,
+ Collection<String> entityTypes,
+ int annotationUsecase,
+ boolean isSerializedEntityDataEnabled) {
+ this.referenceTimeMsUtc = referenceTimeMsUtc;
+ this.referenceTimezone = referenceTimezone;
+ this.locales = locales;
+ this.detectedTextLanguageTags = detectedTextLanguageTags;
+ this.entityTypes = entityTypes == null ? new String[0] : entityTypes.toArray(new String[0]);
+ this.annotationUsecase = annotationUsecase;
+ this.isSerializedEntityDataEnabled = isSerializedEntityDataEnabled;
+ }
+
+ public AnnotationOptions(
+ long referenceTimeMsUtc,
+ String referenceTimezone,
+ String locales,
+ String detectedTextLanguageTags) {
+ this(
+ referenceTimeMsUtc,
+ referenceTimezone,
+ locales,
+ detectedTextLanguageTags,
+ null,
+ AnnotationUsecase.SMART.getValue(),
+ /* isSerializedEntityDataEnabled */ false);
+ }
+
+ public long getReferenceTimeMsUtc() {
+ return referenceTimeMsUtc;
+ }
+
+ public String getReferenceTimezone() {
+ return referenceTimezone;
+ }
+
+ public String getLocale() {
+ return locales;
+ }
+
+ /** Returns a comma separated list of BCP 47 language tags. */
+ public String getDetectedTextLanguageTags() {
+ return detectedTextLanguageTags;
+ }
+
+ public String[] getEntityTypes() {
+ return entityTypes;
+ }
+
+ public int getAnnotationUsecase() {
+ return annotationUsecase;
+ }
+
+ public boolean isSerializedEntityDataEnabled() {
+ return isSerializedEntityDataEnabled;
+ }
+ }
+
+ /**
+ * Retrieves the pointer to the native object. Note: Need to keep the AnnotatorModel alive as long
+ * as the pointer is used.
+ */
+ long getNativeAnnotator() {
+ return nativeGetNativeModelPtr(annotatorPtr);
+ }
+
+ private static native long nativeNewAnnotator(int fd);
+
+ private static native long nativeNewAnnotatorFromPath(String path);
+
+ private static native String nativeGetLocales(int fd);
+
+ private static native int nativeGetVersion(int fd);
+
+ private static native String nativeGetName(int fd);
+
+ private native long nativeGetNativeModelPtr(long context);
+
+ private native boolean nativeInitializeKnowledgeEngine(long context, byte[] serializedConfig);
+
+ private native boolean nativeInitializeContactEngine(long context, byte[] serializedConfig);
+
+ private native boolean nativeInitializeInstalledAppEngine(long context, byte[] serializedConfig);
+
+ private native int[] nativeSuggestSelection(
+ long context, String text, int selectionBegin, int selectionEnd, SelectionOptions options);
+
+ private native ClassificationResult[] nativeClassifyText(
+ long context,
+ String text,
+ int selectionBegin,
+ int selectionEnd,
+ ClassificationOptions options,
+ Object appContext,
+ String deviceLocales);
+
+ private native AnnotatedSpan[] nativeAnnotate(
+ long context, String text, AnnotationOptions options);
+
+ private native byte[] nativeLookUpKnowledgeEntity(long context, String id);
+
+ private native void nativeCloseAnnotator(long context);
+}
diff --git a/jni/com/google/android/textclassifier/LangIdModel.java b/jni/com/google/android/textclassifier/LangIdModel.java
new file mode 100644
index 0000000..d3e166f
--- /dev/null
+++ b/jni/com/google/android/textclassifier/LangIdModel.java
@@ -0,0 +1,119 @@
+/*
+ * 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 com.google.android.textclassifier;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Java wrapper for LangId native library interface. This class is used to detect languages in text.
+ *
+ * @hide
+ */
+public final class LangIdModel implements AutoCloseable {
+ private final AtomicBoolean isClosed = new AtomicBoolean(false);
+
+ static {
+ System.loadLibrary("textclassifier");
+ }
+
+ private long modelPtr;
+
+ /** Creates a new instance of LangId predictor, using the provided model image. */
+ public LangIdModel(int fd) {
+ modelPtr = nativeNew(fd);
+ if (modelPtr == 0L) {
+ throw new IllegalArgumentException("Couldn't initialize LangId from given file descriptor.");
+ }
+ }
+
+ /** Creates a new instance of LangId predictor, using the provided model image. */
+ public LangIdModel(String modelPath) {
+ modelPtr = nativeNewFromPath(modelPath);
+ if (modelPtr == 0L) {
+ throw new IllegalArgumentException("Couldn't initialize LangId from given file.");
+ }
+ }
+
+ /** Detects the languages for given text. */
+ public LanguageResult[] detectLanguages(String text) {
+ return nativeDetectLanguages(modelPtr, text);
+ }
+
+ /** Frees up the allocated memory. */
+ @Override
+ public void close() {
+ if (isClosed.compareAndSet(false, true)) {
+ nativeClose(modelPtr);
+ modelPtr = 0L;
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /** Result for detectLanguages method. */
+ public static final class LanguageResult {
+ final String mLanguage;
+ final float mScore;
+
+ LanguageResult(String language, float score) {
+ mLanguage = language;
+ mScore = score;
+ }
+
+ public final String getLanguage() {
+ return mLanguage;
+ }
+
+ public final float getScore() {
+ return mScore;
+ }
+ }
+
+ /** Returns the version of the LangId model used. */
+ public int getVersion() {
+ return nativeGetVersion(modelPtr);
+ }
+
+ public float getLangIdThreshold() {
+ return nativeGetLangIdThreshold(modelPtr);
+ }
+
+ public static int getVersion(int fd) {
+ return nativeGetVersionFromFd(fd);
+ }
+
+ private static native long nativeNew(int fd);
+
+ private static native long nativeNewFromPath(String path);
+
+ private native LanguageResult[] nativeDetectLanguages(long nativePtr, String text);
+
+ private native void nativeClose(long nativePtr);
+
+ private native int nativeGetVersion(long nativePtr);
+
+ private static native int nativeGetVersionFromFd(int fd);
+
+ private native float nativeGetLangIdThreshold(long nativePtr);
+}
diff --git a/jni/com/google/android/textclassifier/NamedVariant.java b/jni/com/google/android/textclassifier/NamedVariant.java
new file mode 100644
index 0000000..d04bb11
--- /dev/null
+++ b/jni/com/google/android/textclassifier/NamedVariant.java
@@ -0,0 +1,115 @@
+/*
+ * 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 com.google.android.textclassifier;
+
+/**
+ * Represents a union of different basic types.
+ *
+ * @hide
+ */
+public final class NamedVariant {
+ public static final int TYPE_EMPTY = 0;
+ public static final int TYPE_INT = 1;
+ public static final int TYPE_LONG = 2;
+ public static final int TYPE_FLOAT = 3;
+ public static final int TYPE_DOUBLE = 4;
+ public static final int TYPE_BOOL = 5;
+ public static final int TYPE_STRING = 6;
+
+ public NamedVariant(String name, int value) {
+ this.name = name;
+ this.intValue = value;
+ this.type = TYPE_INT;
+ }
+
+ public NamedVariant(String name, long value) {
+ this.name = name;
+ this.longValue = value;
+ this.type = TYPE_LONG;
+ }
+
+ public NamedVariant(String name, float value) {
+ this.name = name;
+ this.floatValue = value;
+ this.type = TYPE_FLOAT;
+ }
+
+ public NamedVariant(String name, double value) {
+ this.name = name;
+ this.doubleValue = value;
+ this.type = TYPE_DOUBLE;
+ }
+
+ public NamedVariant(String name, boolean value) {
+ this.name = name;
+ this.boolValue = value;
+ this.type = TYPE_BOOL;
+ }
+
+ public NamedVariant(String name, String value) {
+ this.name = name;
+ this.stringValue = value;
+ this.type = TYPE_STRING;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public int getInt() {
+ assert (type == TYPE_INT);
+ return intValue;
+ }
+
+ public long getLong() {
+ assert (type == TYPE_LONG);
+ return longValue;
+ }
+
+ public float getFloat() {
+ assert (type == TYPE_FLOAT);
+ return floatValue;
+ }
+
+ public double getDouble() {
+ assert (type == TYPE_DOUBLE);
+ return doubleValue;
+ }
+
+ public boolean getBool() {
+ assert (type == TYPE_BOOL);
+ return boolValue;
+ }
+
+ public String getString() {
+ assert (type == TYPE_STRING);
+ return stringValue;
+ }
+
+ private final String name;
+ private final int type;
+ private int intValue;
+ private long longValue;
+ private float floatValue;
+ private double doubleValue;
+ private boolean boolValue;
+ private String stringValue;
+}
diff --git a/jni/com/google/android/textclassifier/RemoteActionTemplate.java b/jni/com/google/android/textclassifier/RemoteActionTemplate.java
new file mode 100644
index 0000000..308d809
--- /dev/null
+++ b/jni/com/google/android/textclassifier/RemoteActionTemplate.java
@@ -0,0 +1,91 @@
+/*
+ * 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 com.google.android.textclassifier;
+
+/**
+ * Represents a template for an Android RemoteAction.
+ *
+ * @hide
+ */
+public final class RemoteActionTemplate {
+ /** Title shown for the action (see: RemoteAction.getTitle). */
+ public final String titleWithoutEntity;
+
+ /** Title with entity for the action. */
+ public final String titleWithEntity;
+
+ /** Description shown for the action (see: RemoteAction.getContentDescription). */
+ public final String description;
+
+ /**
+ * Description shown for the action (see: RemoteAction.getContentDescription) when app name is
+ * available. Caller is expected to replace the placeholder by the name of the app that is going
+ * to handle the action.
+ */
+ public final String descriptionWithAppName;
+
+ /** The action to set on the Intent (see: Intent.setAction). */
+ public final String action;
+
+ /** The data to set on the Intent (see: Intent.setData). */
+ public final String data;
+
+ /** The type to set on the Intent (see: Intent.setType). */
+ public final String type;
+
+ /** Flags for launching the Intent (see: Intent.setFlags). */
+ public final Integer flags;
+
+ /** Categories to set on the Intent (see: Intent.addCategory). */
+ public final String[] category;
+
+ /** Explicit application package to set on the Intent (see: Intent.setPackage). */
+ public final String packageName;
+
+ /** The list of all the extras to add to the Intent. */
+ public final NamedVariant[] extras;
+
+ /** Private request code to use for the Intent. */
+ public final Integer requestCode;
+
+ public RemoteActionTemplate(
+ String titleWithoutEntity,
+ String titleWithEntity,
+ String description,
+ String descriptionWithAppName,
+ String action,
+ String data,
+ String type,
+ Integer flags,
+ String[] category,
+ String packageName,
+ NamedVariant[] extras,
+ Integer requestCode) {
+ this.titleWithoutEntity = titleWithoutEntity;
+ this.titleWithEntity = titleWithEntity;
+ this.description = description;
+ this.descriptionWithAppName = descriptionWithAppName;
+ this.action = action;
+ this.data = data;
+ this.type = type;
+ this.flags = flags;
+ this.category = category;
+ this.packageName = packageName;
+ this.extras = extras;
+ this.requestCode = requestCode;
+ }
+}