• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "utils/intents/jni.h"
18 #include <memory>
19 #include "utils/intents/intent-generator.h"
20 #include "utils/java/scoped_local_ref.h"
21 
22 namespace libtextclassifier3 {
23 
24 // The macros below are intended to reduce the boilerplate and avoid
25 // easily introduced copy/paste errors.
26 #define TC3_CHECK_JNI_PTR(PTR) TC3_CHECK((PTR) != nullptr)
27 #define TC3_GET_CLASS(FIELD, NAME)                                           \
28   handler->FIELD = MakeGlobalRef(env->FindClass(NAME), env, jni_cache->jvm); \
29   TC3_CHECK_JNI_PTR(handler->FIELD) << "Error finding class: " << NAME;
30 #define TC3_GET_METHOD(CLASS, FIELD, NAME, SIGNATURE)                       \
31   handler->FIELD = env->GetMethodID(handler->CLASS.get(), NAME, SIGNATURE); \
32   TC3_CHECK(handler->FIELD) << "Error finding method: " << NAME;
33 
34 std::unique_ptr<RemoteActionTemplatesHandler>
Create(const std::shared_ptr<JniCache> & jni_cache)35 RemoteActionTemplatesHandler::Create(
36     const std::shared_ptr<JniCache>& jni_cache) {
37   JNIEnv* env = jni_cache->GetEnv();
38   if (env == nullptr) {
39     return nullptr;
40   }
41 
42   std::unique_ptr<RemoteActionTemplatesHandler> handler(
43       new RemoteActionTemplatesHandler(jni_cache));
44 
45   TC3_GET_CLASS(integer_class_, "java/lang/Integer");
46   TC3_GET_METHOD(integer_class_, integer_init_, "<init>", "(I)V");
47 
48   TC3_GET_CLASS(remote_action_template_class_,
49                 TC3_PACKAGE_PATH TC3_REMOTE_ACTION_TEMPLATE_CLASS_NAME_STR);
50   TC3_GET_METHOD(
51       remote_action_template_class_, remote_action_template_init_, "<init>",
52       "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
53       "String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
54       "Integer;[Ljava/lang/String;Ljava/lang/String;[L" TC3_PACKAGE_PATH
55           TC3_NAMED_VARIANT_CLASS_NAME_STR ";Ljava/lang/Integer;)V");
56 
57   TC3_GET_CLASS(named_variant_class_,
58                 TC3_PACKAGE_PATH TC3_NAMED_VARIANT_CLASS_NAME_STR);
59 
60   TC3_GET_METHOD(named_variant_class_, named_variant_from_int_, "<init>",
61                  "(Ljava/lang/String;I)V");
62   TC3_GET_METHOD(named_variant_class_, named_variant_from_long_, "<init>",
63                  "(Ljava/lang/String;J)V");
64   TC3_GET_METHOD(named_variant_class_, named_variant_from_float_, "<init>",
65                  "(Ljava/lang/String;F)V");
66   TC3_GET_METHOD(named_variant_class_, named_variant_from_double_, "<init>",
67                  "(Ljava/lang/String;D)V");
68   TC3_GET_METHOD(named_variant_class_, named_variant_from_bool_, "<init>",
69                  "(Ljava/lang/String;Z)V");
70   TC3_GET_METHOD(named_variant_class_, named_variant_from_string_, "<init>",
71                  "(Ljava/lang/String;Ljava/lang/String;)V");
72 
73   return handler;
74 }
75 
AsUTF8String(const Optional<std::string> & optional) const76 jstring RemoteActionTemplatesHandler::AsUTF8String(
77     const Optional<std::string>& optional) const {
78   if (!optional.has_value()) {
79     return nullptr;
80   }
81   return jni_cache_->ConvertToJavaString(optional.value()).release();
82 }
83 
AsInteger(const Optional<int> & optional) const84 jobject RemoteActionTemplatesHandler::AsInteger(
85     const Optional<int>& optional) const {
86   return (optional.has_value()
87               ? jni_cache_->GetEnv()->NewObject(integer_class_.get(),
88                                                 integer_init_, optional.value())
89               : nullptr);
90 }
91 
AsStringArray(const std::vector<std::string> & values) const92 jobjectArray RemoteActionTemplatesHandler::AsStringArray(
93     const std::vector<std::string>& values) const {
94   if (values.empty()) {
95     return nullptr;
96   }
97   jobjectArray result = jni_cache_->GetEnv()->NewObjectArray(
98       values.size(), jni_cache_->string_class.get(), nullptr);
99   if (result == nullptr) {
100     return nullptr;
101   }
102   for (int k = 0; k < values.size(); k++) {
103     ScopedLocalRef<jstring> value_str =
104         jni_cache_->ConvertToJavaString(values[k]);
105     jni_cache_->GetEnv()->SetObjectArrayElement(result, k, value_str.get());
106   }
107   return result;
108 }
109 
AsNamedVariant(const std::string & name_str,const Variant & value) const110 jobject RemoteActionTemplatesHandler::AsNamedVariant(
111     const std::string& name_str, const Variant& value) const {
112   ScopedLocalRef<jstring> name = jni_cache_->ConvertToJavaString(name_str);
113   if (name == nullptr) {
114     return nullptr;
115   }
116   switch (value.GetType()) {
117     case Variant::TYPE_INT_VALUE:
118       return jni_cache_->GetEnv()->NewObject(named_variant_class_.get(),
119                                              named_variant_from_int_,
120                                              name.get(), value.IntValue());
121     case Variant::TYPE_INT64_VALUE:
122       return jni_cache_->GetEnv()->NewObject(named_variant_class_.get(),
123                                              named_variant_from_long_,
124                                              name.get(), value.Int64Value());
125     case Variant::TYPE_FLOAT_VALUE:
126       return jni_cache_->GetEnv()->NewObject(named_variant_class_.get(),
127                                              named_variant_from_float_,
128                                              name.get(), value.FloatValue());
129     case Variant::TYPE_DOUBLE_VALUE:
130       return jni_cache_->GetEnv()->NewObject(named_variant_class_.get(),
131                                              named_variant_from_double_,
132                                              name.get(), value.DoubleValue());
133     case Variant::TYPE_BOOL_VALUE:
134       return jni_cache_->GetEnv()->NewObject(named_variant_class_.get(),
135                                              named_variant_from_bool_,
136                                              name.get(), value.BoolValue());
137     case Variant::TYPE_STRING_VALUE: {
138       ScopedLocalRef<jstring> value_jstring =
139           jni_cache_->ConvertToJavaString(value.StringValue());
140       if (value_jstring == nullptr) {
141         return nullptr;
142       }
143       return jni_cache_->GetEnv()->NewObject(named_variant_class_.get(),
144                                              named_variant_from_string_,
145                                              name.get(), value_jstring.get());
146     }
147     default:
148       return nullptr;
149   }
150 }
151 
AsNamedVariantArray(const std::map<std::string,Variant> & values) const152 jobjectArray RemoteActionTemplatesHandler::AsNamedVariantArray(
153     const std::map<std::string, Variant>& values) const {
154   if (values.empty()) {
155     return nullptr;
156   }
157   jobjectArray result = jni_cache_->GetEnv()->NewObjectArray(
158       values.size(), named_variant_class_.get(), nullptr);
159   int element_index = 0;
160   for (auto key_value_pair : values) {
161     if (!key_value_pair.second.HasValue()) {
162       element_index++;
163       continue;
164     }
165     ScopedLocalRef<jobject> named_extra(
166         AsNamedVariant(key_value_pair.first, key_value_pair.second),
167         jni_cache_->GetEnv());
168     if (named_extra == nullptr) {
169       return nullptr;
170     }
171     jni_cache_->GetEnv()->SetObjectArrayElement(result, element_index,
172                                                 named_extra.get());
173     element_index++;
174   }
175   return result;
176 }
177 
RemoteActionTemplatesToJObjectArray(const std::vector<RemoteActionTemplate> & remote_actions) const178 jobjectArray RemoteActionTemplatesHandler::RemoteActionTemplatesToJObjectArray(
179     const std::vector<RemoteActionTemplate>& remote_actions) const {
180   const jobjectArray results = jni_cache_->GetEnv()->NewObjectArray(
181       remote_actions.size(), remote_action_template_class_.get(), nullptr);
182   if (results == nullptr) {
183     return nullptr;
184   }
185   for (int i = 0; i < remote_actions.size(); i++) {
186     const RemoteActionTemplate& remote_action = remote_actions[i];
187     const jstring title_without_entity =
188         AsUTF8String(remote_action.title_without_entity);
189     const jstring title_with_entity =
190         AsUTF8String(remote_action.title_with_entity);
191     const jstring description = AsUTF8String(remote_action.description);
192     const jstring description_with_app_name =
193         AsUTF8String(remote_action.description_with_app_name);
194     const jstring action = AsUTF8String(remote_action.action);
195     const jstring data = AsUTF8String(remote_action.data);
196     const jstring type = AsUTF8String(remote_action.type);
197     const jobject flags = AsInteger(remote_action.flags);
198     const jobjectArray category = AsStringArray(remote_action.category);
199     const jstring package = AsUTF8String(remote_action.package_name);
200     const jobjectArray extra = AsNamedVariantArray(remote_action.extra);
201     const jobject request_code = AsInteger(remote_action.request_code);
202     ScopedLocalRef<jobject> result(
203         jni_cache_->GetEnv()->NewObject(
204             remote_action_template_class_.get(), remote_action_template_init_,
205             title_without_entity, title_with_entity, description,
206             description_with_app_name, action, data, type, flags, category,
207             package, extra, request_code),
208         jni_cache_->GetEnv());
209     if (result == nullptr) {
210       return nullptr;
211     }
212     jni_cache_->GetEnv()->SetObjectArrayElement(results, i, result.get());
213   }
214   return results;
215 }
216 
EntityDataAsNamedVariantArray(const reflection::Schema * entity_data_schema,const std::string & serialized_entity_data) const217 jobject RemoteActionTemplatesHandler::EntityDataAsNamedVariantArray(
218     const reflection::Schema* entity_data_schema,
219     const std::string& serialized_entity_data) const {
220   ReflectiveFlatbufferBuilder entity_data_builder(entity_data_schema);
221   std::unique_ptr<ReflectiveFlatbuffer> buffer = entity_data_builder.NewRoot();
222   buffer->MergeFromSerializedFlatbuffer(serialized_entity_data);
223   std::map<std::string, Variant> entity_data_map = buffer->AsFlatMap();
224   return AsNamedVariantArray(entity_data_map);
225 }
226 
227 }  // namespace libtextclassifier3
228