blob: 9e15a2e1f011159a16c25685aa01b852dea7e05c [file] [log] [blame] [edit]
/*
* 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.
*/
// JNI wrapper for actions.
#include "actions/actions_jni.h"
#include <jni.h>
#include <map>
#include <type_traits>
#include <vector>
#include "actions/actions-suggestions.h"
#include "annotator/annotator.h"
#include "annotator/annotator_jni_common.h"
#include "utils/base/integral_types.h"
#include "utils/base/status_macros.h"
#include "utils/base/statusor.h"
#include "utils/intents/intent-generator.h"
#include "utils/intents/jni.h"
#include "utils/intents/remote-action-template.h"
#include "utils/java/jni-base.h"
#include "utils/java/jni-cache.h"
#include "utils/java/jni-helper.h"
#include "utils/memory/mmap.h"
using libtextclassifier3::ActionsSuggestions;
using libtextclassifier3::ActionsSuggestionsResponse;
using libtextclassifier3::ActionSuggestionOptions;
using libtextclassifier3::Annotator;
using libtextclassifier3::Conversation;
using libtextclassifier3::IntentGenerator;
using libtextclassifier3::JStringToUtf8String;
using libtextclassifier3::ScopedLocalRef;
using libtextclassifier3::StatusOr;
// When using the Java's ICU, UniLib needs to be instantiated with a JavaVM
// pointer from JNI. When using a standard ICU the pointer is not needed and the
// objects are instantiated implicitly.
#ifdef TC3_UNILIB_JAVAICU
using libtextclassifier3::UniLib;
#endif
namespace libtextclassifier3 {
namespace {
// Cached state for model inference.
// Keeps a jni cache, intent generator and model instance so that they don't
// have to be recreated for each call.
class ActionsSuggestionsJniContext {
public:
static ActionsSuggestionsJniContext* Create(
const std::shared_ptr<libtextclassifier3::JniCache>& jni_cache,
std::unique_ptr<ActionsSuggestions> model) {
if (jni_cache == nullptr || model == nullptr) {
return nullptr;
}
std::unique_ptr<IntentGenerator> intent_generator =
IntentGenerator::Create(model->model()->android_intent_options(),
model->model()->resources(), jni_cache);
if (intent_generator == nullptr) {
return nullptr;
}
TC3_ASSIGN_OR_RETURN_NULL(
std::unique_ptr<RemoteActionTemplatesHandler> template_handler,
libtextclassifier3::RemoteActionTemplatesHandler::Create(jni_cache));
return new ActionsSuggestionsJniContext(jni_cache, std::move(model),
std::move(intent_generator),
std::move(template_handler));
}
std::shared_ptr<libtextclassifier3::JniCache> jni_cache() const {
return jni_cache_;
}
ActionsSuggestions* model() const { return model_.get(); }
IntentGenerator* intent_generator() const { return intent_generator_.get(); }
RemoteActionTemplatesHandler* template_handler() const {
return template_handler_.get();
}
private:
ActionsSuggestionsJniContext(
const std::shared_ptr<libtextclassifier3::JniCache>& jni_cache,
std::unique_ptr<ActionsSuggestions> model,
std::unique_ptr<IntentGenerator> intent_generator,
std::unique_ptr<RemoteActionTemplatesHandler> template_handler)
: jni_cache_(jni_cache),
model_(std::move(model)),
intent_generator_(std::move(intent_generator)),
template_handler_(std::move(template_handler)) {}
std::shared_ptr<libtextclassifier3::JniCache> jni_cache_;
std::unique_ptr<ActionsSuggestions> model_;
std::unique_ptr<IntentGenerator> intent_generator_;
std::unique_ptr<RemoteActionTemplatesHandler> template_handler_;
};
ActionSuggestionOptions FromJavaActionSuggestionOptions(JNIEnv* env,
jobject joptions) {
ActionSuggestionOptions options = ActionSuggestionOptions::Default();
return options;
}
StatusOr<ScopedLocalRef<jobject>> ActionSuggestionsToJObject(
JNIEnv* env, const ActionsSuggestionsJniContext* context,
jobject app_context,
const reflection::Schema* annotations_entity_data_schema,
const ActionsSuggestionsResponse& action_response,
const Conversation& conversation, const jstring device_locales,
const bool generate_intents) {
// Find the class ActionSuggestion.
auto status_or_action_class = JniHelper::FindClass(
env, TC3_PACKAGE_PATH TC3_ACTIONS_CLASS_NAME_STR "$ActionSuggestion");
if (!status_or_action_class.ok()) {
TC3_LOG(ERROR) << "Couldn't find ActionSuggestion class.";
return status_or_action_class.status();
}
ScopedLocalRef<jclass> action_class =
std::move(status_or_action_class.ValueOrDie());
// Find the class ActionSuggestions
auto status_or_result_class = JniHelper::FindClass(
env, TC3_PACKAGE_PATH TC3_ACTIONS_CLASS_NAME_STR "$ActionSuggestions");
if (!status_or_result_class.ok()) {
TC3_LOG(ERROR) << "Couldn't find ActionSuggestions class.";
return status_or_result_class.status();
}
ScopedLocalRef<jclass> result_class =
std::move(status_or_result_class.ValueOrDie());
// Find the class Slot.
auto status_or_slot_class = JniHelper::FindClass(
env, TC3_PACKAGE_PATH TC3_ACTIONS_CLASS_NAME_STR "$Slot");
if (!status_or_slot_class.ok()) {
TC3_LOG(ERROR) << "Couldn't find Slot class.";
return status_or_slot_class.status();
}
ScopedLocalRef<jclass> slot_class =
std::move(status_or_slot_class.ValueOrDie());
TC3_ASSIGN_OR_RETURN(
const jmethodID action_class_constructor,
JniHelper::GetMethodID(
env, action_class.get(), "<init>",
"(Ljava/lang/String;Ljava/lang/String;F[L" TC3_PACKAGE_PATH
TC3_NAMED_VARIANT_CLASS_NAME_STR
";[B[L" TC3_PACKAGE_PATH TC3_REMOTE_ACTION_TEMPLATE_CLASS_NAME_STR
";[L" TC3_PACKAGE_PATH TC3_ACTIONS_CLASS_NAME_STR "$Slot;)V"));
TC3_ASSIGN_OR_RETURN(const jmethodID slot_class_constructor,
JniHelper::GetMethodID(env, slot_class.get(), "<init>",
"(Ljava/lang/String;IIIF)V"));
TC3_ASSIGN_OR_RETURN(
ScopedLocalRef<jobjectArray> actions,
JniHelper::NewObjectArray(env, action_response.actions.size(),
action_class.get(), nullptr));
for (int i = 0; i < action_response.actions.size(); i++) {
ScopedLocalRef<jobjectArray> extras;
const reflection::Schema* actions_entity_data_schema =
context->model()->entity_data_schema();
if (actions_entity_data_schema != nullptr &&
!action_response.actions[i].serialized_entity_data.empty()) {
TC3_ASSIGN_OR_RETURN(
extras, context->template_handler()->EntityDataAsNamedVariantArray(
actions_entity_data_schema,
action_response.actions[i].serialized_entity_data));
}
ScopedLocalRef<jbyteArray> serialized_entity_data;
if (!action_response.actions[i].serialized_entity_data.empty()) {
TC3_ASSIGN_OR_RETURN(
serialized_entity_data,
JniHelper::NewByteArray(
env, action_response.actions[i].serialized_entity_data.size()));
TC3_RETURN_IF_ERROR(JniHelper::SetByteArrayRegion(
env, serialized_entity_data.get(), 0,
action_response.actions[i].serialized_entity_data.size(),
reinterpret_cast<const jbyte*>(
action_response.actions[i].serialized_entity_data.data())));
}
ScopedLocalRef<jobjectArray> remote_action_templates_result;
if (generate_intents) {
std::vector<RemoteActionTemplate> remote_action_templates;
if (context->intent_generator()->GenerateIntents(
device_locales, action_response.actions[i], conversation,
app_context,
/*annotations_entity_data_schema=*/annotations_entity_data_schema,
/*actions_entity_data_schema=*/actions_entity_data_schema,
&remote_action_templates)) {
TC3_ASSIGN_OR_RETURN(
remote_action_templates_result,
context->template_handler()->RemoteActionTemplatesToJObjectArray(
remote_action_templates));
}
}
TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> reply,
context->jni_cache()->ConvertToJavaString(
action_response.actions[i].response_text));
TC3_ASSIGN_OR_RETURN(
ScopedLocalRef<jstring> action_type,
JniHelper::NewStringUTF(env, action_response.actions[i].type.c_str()));
ScopedLocalRef<jobjectArray> slots;
if (!action_response.actions[i].slots.empty()) {
TC3_ASSIGN_OR_RETURN(slots,
JniHelper::NewObjectArray(
env, action_response.actions[i].slots.size(),
slot_class.get(), nullptr));
for (int j = 0; j < action_response.actions[i].slots.size(); j++) {
const Slot& slot_c = action_response.actions[i].slots[j];
TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> slot_type,
JniHelper::NewStringUTF(env, slot_c.type.c_str()));
TC3_ASSIGN_OR_RETURN(
ScopedLocalRef<jobject> slot,
JniHelper::NewObject(
env, slot_class.get(), slot_class_constructor, slot_type.get(),
slot_c.span.message_index, slot_c.span.span.first,
slot_c.span.span.second, slot_c.confidence_score));
TC3_RETURN_IF_ERROR(
JniHelper::SetObjectArrayElement(env, slots.get(), j, slot.get()));
}
}
TC3_ASSIGN_OR_RETURN(
ScopedLocalRef<jobject> action,
JniHelper::NewObject(
env, action_class.get(), action_class_constructor, reply.get(),
action_type.get(),
static_cast<jfloat>(action_response.actions[i].score), extras.get(),
serialized_entity_data.get(), remote_action_templates_result.get(),
slots.get()));
TC3_RETURN_IF_ERROR(
JniHelper::SetObjectArrayElement(env, actions.get(), i, action.get()));
}
// Create the ActionSuggestions object.
TC3_ASSIGN_OR_RETURN(
const jmethodID result_class_constructor,
JniHelper::GetMethodID(env, result_class.get(), "<init>",
"([L" TC3_PACKAGE_PATH TC3_ACTIONS_CLASS_NAME_STR
"$ActionSuggestion;Z)V"));
TC3_ASSIGN_OR_RETURN(
ScopedLocalRef<jobject> result,
JniHelper::NewObject(env, result_class.get(), result_class_constructor,
actions.get(), action_response.is_sensitive));
return result;
}
StatusOr<ConversationMessage> FromJavaConversationMessage(JNIEnv* env,
jobject jmessage) {
if (!jmessage) {
return {};
}
TC3_ASSIGN_OR_RETURN(
ScopedLocalRef<jclass> message_class,
JniHelper::FindClass(env, TC3_PACKAGE_PATH TC3_ACTIONS_CLASS_NAME_STR
"$ConversationMessage"));
// .getText()
TC3_ASSIGN_OR_RETURN(
jmethodID get_text_method,
JniHelper::GetMethodID(env, message_class.get(), "getText",
"()Ljava/lang/String;"));
TC3_ASSIGN_OR_RETURN(
ScopedLocalRef<jstring> text,
JniHelper::CallObjectMethod<jstring>(env, jmessage, get_text_method));
// .getUserId()
TC3_ASSIGN_OR_RETURN(
jmethodID get_user_id_method,
JniHelper::GetMethodID(env, message_class.get(), "getUserId", "()I"));
TC3_ASSIGN_OR_RETURN(int32 user_id, JniHelper::CallIntMethod(
env, jmessage, get_user_id_method));
// .getReferenceTimeMsUtc()
TC3_ASSIGN_OR_RETURN(jmethodID get_reference_time_method,
JniHelper::GetMethodID(env, message_class.get(),
"getReferenceTimeMsUtc", "()J"));
TC3_ASSIGN_OR_RETURN(
int64 reference_time,
JniHelper::CallLongMethod(env, jmessage, get_reference_time_method));
// .getReferenceTimezone()
TC3_ASSIGN_OR_RETURN(
jmethodID get_reference_timezone_method,
JniHelper::GetMethodID(env, message_class.get(), "getReferenceTimezone",
"()Ljava/lang/String;"));
TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> reference_timezone,
JniHelper::CallObjectMethod<jstring>(
env, jmessage, get_reference_timezone_method));
// .getDetectedTextLanguageTags()
TC3_ASSIGN_OR_RETURN(jmethodID get_detected_text_language_tags_method,
JniHelper::GetMethodID(env, message_class.get(),
"getDetectedTextLanguageTags",
"()Ljava/lang/String;"));
TC3_ASSIGN_OR_RETURN(
ScopedLocalRef<jstring> detected_text_language_tags,
JniHelper::CallObjectMethod<jstring>(
env, jmessage, get_detected_text_language_tags_method));
ConversationMessage message;
TC3_ASSIGN_OR_RETURN(message.text, JStringToUtf8String(env, text.get()));
message.user_id = user_id;
message.reference_time_ms_utc = reference_time;
TC3_ASSIGN_OR_RETURN(message.reference_timezone,
JStringToUtf8String(env, reference_timezone.get()));
TC3_ASSIGN_OR_RETURN(
message.detected_text_language_tags,
JStringToUtf8String(env, detected_text_language_tags.get()));
return message;
}
StatusOr<Conversation> FromJavaConversation(JNIEnv* env,
jobject jconversation) {
if (!jconversation) {
return {Status::UNKNOWN};
}
TC3_ASSIGN_OR_RETURN(
ScopedLocalRef<jclass> conversation_class,
JniHelper::FindClass(
env, TC3_PACKAGE_PATH TC3_ACTIONS_CLASS_NAME_STR "$Conversation"));
TC3_ASSIGN_OR_RETURN(
jmethodID get_conversation_messages_method,
JniHelper::GetMethodID(env, conversation_class.get(),
"getConversationMessages",
"()[L" TC3_PACKAGE_PATH TC3_ACTIONS_CLASS_NAME_STR
"$ConversationMessage;"));
TC3_ASSIGN_OR_RETURN(
ScopedLocalRef<jobjectArray> jmessages,
JniHelper::CallObjectMethod<jobjectArray>(
env, jconversation, get_conversation_messages_method));
std::vector<ConversationMessage> messages;
TC3_ASSIGN_OR_RETURN(const int size,
JniHelper::GetArrayLength(env, jmessages.get()));
for (int i = 0; i < size; i++) {
TC3_ASSIGN_OR_RETURN(
ScopedLocalRef<jobject> jmessage,
JniHelper::GetObjectArrayElement<jobject>(env, jmessages.get(), i));
TC3_ASSIGN_OR_RETURN(ConversationMessage message,
FromJavaConversationMessage(env, jmessage.get()));
messages.push_back(message);
}
Conversation conversation;
conversation.messages = messages;
return conversation;
}
StatusOr<ScopedLocalRef<jstring>> GetLocalesFromMmap(
JNIEnv* env, libtextclassifier3::ScopedMmap* mmap) {
if (!mmap->handle().ok()) {
return JniHelper::NewStringUTF(env, "");
}
const ActionsModel* model = libtextclassifier3::ViewActionsModel(
mmap->handle().start(), mmap->handle().num_bytes());
if (!model || !model->locales()) {
return JniHelper::NewStringUTF(env, "");
}
return JniHelper::NewStringUTF(env, model->locales()->c_str());
}
jint GetVersionFromMmap(JNIEnv* env, libtextclassifier3::ScopedMmap* mmap) {
if (!mmap->handle().ok()) {
return 0;
}
const ActionsModel* model = libtextclassifier3::ViewActionsModel(
mmap->handle().start(), mmap->handle().num_bytes());
if (!model) {
return 0;
}
return model->version();
}
StatusOr<ScopedLocalRef<jstring>> GetNameFromMmap(
JNIEnv* env, libtextclassifier3::ScopedMmap* mmap) {
if (!mmap->handle().ok()) {
return JniHelper::NewStringUTF(env, "");
}
const ActionsModel* model = libtextclassifier3::ViewActionsModel(
mmap->handle().start(), mmap->handle().num_bytes());
if (!model || !model->name()) {
return JniHelper::NewStringUTF(env, "");
}
return JniHelper::NewStringUTF(env, model->name()->c_str());
}
} // namespace
} // namespace libtextclassifier3
using libtextclassifier3::ActionsSuggestionsJniContext;
using libtextclassifier3::ActionSuggestionsToJObject;
using libtextclassifier3::FromJavaActionSuggestionOptions;
using libtextclassifier3::FromJavaConversation;
using libtextclassifier3::JByteArrayToString;
TC3_JNI_METHOD(jlong, TC3_ACTIONS_CLASS_NAME, nativeNewActionsModel)
(JNIEnv* env, jobject clazz, jint fd, jbyteArray jserialized_preconditions) {
std::shared_ptr<libtextclassifier3::JniCache> jni_cache =
libtextclassifier3::JniCache::Create(env);
std::string serialized_preconditions;
if (jserialized_preconditions != nullptr) {
TC3_ASSIGN_OR_RETURN_0(
serialized_preconditions,
JByteArrayToString(env, jserialized_preconditions),
TC3_LOG(ERROR) << "Could not convert serialized preconditions.");
}
#ifdef TC3_UNILIB_JAVAICU
return reinterpret_cast<jlong>(ActionsSuggestionsJniContext::Create(
jni_cache, ActionsSuggestions::FromFileDescriptor(
fd, std::unique_ptr<UniLib>(new UniLib(jni_cache)),
serialized_preconditions)));
#else
return reinterpret_cast<jlong>(ActionsSuggestionsJniContext::Create(
jni_cache, ActionsSuggestions::FromFileDescriptor(
fd, /*unilib=*/nullptr, serialized_preconditions)));
#endif // TC3_UNILIB_JAVAICU
}
TC3_JNI_METHOD(jlong, TC3_ACTIONS_CLASS_NAME, nativeNewActionsModelFromPath)
(JNIEnv* env, jobject clazz, jstring path,
jbyteArray jserialized_preconditions) {
std::shared_ptr<libtextclassifier3::JniCache> jni_cache =
libtextclassifier3::JniCache::Create(env);
TC3_ASSIGN_OR_RETURN_0(const std::string path_str,
JStringToUtf8String(env, path));
std::string serialized_preconditions;
if (jserialized_preconditions != nullptr) {
TC3_ASSIGN_OR_RETURN_0(
serialized_preconditions,
JByteArrayToString(env, jserialized_preconditions),
TC3_LOG(ERROR) << "Could not convert serialized preconditions.");
}
#ifdef TC3_UNILIB_JAVAICU
return reinterpret_cast<jlong>(ActionsSuggestionsJniContext::Create(
jni_cache, ActionsSuggestions::FromPath(
path_str, std::unique_ptr<UniLib>(new UniLib(jni_cache)),
serialized_preconditions)));
#else
return reinterpret_cast<jlong>(ActionsSuggestionsJniContext::Create(
jni_cache, ActionsSuggestions::FromPath(path_str, /*unilib=*/nullptr,
serialized_preconditions)));
#endif // TC3_UNILIB_JAVAICU
}
TC3_JNI_METHOD(jlong, TC3_ACTIONS_CLASS_NAME, nativeNewActionsModelWithOffset)
(JNIEnv* env, jobject clazz, jint fd, jlong offset, jlong size,
jbyteArray jserialized_preconditions) {
std::shared_ptr<libtextclassifier3::JniCache> jni_cache =
libtextclassifier3::JniCache::Create(env);
std::string serialized_preconditions;
if (jserialized_preconditions != nullptr) {
TC3_ASSIGN_OR_RETURN_0(
serialized_preconditions,
JByteArrayToString(env, jserialized_preconditions),
TC3_LOG(ERROR) << "Could not convert serialized preconditions.");
}
#ifdef TC3_UNILIB_JAVAICU
return reinterpret_cast<jlong>(ActionsSuggestionsJniContext::Create(
jni_cache,
ActionsSuggestions::FromFileDescriptor(
fd, offset, size, std::unique_ptr<UniLib>(new UniLib(jni_cache)),
serialized_preconditions)));
#else
return reinterpret_cast<jlong>(ActionsSuggestionsJniContext::Create(
jni_cache,
ActionsSuggestions::FromFileDescriptor(
fd, offset, size, /*unilib=*/nullptr, serialized_preconditions)));
#endif // TC3_UNILIB_JAVAICU
}
TC3_JNI_METHOD(jobject, TC3_ACTIONS_CLASS_NAME, nativeSuggestActions)
(JNIEnv* env, jobject thiz, jlong ptr, jobject jconversation, jobject joptions,
jlong annotatorPtr, jobject app_context, jstring device_locales,
jboolean generate_intents) {
if (!ptr) {
return nullptr;
}
TC3_ASSIGN_OR_RETURN_NULL(const Conversation conversation,
FromJavaConversation(env, jconversation));
const ActionSuggestionOptions options =
FromJavaActionSuggestionOptions(env, joptions);
const ActionsSuggestionsJniContext* context =
reinterpret_cast<ActionsSuggestionsJniContext*>(ptr);
const Annotator* annotator = reinterpret_cast<Annotator*>(annotatorPtr);
const ActionsSuggestionsResponse response =
context->model()->SuggestActions(conversation, annotator, options);
const reflection::Schema* anntotations_entity_data_schema =
annotator ? annotator->entity_data_schema() : nullptr;
TC3_ASSIGN_OR_RETURN_NULL(
ScopedLocalRef<jobject> result,
ActionSuggestionsToJObject(
env, context, app_context, anntotations_entity_data_schema, response,
conversation, device_locales, generate_intents));
return result.release();
}
TC3_JNI_METHOD(void, TC3_ACTIONS_CLASS_NAME, nativeCloseActionsModel)
(JNIEnv* env, jobject thiz, jlong model_ptr) {
const ActionsSuggestionsJniContext* context =
reinterpret_cast<ActionsSuggestionsJniContext*>(model_ptr);
delete context;
}
TC3_JNI_METHOD(jstring, TC3_ACTIONS_CLASS_NAME, nativeGetLocales)
(JNIEnv* env, jobject clazz, jint fd) {
const std::unique_ptr<libtextclassifier3::ScopedMmap> mmap(
new libtextclassifier3::ScopedMmap(fd));
TC3_ASSIGN_OR_RETURN_NULL(
ScopedLocalRef<jstring> result,
libtextclassifier3::GetLocalesFromMmap(env, mmap.get()));
return result.release();
}
TC3_JNI_METHOD(jstring, TC3_ACTIONS_CLASS_NAME, nativeGetLocalesWithOffset)
(JNIEnv* env, jobject clazz, jint fd, jlong offset, jlong size) {
const std::unique_ptr<libtextclassifier3::ScopedMmap> mmap(
new libtextclassifier3::ScopedMmap(fd, offset, size));
TC3_ASSIGN_OR_RETURN_NULL(
ScopedLocalRef<jstring> result,
libtextclassifier3::GetLocalesFromMmap(env, mmap.get()));
return result.release();
}
TC3_JNI_METHOD(jstring, TC3_ACTIONS_CLASS_NAME, nativeGetName)
(JNIEnv* env, jobject clazz, jint fd) {
const std::unique_ptr<libtextclassifier3::ScopedMmap> mmap(
new libtextclassifier3::ScopedMmap(fd));
TC3_ASSIGN_OR_RETURN_NULL(
ScopedLocalRef<jstring> result,
libtextclassifier3::GetNameFromMmap(env, mmap.get()));
return result.release();
}
TC3_JNI_METHOD(jstring, TC3_ACTIONS_CLASS_NAME, nativeGetNameWithOffset)
(JNIEnv* env, jobject clazz, jint fd, jlong offset, jlong size) {
const std::unique_ptr<libtextclassifier3::ScopedMmap> mmap(
new libtextclassifier3::ScopedMmap(fd, offset, size));
TC3_ASSIGN_OR_RETURN_NULL(
ScopedLocalRef<jstring> result,
libtextclassifier3::GetNameFromMmap(env, mmap.get()));
return result.release();
}
TC3_JNI_METHOD(jint, TC3_ACTIONS_CLASS_NAME, nativeGetVersion)
(JNIEnv* env, jobject clazz, jint fd) {
const std::unique_ptr<libtextclassifier3::ScopedMmap> mmap(
new libtextclassifier3::ScopedMmap(fd));
return libtextclassifier3::GetVersionFromMmap(env, mmap.get());
}
TC3_JNI_METHOD(jint, TC3_ACTIONS_CLASS_NAME, nativeGetVersionWithOffset)
(JNIEnv* env, jobject clazz, jint fd, jlong offset, jlong size) {
const std::unique_ptr<libtextclassifier3::ScopedMmap> mmap(
new libtextclassifier3::ScopedMmap(fd, offset, size));
return libtextclassifier3::GetVersionFromMmap(env, mmap.get());
}
TC3_JNI_METHOD(jlong, TC3_ACTIONS_CLASS_NAME, nativeGetNativeModelPtr)
(JNIEnv* env, jobject thiz, jlong ptr) {
if (!ptr) {
return 0L;
}
return reinterpret_cast<jlong>(
reinterpret_cast<ActionsSuggestionsJniContext*>(ptr)->model());
}
TC3_JNI_METHOD(jboolean, TC3_ACTIONS_CLASS_NAME,
nativeInitializeConversationIntentDetection)
(JNIEnv* env, jobject thiz, jlong ptr, jbyteArray jserialized_config) {
if (!ptr) {
return false;
}
ActionsSuggestions* model =
reinterpret_cast<ActionsSuggestionsJniContext*>(ptr)->model();
std::string serialized_config;
TC3_ASSIGN_OR_RETURN_0(
serialized_config, JByteArrayToString(env, jserialized_config),
TC3_LOG(ERROR) << "Could not convert serialized conversation intent "
"detection config.");
return model->InitializeConversationIntentDetection(serialized_config);
}