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.
358 lines
15 KiB
358 lines
15 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.
|
|
*/
|
|
|
|
#include "utils/intents/jni.h"
|
|
|
|
#include <memory>
|
|
|
|
#include "utils/base/status_macros.h"
|
|
#include "utils/base/statusor.h"
|
|
#include "utils/java/jni-base.h"
|
|
#include "utils/java/jni-helper.h"
|
|
|
|
namespace libtextclassifier3 {
|
|
|
|
// The macros below are intended to reduce the boilerplate and avoid
|
|
// easily introduced copy/paste errors.
|
|
#define TC3_CHECK_JNI_PTR(PTR) TC3_CHECK((PTR) != nullptr)
|
|
#define TC3_GET_CLASS(FIELD, NAME) \
|
|
{ \
|
|
TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jclass> clazz, \
|
|
JniHelper::FindClass(env, NAME)); \
|
|
handler->FIELD = MakeGlobalRef(clazz.release(), env, jni_cache->jvm); \
|
|
TC3_CHECK_JNI_PTR(handler->FIELD) << "Error finding class: " << NAME; \
|
|
}
|
|
#define TC3_GET_METHOD(CLASS, FIELD, NAME, SIGNATURE) \
|
|
TC3_ASSIGN_OR_RETURN( \
|
|
handler->FIELD, \
|
|
JniHelper::GetMethodID(env, handler->CLASS.get(), NAME, SIGNATURE));
|
|
|
|
StatusOr<std::unique_ptr<RemoteActionTemplatesHandler>>
|
|
RemoteActionTemplatesHandler::Create(
|
|
const std::shared_ptr<JniCache>& jni_cache) {
|
|
JNIEnv* env = jni_cache->GetEnv();
|
|
if (env == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<RemoteActionTemplatesHandler> handler(
|
|
new RemoteActionTemplatesHandler(jni_cache));
|
|
|
|
TC3_GET_CLASS(integer_class_, "java/lang/Integer");
|
|
TC3_GET_METHOD(integer_class_, integer_init_, "<init>", "(I)V");
|
|
|
|
TC3_GET_CLASS(remote_action_template_class_,
|
|
TC3_PACKAGE_PATH TC3_REMOTE_ACTION_TEMPLATE_CLASS_NAME_STR);
|
|
TC3_GET_METHOD(
|
|
remote_action_template_class_, remote_action_template_init_, "<init>",
|
|
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
|
|
"String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
|
|
"Integer;[Ljava/lang/String;Ljava/lang/String;[L" TC3_PACKAGE_PATH
|
|
TC3_NAMED_VARIANT_CLASS_NAME_STR ";Ljava/lang/Integer;)V");
|
|
|
|
TC3_GET_CLASS(named_variant_class_,
|
|
TC3_PACKAGE_PATH TC3_NAMED_VARIANT_CLASS_NAME_STR);
|
|
|
|
TC3_GET_METHOD(named_variant_class_, named_variant_from_int_, "<init>",
|
|
"(Ljava/lang/String;I)V");
|
|
TC3_GET_METHOD(named_variant_class_, named_variant_from_long_, "<init>",
|
|
"(Ljava/lang/String;J)V");
|
|
TC3_GET_METHOD(named_variant_class_, named_variant_from_float_, "<init>",
|
|
"(Ljava/lang/String;F)V");
|
|
TC3_GET_METHOD(named_variant_class_, named_variant_from_double_, "<init>",
|
|
"(Ljava/lang/String;D)V");
|
|
TC3_GET_METHOD(named_variant_class_, named_variant_from_bool_, "<init>",
|
|
"(Ljava/lang/String;Z)V");
|
|
TC3_GET_METHOD(named_variant_class_, named_variant_from_string_, "<init>",
|
|
"(Ljava/lang/String;Ljava/lang/String;)V");
|
|
TC3_GET_METHOD(named_variant_class_, named_variant_from_string_array_,
|
|
"<init>", "(Ljava/lang/String;[Ljava/lang/String;)V");
|
|
TC3_GET_METHOD(named_variant_class_, named_variant_from_float_array_,
|
|
"<init>", "(Ljava/lang/String;[F)V");
|
|
TC3_GET_METHOD(named_variant_class_, named_variant_from_int_array_, "<init>",
|
|
"(Ljava/lang/String;[I)V");
|
|
TC3_GET_METHOD(
|
|
named_variant_class_, named_variant_from_named_variant_array_, "<init>",
|
|
"(Ljava/lang/String;[L" TC3_PACKAGE_PATH TC3_NAMED_VARIANT_CLASS_NAME_STR
|
|
";)V");
|
|
return handler;
|
|
}
|
|
|
|
StatusOr<ScopedLocalRef<jstring>> RemoteActionTemplatesHandler::AsUTF8String(
|
|
const Optional<std::string>& optional) const {
|
|
if (!optional.has_value()) {
|
|
return {{nullptr, jni_cache_->GetEnv()}};
|
|
}
|
|
return jni_cache_->ConvertToJavaString(optional.value());
|
|
}
|
|
|
|
StatusOr<ScopedLocalRef<jobject>> RemoteActionTemplatesHandler::AsInteger(
|
|
const Optional<int>& optional) const {
|
|
if (!optional.has_value()) {
|
|
return {{nullptr, jni_cache_->GetEnv()}};
|
|
}
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jobject> result,
|
|
JniHelper::NewObject(jni_cache_->GetEnv(), integer_class_.get(),
|
|
integer_init_, optional.value()));
|
|
|
|
return result;
|
|
}
|
|
|
|
StatusOr<ScopedLocalRef<jobjectArray>>
|
|
RemoteActionTemplatesHandler::AsStringArray(
|
|
const std::vector<std::string>& values) const {
|
|
if (values.empty()) {
|
|
return {{nullptr, jni_cache_->GetEnv()}};
|
|
}
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jobjectArray> result,
|
|
JniHelper::NewObjectArray(jni_cache_->GetEnv(), values.size(),
|
|
jni_cache_->string_class.get(), nullptr));
|
|
|
|
for (int k = 0; k < values.size(); k++) {
|
|
TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> value_str,
|
|
jni_cache_->ConvertToJavaString(values[k]));
|
|
TC3_RETURN_IF_ERROR(JniHelper::SetObjectArrayElement(
|
|
jni_cache_->GetEnv(), result.get(), k, value_str.get()));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
StatusOr<ScopedLocalRef<jfloatArray>>
|
|
RemoteActionTemplatesHandler::AsFloatArray(
|
|
const std::vector<float>& values) const {
|
|
if (values.empty()) {
|
|
return {{nullptr, jni_cache_->GetEnv()}};
|
|
}
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jfloatArray> result,
|
|
JniHelper::NewFloatArray(jni_cache_->GetEnv(), values.size()));
|
|
|
|
TC3_RETURN_IF_ERROR(JniHelper::SetFloatArrayRegion(
|
|
jni_cache_->GetEnv(), result.get(), /*start=*/0,
|
|
/*len=*/values.size(), &(values[0])));
|
|
return result;
|
|
}
|
|
|
|
StatusOr<ScopedLocalRef<jintArray>> RemoteActionTemplatesHandler::AsIntArray(
|
|
const std::vector<int>& values) const {
|
|
if (values.empty()) {
|
|
return {{nullptr, jni_cache_->GetEnv()}};
|
|
}
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jintArray> result,
|
|
JniHelper::NewIntArray(jni_cache_->GetEnv(), values.size()));
|
|
|
|
TC3_RETURN_IF_ERROR(JniHelper::SetIntArrayRegion(
|
|
jni_cache_->GetEnv(), result.get(), /*start=*/0,
|
|
/*len=*/values.size(), &(values[0])));
|
|
return result;
|
|
}
|
|
|
|
StatusOr<ScopedLocalRef<jobject>> RemoteActionTemplatesHandler::AsNamedVariant(
|
|
const std::string& name_str, const Variant& value) const {
|
|
TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> name,
|
|
jni_cache_->ConvertToJavaString(name_str));
|
|
|
|
JNIEnv* env = jni_cache_->GetEnv();
|
|
switch (value.GetType()) {
|
|
case Variant::TYPE_INT_VALUE:
|
|
return JniHelper::NewObject(env, named_variant_class_.get(),
|
|
named_variant_from_int_, name.get(),
|
|
value.Value<int>());
|
|
|
|
case Variant::TYPE_INT64_VALUE:
|
|
return JniHelper::NewObject(env, named_variant_class_.get(),
|
|
named_variant_from_long_, name.get(),
|
|
value.Value<int64>());
|
|
|
|
case Variant::TYPE_FLOAT_VALUE:
|
|
return JniHelper::NewObject(env, named_variant_class_.get(),
|
|
named_variant_from_float_, name.get(),
|
|
value.Value<float>());
|
|
|
|
case Variant::TYPE_DOUBLE_VALUE:
|
|
return JniHelper::NewObject(env, named_variant_class_.get(),
|
|
named_variant_from_double_, name.get(),
|
|
value.Value<double>());
|
|
|
|
case Variant::TYPE_BOOL_VALUE:
|
|
return JniHelper::NewObject(env, named_variant_class_.get(),
|
|
named_variant_from_bool_, name.get(),
|
|
value.Value<bool>());
|
|
|
|
case Variant::TYPE_STRING_VALUE: {
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jstring> value_jstring,
|
|
jni_cache_->ConvertToJavaString(value.ConstRefValue<std::string>()));
|
|
return JniHelper::NewObject(env, named_variant_class_.get(),
|
|
named_variant_from_string_, name.get(),
|
|
value_jstring.get());
|
|
}
|
|
|
|
case Variant::TYPE_STRING_VECTOR_VALUE: {
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jobjectArray> value_jstring_array,
|
|
AsStringArray(value.ConstRefValue<std::vector<std::string>>()));
|
|
|
|
return JniHelper::NewObject(env, named_variant_class_.get(),
|
|
named_variant_from_string_array_, name.get(),
|
|
value_jstring_array.get());
|
|
}
|
|
|
|
case Variant::TYPE_FLOAT_VECTOR_VALUE: {
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jfloatArray> value_jfloat_array,
|
|
AsFloatArray(value.ConstRefValue<std::vector<float>>()));
|
|
|
|
return JniHelper::NewObject(env, named_variant_class_.get(),
|
|
named_variant_from_float_array_, name.get(),
|
|
value_jfloat_array.get());
|
|
}
|
|
|
|
case Variant::TYPE_INT_VECTOR_VALUE: {
|
|
TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jintArray> value_jint_array,
|
|
AsIntArray(value.ConstRefValue<std::vector<int>>()));
|
|
|
|
return JniHelper::NewObject(env, named_variant_class_.get(),
|
|
named_variant_from_int_array_, name.get(),
|
|
value_jint_array.get());
|
|
}
|
|
|
|
case Variant::TYPE_STRING_VARIANT_MAP_VALUE: {
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jobjectArray> value_jobect_array,
|
|
AsNamedVariantArray(
|
|
value.ConstRefValue<std::map<std::string, Variant>>()));
|
|
return JniHelper::NewObject(env, named_variant_class_.get(),
|
|
named_variant_from_named_variant_array_,
|
|
name.get(), value_jobect_array.get());
|
|
}
|
|
|
|
case Variant::TYPE_EMPTY:
|
|
return {Status::UNKNOWN};
|
|
|
|
default:
|
|
TC3_LOG(ERROR) << "Unsupported NamedVariant type: " << value.GetType();
|
|
return {Status::UNKNOWN};
|
|
}
|
|
}
|
|
|
|
StatusOr<ScopedLocalRef<jobjectArray>>
|
|
RemoteActionTemplatesHandler::AsNamedVariantArray(
|
|
const std::map<std::string, Variant>& values) const {
|
|
JNIEnv* env = jni_cache_->GetEnv();
|
|
if (values.empty()) {
|
|
return {{nullptr, env}};
|
|
}
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jobjectArray> result,
|
|
JniHelper::NewObjectArray(jni_cache_->GetEnv(), values.size(),
|
|
named_variant_class_.get(), nullptr));
|
|
int element_index = 0;
|
|
for (const auto& key_value_pair : values) {
|
|
if (!key_value_pair.second.HasValue()) {
|
|
element_index++;
|
|
continue;
|
|
}
|
|
TC3_ASSIGN_OR_RETURN(
|
|
StatusOr<ScopedLocalRef<jobject>> named_extra,
|
|
AsNamedVariant(key_value_pair.first, key_value_pair.second));
|
|
TC3_RETURN_IF_ERROR(JniHelper::SetObjectArrayElement(
|
|
env, result.get(), element_index, named_extra.ValueOrDie().get()));
|
|
element_index++;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
StatusOr<ScopedLocalRef<jobjectArray>>
|
|
RemoteActionTemplatesHandler::RemoteActionTemplatesToJObjectArray(
|
|
const std::vector<RemoteActionTemplate>& remote_actions) const {
|
|
JNIEnv* env = jni_cache_->GetEnv();
|
|
TC3_ASSIGN_OR_RETURN(
|
|
ScopedLocalRef<jobjectArray> results,
|
|
JniHelper::NewObjectArray(env, remote_actions.size(),
|
|
remote_action_template_class_.get(), nullptr));
|
|
|
|
for (int i = 0; i < remote_actions.size(); i++) {
|
|
const RemoteActionTemplate& remote_action = remote_actions[i];
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
const StatusOr<ScopedLocalRef<jstring>> title_without_entity,
|
|
AsUTF8String(remote_action.title_without_entity));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
const StatusOr<ScopedLocalRef<jstring>> title_with_entity,
|
|
AsUTF8String(remote_action.title_with_entity));
|
|
TC3_ASSIGN_OR_RETURN(const StatusOr<ScopedLocalRef<jstring>> description,
|
|
AsUTF8String(remote_action.description));
|
|
TC3_ASSIGN_OR_RETURN(
|
|
const StatusOr<ScopedLocalRef<jstring>> description_with_app_name,
|
|
AsUTF8String(remote_action.description_with_app_name));
|
|
TC3_ASSIGN_OR_RETURN(const StatusOr<ScopedLocalRef<jstring>> action,
|
|
AsUTF8String(remote_action.action));
|
|
TC3_ASSIGN_OR_RETURN(const StatusOr<ScopedLocalRef<jstring>> data,
|
|
AsUTF8String(remote_action.data));
|
|
TC3_ASSIGN_OR_RETURN(const StatusOr<ScopedLocalRef<jstring>> type,
|
|
AsUTF8String(remote_action.type));
|
|
TC3_ASSIGN_OR_RETURN(const StatusOr<ScopedLocalRef<jobject>> flags,
|
|
AsInteger(remote_action.flags));
|
|
TC3_ASSIGN_OR_RETURN(const StatusOr<ScopedLocalRef<jobjectArray>> category,
|
|
AsStringArray(remote_action.category));
|
|
TC3_ASSIGN_OR_RETURN(const StatusOr<ScopedLocalRef<jstring>> package,
|
|
AsUTF8String(remote_action.package_name));
|
|
TC3_ASSIGN_OR_RETURN(const StatusOr<ScopedLocalRef<jobjectArray>> extra,
|
|
AsNamedVariantArray(remote_action.extra));
|
|
TC3_ASSIGN_OR_RETURN(const StatusOr<ScopedLocalRef<jobject>> request_code,
|
|
AsInteger(remote_action.request_code));
|
|
|
|
TC3_ASSIGN_OR_RETURN(
|
|
const ScopedLocalRef<jobject> result,
|
|
JniHelper::NewObject(
|
|
env, remote_action_template_class_.get(),
|
|
remote_action_template_init_,
|
|
title_without_entity.ValueOrDie().get(),
|
|
title_with_entity.ValueOrDie().get(),
|
|
description.ValueOrDie().get(),
|
|
description_with_app_name.ValueOrDie().get(),
|
|
action.ValueOrDie().get(), data.ValueOrDie().get(),
|
|
type.ValueOrDie().get(), flags.ValueOrDie().get(),
|
|
category.ValueOrDie().get(), package.ValueOrDie().get(),
|
|
extra.ValueOrDie().get(), request_code.ValueOrDie().get()));
|
|
TC3_RETURN_IF_ERROR(
|
|
JniHelper::SetObjectArrayElement(env, results.get(), i, result.get()));
|
|
}
|
|
return results;
|
|
}
|
|
|
|
StatusOr<ScopedLocalRef<jobjectArray>>
|
|
RemoteActionTemplatesHandler::EntityDataAsNamedVariantArray(
|
|
const reflection::Schema* entity_data_schema,
|
|
const std::string& serialized_entity_data) const {
|
|
MutableFlatbufferBuilder entity_data_builder(entity_data_schema);
|
|
std::unique_ptr<MutableFlatbuffer> buffer = entity_data_builder.NewRoot();
|
|
buffer->MergeFromSerializedFlatbuffer(serialized_entity_data);
|
|
std::map<std::string, Variant> entity_data_map = buffer->AsFlatMap();
|
|
return AsNamedVariantArray(entity_data_map);
|
|
}
|
|
|
|
} // namespace libtextclassifier3
|