You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
614 lines
24 KiB
614 lines
24 KiB
/*
|
|
* 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);
|
|
}
|