• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "text_embedding_napi.h"
17 
18 #include <dlfcn.h>
19 
20 #include "aip_log.h"
21 #include "aip_napi_error.h"
22 #include "aip_napi_utils.h"
23 #include "i_aip_core_manager_impl.h"
24 
25 #undef LOG_TAG
26 #define LOG_TAG "TextEmbeddingNapi"
27 
28 namespace OHOS {
29 namespace DataIntelligence {
30 namespace {
31 const int32_t ERR_OK = 0;
32 static constexpr uint8_t ARG_0 = 0;
33 static constexpr uint8_t ARG_1 = 1;
34 static constexpr uint8_t ARG_2 = 2;
35 
36 static constexpr uint8_t NUM_0 = 0;
37 static constexpr uint8_t NUM_1 = 1;
38 static constexpr uint8_t BASIC_MODEL = 0;
39 static constexpr uint32_t MAX_STR_PARAM_LEN = 512;
40 static const std::string CLASS_NAME = "TextEmbedding";
41 const std::vector<std::string> EXPECTED_SPLITTEXT_ARG_TYPES = { "string", "object" };
42 const std::vector<std::string> EXPECTED_GET_TEXT_MODEL_ARG_TYPES = { "object" };
43 constexpr const char *AIP_MANAGER_PATH = "libaip_core.z.so";
44 } // namespace
45 AipCoreManagerHandle TextEmbeddingNapi::textAipCoreMgrHandle_{};
46 thread_local napi_ref TextEmbeddingNapi::sConstructor_ = nullptr;
47 IAipCoreManager *TextEmbeddingNapi::textAipCoreManager_ = nullptr;
48 
49 struct LoadCallbackData {
50     napi_async_work asyncWork;
51     napi_deferred deferred;
52     int32_t ret;
53 };
54 
55 struct ReleaseCallbackData {
56     napi_async_work asyncWork;
57     napi_deferred deferred;
58     int32_t ret;
59 };
60 
61 struct TextStringCallbackData {
62     napi_async_work asyncWork;
63     napi_deferred deferred;
64     std::string strArg;
65     int32_t dataRet;
66     std::vector<float> ret;
67 };
68 
69 struct TextArrayCallbackData {
70     napi_async_work asyncWork;
71     napi_deferred deferred;
72     std::vector<std::string> text;
73     int32_t dataRet;
74     std::vector<std::vector<float>> ret;
75 };
76 
77 
78 struct SplitTextCallbackData {
79     napi_async_work asyncWork;
80     napi_deferred deferred;
81     std::string strArg;
82     int32_t configSize;
83     double configOverlap;
84     int32_t dataRet;
85     std::vector<std::string> ret;
86 };
87 
88 struct TextEmbeddingConstructorInfo {
89     std::string className;
90     napi_ref *classRef;
91     napi_callback constructor;
92     const napi_property_descriptor *property;
93     size_t propertyCount;
94     const napi_property_descriptor *staticProperty;
95     size_t staticPropertyCount;
96 };
97 
TextEmbeddingNapi()98 TextEmbeddingNapi::TextEmbeddingNapi() : env_(nullptr) {}
99 
~TextEmbeddingNapi()100 TextEmbeddingNapi::~TextEmbeddingNapi()
101 {
102     AIP_HILOGI("Enter");
103     AipNapiUtils::UnLoadAlgoLibrary(textAipCoreMgrHandle_);
104     delete textAipCoreManager_;
105     textAipCoreManager_ = nullptr;
106 }
107 
StartInit(napi_env env,napi_value exports,struct TextEmbeddingConstructorInfo info)108 static napi_value StartInit(napi_env env, napi_value exports, struct TextEmbeddingConstructorInfo info)
109 {
110     napi_value constructor = nullptr;
111     napi_status status = napi_define_class(env, info.className.c_str(), NAPI_AUTO_LENGTH, info.constructor, nullptr,
112         info.propertyCount, info.property, &constructor);
113     if (status != napi_ok) {
114         AIP_HILOGE("define class fail");
115         return nullptr;
116     }
117 
118     status = napi_create_reference(env, constructor, NUM_1, info.classRef);
119     if (status != napi_ok) {
120         AIP_HILOGE("create reference fail");
121         return nullptr;
122     }
123 
124     napi_value global = nullptr;
125     status = napi_get_global(env, &global);
126     if (status != napi_ok) {
127         AIP_HILOGE("create global fail");
128         return nullptr;
129     }
130 
131     status = napi_set_named_property(env, global, info.className.c_str(), constructor);
132     if (status != napi_ok) {
133         AIP_HILOGE("Init::set global named property fail");
134         return nullptr;
135     }
136 
137     status = napi_define_properties(env, exports, info.staticPropertyCount, info.staticProperty);
138     if (status != napi_ok) {
139         AIP_HILOGE("define properties fail");
140         return nullptr;
141     }
142     return exports;
143 }
144 
Init(napi_env env,napi_value exports)145 napi_value TextEmbeddingNapi::Init(napi_env env, napi_value exports)
146 {
147     AIP_HILOGD("Enter");
148     if (!AipNapiUtils::LoadAlgoLibrary(AIP_MANAGER_PATH, textAipCoreMgrHandle_)) {
149         AIP_HILOGE("LoadAlgoLibrary failed");
150     }
151 
152     if (textAipCoreMgrHandle_.pAipManager != nullptr) {
153         textAipCoreManager_ = AipNapiUtils::GetAlgoObj(textAipCoreMgrHandle_);
154     } else {
155         textAipCoreManager_ = new (std::nothrow) IAipCoreManagerImpl();
156     }
157 
158     if (textAipCoreManager_ == nullptr) {
159         AIP_HILOGE("GetAlgoObj failed");
160         return nullptr;
161     }
162 
163     napi_property_descriptor properties[] = {
164         DECLARE_NAPI_FUNCTION("loadModel", LoadModel),
165         DECLARE_NAPI_FUNCTION("releaseModel", ReleaseModel),
166         DECLARE_NAPI_FUNCTION("getEmbedding", GetEmbedding),
167     };
168 
169     napi_property_descriptor static_prop[] = {
170         DECLARE_NAPI_STATIC_FUNCTION("getTextEmbeddingModel", GetTextEmbeddingModel),
171         DECLARE_NAPI_STATIC_FUNCTION("splitText", SplitText),
172     };
173 
174     napi_value modelVersion;
175     napi_status status = napi_create_object(env, &modelVersion);
176     if (status != napi_ok) {
177         AIP_HILOGE("Failed create object");
178         return nullptr;
179     }
180 
181     AipNapiUtils::SetInt32Property(env, modelVersion, BASIC_MODEL, "BASIC_MODEL");
182     AipNapiUtils::SetPropertyName(env, exports, "ModelVersion", modelVersion);
183 
184     struct TextEmbeddingConstructorInfo info = {
185         .className = CLASS_NAME,
186         .classRef = &sConstructor_,
187         .constructor = TextConstructor,
188         .property = properties,
189         .propertyCount = sizeof(properties) / sizeof(properties[NUM_0]),
190         .staticProperty = static_prop,
191         .staticPropertyCount = sizeof(static_prop) / sizeof(static_prop[NUM_0]),
192     };
193 
194     if (StartInit(env, exports, info)) {
195         return nullptr;
196     }
197     return exports;
198 }
199 
TextConstructor(napi_env env,napi_callback_info info)200 napi_value TextEmbeddingNapi::TextConstructor(napi_env env, napi_callback_info info)
201 {
202     napi_value undefineValue = nullptr;
203     napi_get_undefined(env, &undefineValue);
204 
205     napi_status status;
206     napi_value thisVar = nullptr;
207     status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
208     if (status == napi_ok && thisVar != nullptr) {
209         std::unique_ptr<TextEmbeddingNapi> txtEmbNapi = std::make_unique<TextEmbeddingNapi>();
210         if (txtEmbNapi != nullptr) {
211             txtEmbNapi->env_ = env;
212             status = napi_wrap(env, thisVar, reinterpret_cast<void *>(txtEmbNapi.get()), TextEmbeddingNapi::Destructor,
213                 nullptr, nullptr);
214             if (status == napi_ok) {
215                 txtEmbNapi.release();
216                 return thisVar;
217             } else {
218                 AIP_HILOGE("Failure wrapping js to native napi");
219             }
220         }
221     }
222     return undefineValue;
223 }
224 
Destructor(napi_env env,void * nativeObject,void * finalize)225 void TextEmbeddingNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
226 {
227     AIP_HILOGD("TextEmbeddingNapi, Destructor");
228 }
229 
GetTextEmbeddingModel(napi_env env,napi_callback_info info)230 napi_value TextEmbeddingNapi::GetTextEmbeddingModel(napi_env env, napi_callback_info info)
231 {
232     AIP_HILOGE("Enter");
233     size_t argc = ARG_1;
234     napi_value args[ARG_1] = { nullptr };
235     napi_value jsThis = nullptr;
236 
237     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
238     if (status != napi_ok) {
239         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "napi_get_cb_info failed");
240         return nullptr;
241     }
242 
243     if (!AipNapiUtils::ValidateArgsType(env, args, argc, EXPECTED_GET_TEXT_MODEL_ARG_TYPES)) {
244         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "ValidateArgsType failed");
245         return nullptr;
246     }
247 
248     ModelConfigData textModelConfig;
249     if (!ParseModelConfig(env, args, argc, &textModelConfig)) {
250         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "ParseModelConfig failed");
251         return nullptr;
252     }
253 
254     napi_value promise = nullptr;
255     napi_deferred deferred = nullptr;
256     status = napi_create_promise(env, &deferred, &promise);
257     if (status != napi_ok) {
258         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "create promise failed");
259         return nullptr;
260     }
261 
262     auto asyncGetTextEmbeddingModelData = new (std::nothrow) AsyncGetTextEmbeddingModelData{
263         .asyncWork = nullptr,
264         .deferred = deferred,
265         .config = textModelConfig,
266     };
267     if (asyncGetTextEmbeddingModelData == nullptr) {
268         AIP_HILOGE("new asyncGetTextEmbeddingModelData error.");
269         ThrowIntelligenceErr(env, INNER_ERROR, "new asyncGetTextEmbeddingModelData failed");
270         return nullptr;
271     }
272 
273     if (!CreateAsyncTextModelExecution(env, asyncGetTextEmbeddingModelData)) {
274         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "create AsyncTextModelExecution failed");
275         delete asyncGetTextEmbeddingModelData;
276         return nullptr;
277     }
278 
279     return promise;
280 }
281 
ParseModelConfig(napi_env env,napi_value * args,size_t argc,ModelConfigData * textModelConfig)282 bool TextEmbeddingNapi::ParseModelConfig(napi_env env, napi_value *args, size_t argc, ModelConfigData *textModelConfig)
283 {
284     AIP_HILOGI("Enter");
285     if (textModelConfig == nullptr) {
286         AIP_HILOGE("The modelConfig is null");
287         return false;
288     }
289     if (!AipNapiUtils::CheckModelConfig(env, args[ARG_0])) {
290         AIP_HILOGE("The modelConfig is failed");
291         return false;
292     }
293 
294     napi_value version;
295     napi_value isNPUAvailable;
296     napi_value cachePath;
297     napi_status status = napi_get_named_property(env, args[ARG_0], "version", &version);
298     if (status != napi_ok) {
299         AIP_HILOGE("napi get version property failed");
300         return false;
301     }
302 
303     if (!AipNapiUtils::TransJsToInt32(env, version, textModelConfig->versionValue)) {
304         AIP_HILOGE("Trans version failed");
305         return false;
306     }
307 
308     if (textModelConfig->versionValue != BASIC_MODEL) {
309         AIP_HILOGE("The version value is invalid");
310         return false;
311     }
312 
313     status = napi_get_named_property(env, args[ARG_0], "isNpuAvailable", &isNPUAvailable);
314     if (status != napi_ok) {
315         AIP_HILOGE("napi get isNpuAvailable property failed");
316         return false;
317     }
318 
319     if (!AipNapiUtils::TransJsToBool(env, isNPUAvailable, textModelConfig->isNPUAvailableValue)) {
320         AIP_HILOGE("Trans isNPUAvailable failed");
321         return false;
322     }
323 
324     if (textModelConfig->isNPUAvailableValue) {
325         status = napi_get_named_property(env, args[ARG_0], "cachePath", &cachePath);
326         if (status != napi_ok) {
327             AIP_HILOGE("napi get cachePath property failed");
328             return false;
329         }
330 
331         if (!AipNapiUtils::TransJsToStr(env, cachePath, textModelConfig->cachePathValue)) {
332             AIP_HILOGE("Trans cachePath failed");
333             return false;
334         }
335     } else {
336         textModelConfig->cachePathValue = "";
337     }
338     return true;
339 }
340 
CreateAsyncTextModelExecution(napi_env env,AsyncGetTextEmbeddingModelData * asyncModelData)341 bool TextEmbeddingNapi::CreateAsyncTextModelExecution(napi_env env, AsyncGetTextEmbeddingModelData *asyncModelData)
342 {
343     AIP_HILOGI("Enter");
344     napi_value resourceName;
345     napi_status status = napi_create_string_utf8(env, "GetTextEmbeddingModel", NAPI_AUTO_LENGTH, &resourceName);
346     if (status != napi_ok) {
347         AIP_HILOGE(" napi_create_string_utf8 failed");
348         return false;
349     }
350 
351     status = napi_create_async_work(env, nullptr, resourceName, GetTextEmbeddingModelExecutionCB,
352         GetTextEmbeddingModelCompleteCB, static_cast<void *>(asyncModelData), &asyncModelData->asyncWork);
353     if (status != napi_ok) {
354         AIP_HILOGE("napi_create_async_work failed");
355         return false;
356     }
357 
358     status = napi_queue_async_work_with_qos(env, asyncModelData->asyncWork, napi_qos_default);
359     if (status != napi_ok) {
360         AIP_HILOGE("napi_queue_async_work_with_qos failed");
361         return false;
362     }
363     return true;
364 }
365 
366 
GetTextEmbeddingModelExecutionCB(napi_env env,void * data)367 void TextEmbeddingNapi::GetTextEmbeddingModelExecutionCB(napi_env env, void *data)
368 {
369     AIP_HILOGD("Enter");
370     AsyncGetTextEmbeddingModelData *modelData = static_cast<AsyncGetTextEmbeddingModelData *>(data);
371     if (textAipCoreManager_ == nullptr) {
372         AIP_HILOGE("pAipManager is nullptr");
373         return;
374     }
375     auto config = modelData->config;
376     int32_t result = textAipCoreManager_->InitTextModel(config);
377     modelData->ret = result;
378     AIP_HILOGD("Exit");
379 }
380 
GetTextEmbeddingModelCompleteCB(napi_env env,napi_status status,void * data)381 void TextEmbeddingNapi::GetTextEmbeddingModelCompleteCB(napi_env env, napi_status status, void *data)
382 {
383     AIP_HILOGD("Enter");
384     AsyncGetTextEmbeddingModelData *modelData = static_cast<AsyncGetTextEmbeddingModelData *>(data);
385     auto ret = modelData->ret;
386     napi_value result = nullptr;
387     napi_value constructor = nullptr;
388     if (ret != ERR_OK) {
389         if (ret == DEVICE_EXCEPTION) {
390             ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "GetTextEmbeddingModelCompleteCB failed", result);
391         } else {
392             ThrowIntelligenceErrByPromise(env, INNER_ERROR, "GetTextEmbeddingModelCompleteCB failed", result);
393         }
394         napi_reject_deferred(env, modelData->deferred, result);
395     } else {
396         status = napi_get_reference_value(env, sConstructor_, &constructor);
397         if (status != napi_ok) {
398             AIP_HILOGE("napi_get_reference_value failed");
399             napi_get_undefined(env, &result);
400             delete modelData;
401             return;
402         }
403 
404         status = napi_new_instance(env, constructor, 0, nullptr, &result);
405         if (status != napi_ok) {
406             AIP_HILOGE("napi_new_instance failed");
407             napi_get_undefined(env, &result);
408             delete modelData;
409             return;
410         }
411 
412         status = napi_resolve_deferred(env, modelData->deferred, result);
413         if (status != napi_ok) {
414             AIP_HILOGE(" napi_resolve_deferred failed");
415         }
416     }
417 
418     status = napi_delete_async_work(env, modelData->asyncWork);
419     if (status != napi_ok) {
420         AIP_HILOGE("napi_delete_async_work failed");
421     }
422     delete modelData;
423 }
424 
425 
SplitText(napi_env env,napi_callback_info info)426 napi_value TextEmbeddingNapi::SplitText(napi_env env, napi_callback_info info)
427 {
428     AIP_HILOGI("Enter");
429     size_t argc = ARG_2;
430     napi_value args[ARG_2] = { nullptr };
431     napi_value jsThis = nullptr;
432 
433     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
434     if (status != napi_ok) {
435         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "napi_get_cb_info failed");
436         return nullptr;
437     }
438 
439     if (!AipNapiUtils::ValidateArgsType(env, args, argc, EXPECTED_SPLITTEXT_ARG_TYPES)) {
440         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "ValidateArgsType failed");
441         return nullptr;
442     }
443 
444     std::string strArg;
445     if (!AipNapiUtils::TransJsToStrUnlimited(env, args[ARG_0], strArg)) {
446         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "TransJsToStrUnlimited failed");
447         return nullptr;
448     }
449 
450     napi_value cfgSize;
451     napi_value cfgOverlap;
452     if (!GetProperties(env, args[ARG_1], cfgSize, cfgOverlap)) {
453         AIP_HILOGE("content property failed");
454         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "content property failed");
455         return nullptr;
456     }
457     int32_t configSize;
458     double configOverlap;
459     AipNapiUtils::TransJsToInt32(env, cfgSize, configSize);
460     AipNapiUtils::TransJsToDouble(env, cfgOverlap, configOverlap);
461     AIP_HILOGD("string strArg: %{public}d", configSize);
462     AIP_HILOGD("string strArg: %{public}f", configOverlap);
463 
464     napi_value promise = nullptr;
465     napi_deferred deferred = nullptr;
466     status = napi_create_promise(env, &deferred, &promise);
467     if (status != napi_ok) {
468         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "create promise failed");
469         return nullptr;
470     }
471 
472     if (!textAipCoreManager_->CheckDeviceType()) {
473         napi_value value = nullptr;
474         ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "SplitText failed", value);
475         napi_reject_deferred(env, deferred, value);
476         return promise;
477     }
478     if (configSize <= NUM_0 || configOverlap < NUM_0 || configOverlap >= NUM_1) {
479         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "The parameter value range is incorrect");
480         return nullptr;
481     }
482 
483     if (!SplitTextAsyncExecution(env, deferred, strArg, configSize, configOverlap)) {
484         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "create split text async execution failed");
485         return nullptr;
486     }
487     AIP_HILOGD("Exit");
488     return promise;
489 }
490 
SplitTextAsyncExecution(napi_env env,napi_deferred deferred,std::string strArg,int32_t configSize,double configOverlap)491 bool TextEmbeddingNapi::SplitTextAsyncExecution(napi_env env, napi_deferred deferred, std::string strArg,
492     int32_t configSize, double configOverlap)
493 {
494     AIP_HILOGD("Enter");
495     auto splitTextCallbackData = new (std::nothrow) SplitTextCallbackData{
496         .asyncWork = nullptr,
497         .deferred = deferred,
498         .strArg = strArg,
499         .configSize = configSize,
500         .configOverlap = configOverlap,
501     };
502     if (splitTextCallbackData == nullptr) {
503         AIP_HILOGE("new splitTextCallbackData error.");
504         return false;
505     }
506 
507     napi_value resourceName;
508     napi_status status = napi_create_string_utf8(env, "SplitText", NAPI_AUTO_LENGTH, &resourceName);
509     if (status != napi_ok) {
510         AIP_HILOGE("napi_create_string_utf8 failed");
511         delete splitTextCallbackData;
512         return false;
513     }
514 
515     status = napi_create_async_work(env, nullptr, resourceName, SplitTextExecuteCB, SplitTextCompleteCB,
516         static_cast<void *>(splitTextCallbackData), &splitTextCallbackData->asyncWork);
517     if (status != napi_ok) {
518         AIP_HILOGE("napi_create_async_work failed");
519         delete splitTextCallbackData;
520         return false;
521     }
522 
523     status = napi_queue_async_work_with_qos(env, splitTextCallbackData->asyncWork, napi_qos_default);
524     if (status != napi_ok) {
525         AIP_HILOGE("napi_queue_async_work_with_qos failed");
526         napi_delete_async_work(env, splitTextCallbackData->asyncWork);
527         delete splitTextCallbackData;
528         return false;
529     }
530     return true;
531 }
532 
SplitTextExecuteCB(napi_env env,void * data)533 void TextEmbeddingNapi::SplitTextExecuteCB(napi_env env, void *data)
534 {
535     AIP_HILOGD("Enter");
536     SplitTextCallbackData *splitTextCallbackData = static_cast<SplitTextCallbackData *>(data);
537     std::string strArg = splitTextCallbackData->strArg;
538     int32_t configSize = splitTextCallbackData->configSize;
539     double configOverlap = splitTextCallbackData->configOverlap;
540     std::vector<std::string> result;
541     int32_t ret = textAipCoreManager_->SplitText(strArg, configSize, static_cast<float>(configOverlap), result);
542     if (ret != ERR_OK) {
543         AIP_HILOGE("SplitText failed");
544         result = {};
545     }
546     splitTextCallbackData->ret = result;
547     splitTextCallbackData->dataRet = ret;
548     AIP_HILOGD("Exit");
549 }
SplitTextCompleteCB(napi_env env,napi_status status,void * data)550 void TextEmbeddingNapi::SplitTextCompleteCB(napi_env env, napi_status status, void *data)
551 {
552     AIP_HILOGD("Enter");
553     SplitTextCallbackData *splitTextCallbackData = static_cast<SplitTextCallbackData *>(data);
554     napi_value value = nullptr;
555     std::vector<std::string> ret = splitTextCallbackData->ret;
556     int32_t dataRet = splitTextCallbackData->dataRet;
557     if (dataRet != ERR_OK) {
558         if (dataRet == DEVICE_EXCEPTION) {
559             ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "SplitTextCompleteCB failed", value);
560         } else {
561             ThrowIntelligenceErrByPromise(env, INNER_ERROR, "SplitTextCompleteCB failed", value);
562         }
563         napi_reject_deferred(env, splitTextCallbackData->deferred, value);
564     } else {
565         status = napi_create_array(env, &value);
566         if (status != napi_ok) {
567             AIP_HILOGE("napi_create_array failed");
568         } else {
569             for (size_t i = 0; i < ret.size(); i++) {
570                 napi_value jsStr = nullptr;
571                 napi_create_string_utf8(env, ret[i].c_str(), NAPI_AUTO_LENGTH, &jsStr);
572                 napi_set_element(env, value, i, jsStr);
573             }
574             status = napi_resolve_deferred(env, splitTextCallbackData->deferred, value);
575             if (status != napi_ok) {
576                 AIP_HILOGE("napi_resolve_deferred failed");
577             }
578         }
579     }
580 
581     status = napi_delete_async_work(env, splitTextCallbackData->asyncWork);
582     if (status != napi_ok) {
583         AIP_HILOGE("napi_delete_async_work failed");
584     }
585     delete splitTextCallbackData;
586 }
587 
588 
GetProperties(napi_env env,napi_value args,napi_value & cfgSize,napi_value & cfgOverlap)589 bool TextEmbeddingNapi::GetProperties(napi_env env, napi_value args, napi_value &cfgSize, napi_value &cfgOverlap)
590 {
591     napi_status status = napi_get_named_property(env, args, "size", &cfgSize);
592     if (status != napi_ok) {
593         AIP_HILOGE("napi get size property failed");
594         return false;
595     }
596 
597     status = napi_get_named_property(env, args, "overlapRatio", &cfgOverlap);
598     if (status != napi_ok) {
599         AIP_HILOGE("napi get overlapRatio property failed");
600         return false;
601     }
602     return true;
603 }
604 
GetEmbedding(napi_env env,napi_callback_info info)605 napi_value TextEmbeddingNapi::GetEmbedding(napi_env env, napi_callback_info info)
606 {
607     AIP_HILOGE("Enter");
608     size_t argc = ARG_1;
609     napi_value args[ARG_1] = { nullptr };
610     napi_value jsThis = nullptr;
611 
612     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
613     if (status != napi_ok) {
614         ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed");
615         return nullptr;
616     }
617 
618     if (argc != ARG_1) {
619         AIP_HILOGE("param size error");
620         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "param size error");
621         return nullptr;
622     }
623 
624     napi_valuetype valueType = napi_undefined;
625     status = napi_typeof(env, args[ARG_0], &valueType);
626     napi_value promise = nullptr;
627     napi_deferred deferred = nullptr;
628     status = napi_create_promise(env, &deferred, &promise);
629     if (status != napi_ok) {
630         ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed");
631         return nullptr;
632     }
633     if (valueType == napi_undefined || valueType == napi_null) {
634         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "param is error");
635         return nullptr;
636     }
637     if (valueType == napi_string) {
638         StringType(env, args[ARG_0], promise, deferred);
639     }
640     if (valueType == napi_object) {
641         ArrayType(env, args[ARG_0], promise, deferred);
642     }
643 
644     return promise;
645 }
646 
StringType(napi_env env,napi_value args,napi_value promise,napi_deferred deferred)647 napi_value TextEmbeddingNapi::StringType(napi_env env, napi_value args, napi_value promise, napi_deferred deferred)
648 {
649     std::string strArg;
650     if (!AipNapiUtils::TransJsToStr(env, args, strArg)) {
651         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "TransJsToStr failed");
652         return nullptr;
653     }
654     if (!GetEmbeddingStringAsyncExecution(env, deferred, strArg)) {
655         ThrowIntelligenceErr(env, INNER_ERROR, "GetEmbeddingStringAsyncExecution failed");
656         return nullptr;
657     }
658     AIP_HILOGD("Exit");
659     return promise;
660 }
661 
GetEmbeddingStringAsyncExecution(napi_env env,napi_deferred deferred,std::string strArg)662 bool TextEmbeddingNapi::GetEmbeddingStringAsyncExecution(napi_env env, napi_deferred deferred, std::string strArg)
663 {
664     AIP_HILOGD("Enter");
665     auto textStringCallbackData = new (std::nothrow) TextStringCallbackData{
666         .asyncWork = nullptr,
667         .deferred = deferred,
668         .strArg = strArg,
669     };
670     if (textStringCallbackData == nullptr) {
671         AIP_HILOGE("new textStringCallbackData error.");
672         return false;
673     }
674 
675     napi_value resourceName;
676     napi_status status = napi_create_string_utf8(env, "textStringEmbedding", NAPI_AUTO_LENGTH, &resourceName);
677     if (status != napi_ok) {
678         AIP_HILOGE("napi_create_string_utf8 failed");
679         delete textStringCallbackData;
680         return false;
681     }
682 
683     status = napi_create_async_work(env, nullptr, resourceName, GetEmbeddingStringExecuteCB,
684         GetEmbeddingStringCompleteCB, static_cast<void *>(textStringCallbackData), &textStringCallbackData->asyncWork);
685     if (status != napi_ok) {
686         AIP_HILOGE("napi_create_async_work failed");
687         delete textStringCallbackData;
688         return false;
689     }
690 
691     status = napi_queue_async_work_with_qos(env, textStringCallbackData->asyncWork, napi_qos_default);
692     if (status != napi_ok) {
693         AIP_HILOGE("napi_queue_async_work_with_qos failed");
694         napi_delete_async_work(env, textStringCallbackData->asyncWork);
695         delete textStringCallbackData;
696         return false;
697     }
698     return true;
699 }
700 
GetEmbeddingStringExecuteCB(napi_env env,void * data)701 void TextEmbeddingNapi::GetEmbeddingStringExecuteCB(napi_env env, void *data)
702 {
703     AIP_HILOGD("Enter");
704     TextStringCallbackData *textStringCallbackData = static_cast<TextStringCallbackData *>(data);
705     std::string strArg = textStringCallbackData->strArg;
706     std::vector<float> result;
707     int32_t ret = textAipCoreManager_->GetTextEmbedding(strArg, result);
708     textStringCallbackData->ret = result;
709     textStringCallbackData->dataRet = ret;
710     AIP_HILOGD("Exit");
711 }
712 
GetEmbeddingStringCompleteCB(napi_env env,napi_status status,void * data)713 void TextEmbeddingNapi::GetEmbeddingStringCompleteCB(napi_env env, napi_status status, void *data)
714 {
715     AIP_HILOGD("Enter");
716     TextStringCallbackData *textStringCallbackData = static_cast<TextStringCallbackData *>(data);
717     napi_value value;
718     auto ret = textStringCallbackData->ret;
719     auto dataRet = textStringCallbackData->dataRet;
720     if (dataRet != ERR_OK) {
721         if (dataRet == DEVICE_EXCEPTION) {
722             ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "GetEmbeddingStringCompleteCB failed", value);
723         } else {
724             ThrowIntelligenceErrByPromise(env, INNER_ERROR, "GetEmbeddingStringCompleteCB failed", value);
725         }
726         napi_reject_deferred(env, textStringCallbackData->deferred, value);
727     } else {
728         status = napi_create_array(env, &value);
729         if (status != napi_ok) {
730             AIP_HILOGE("napi_create_array failed");
731         } else {
732             for (size_t i = 0; i < ret.size(); i++) {
733                 napi_value jsDouble = nullptr;
734                 AipNapiUtils::CreateDoubleData(env, static_cast<double>(ret[i]), &jsDouble);
735                 napi_set_element(env, value, i, jsDouble);
736             }
737             status = napi_resolve_deferred(env, textStringCallbackData->deferred, value);
738             if (status != napi_ok) {
739                 AIP_HILOGE(" napi_resolve_deferred failed");
740             }
741         }
742     }
743 
744     status = napi_delete_async_work(env, textStringCallbackData->asyncWork);
745     if (status != napi_ok) {
746         AIP_HILOGE("napi_delete_async_work failed");
747     }
748     delete textStringCallbackData;
749 }
750 
ValidateAndDealArrayArgs(napi_env env,napi_value args,std::vector<std::string> & strArr)751 bool TextEmbeddingNapi::ValidateAndDealArrayArgs(napi_env env, napi_value args, std::vector<std::string> &strArr)
752 {
753     AIP_HILOGD("Enter");
754     bool isArray = false;
755     napi_status status = napi_is_array(env, args, &isArray);
756     if (status != napi_ok) {
757         AIP_HILOGE("check napi is array failed");
758         return false;
759     }
760 
761     if (!isArray) {
762         AIP_HILOGE("argument is not array");
763         return false;
764     }
765 
766     uint32_t arrayLen = 0;
767     status = napi_get_array_length(env, args, &arrayLen);
768     if (status != napi_ok) {
769         AIP_HILOGE("argument is not array");
770         return false;
771     }
772     if (arrayLen > MAX_STR_PARAM_LEN) {
773         AIP_HILOGE("argument size is too big");
774         return false;
775     }
776 
777     for (uint32_t i = 0; i < arrayLen; ++i) {
778         napi_value element = nullptr;
779         status = napi_get_element(env, args, i, &element);
780         if (status != napi_ok) {
781             AIP_HILOGE("argument get array element failed");
782             return false;
783         }
784         std::string text;
785         if (!AipNapiUtils::TransJsToStr(env, element, text)) {
786             AIP_HILOGE("napi get array element error");
787             strArr.clear();
788             return false;
789         }
790         strArr.push_back(text);
791     }
792     return true;
793 }
794 
ArrayType(napi_env env,napi_value args,napi_value promise,napi_deferred deferred)795 napi_value TextEmbeddingNapi::ArrayType(napi_env env, napi_value args, napi_value promise, napi_deferred deferred)
796 {
797     std::vector<std::string> text;
798     if (!ValidateAndDealArrayArgs(env, args, text)) {
799         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Validate ArrayArgs error!");
800         return nullptr;
801     }
802     if (!GetEmbeddingArrayAsyncExecution(env, deferred, text)) {
803         ThrowIntelligenceErr(env, INNER_ERROR, "GetEmbeddingArrayAsyncExecution failed!");
804         return nullptr;
805     }
806 
807     AIP_HILOGD("exit");
808     return promise;
809 }
810 
GetEmbeddingArrayAsyncExecution(napi_env env,napi_deferred deferred,std::vector<std::string> text)811 bool TextEmbeddingNapi::GetEmbeddingArrayAsyncExecution(napi_env env, napi_deferred deferred,
812     std::vector<std::string> text)
813 {
814     AIP_HILOGD("Enter");
815     auto textArrayCallbackData = new (std::nothrow) TextArrayCallbackData{
816         .asyncWork = nullptr,
817         .deferred = deferred,
818         .text = text,
819     };
820     if (textArrayCallbackData == nullptr) {
821         AIP_HILOGE("new textArrayCallbackData error.");
822         return false;
823     }
824 
825     napi_value resourceName;
826     napi_status status = napi_create_string_utf8(env, "textArrayEmbedding", NAPI_AUTO_LENGTH, &resourceName);
827     if (status != napi_ok) {
828         AIP_HILOGE("napi_create_string_utf8 failed");
829         delete textArrayCallbackData;
830         return false;
831     }
832 
833     status = napi_create_async_work(env, nullptr, resourceName, GetEmbeddingArrayExecuteCB, GetEmbeddingArrayCompleteCB,
834         static_cast<void *>(textArrayCallbackData), &textArrayCallbackData->asyncWork);
835     if (status != napi_ok) {
836         AIP_HILOGE("napi_create_async_work failed");
837         delete textArrayCallbackData;
838         return false;
839     }
840 
841     status = napi_queue_async_work_with_qos(env, textArrayCallbackData->asyncWork, napi_qos_default);
842     if (status != napi_ok) {
843         AIP_HILOGE("napi_queue_async_work_with_qos failed");
844         napi_delete_async_work(env, textArrayCallbackData->asyncWork);
845         delete textArrayCallbackData;
846         return false;
847     }
848     return true;
849 }
850 
851 
GetEmbeddingArrayExecuteCB(napi_env env,void * data)852 void TextEmbeddingNapi::GetEmbeddingArrayExecuteCB(napi_env env, void *data)
853 {
854     AIP_HILOGD("Enter");
855     TextArrayCallbackData *textArrayCallbackData = static_cast<TextArrayCallbackData *>(data);
856     auto text = textArrayCallbackData->text;
857     std::vector<std::vector<float>> result;
858     int32_t ret = textAipCoreManager_->GetTextEmbedding(text, result);
859     textArrayCallbackData->ret = result;
860     textArrayCallbackData->dataRet = ret;
861 }
862 
GetEmbeddingArrayCompleteCB(napi_env env,napi_status status,void * data)863 void TextEmbeddingNapi::GetEmbeddingArrayCompleteCB(napi_env env, napi_status status, void *data)
864 {
865     AIP_HILOGD("Enter");
866     TextArrayCallbackData *textArrayCallbackData = static_cast<TextArrayCallbackData *>(data);
867     napi_value value = nullptr;
868     std::vector<std::vector<float>> ret = textArrayCallbackData->ret;
869     auto dataRet = textArrayCallbackData->dataRet;
870     if (dataRet != ERR_OK) {
871         if (dataRet == DEVICE_EXCEPTION) {
872             ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "GetEmbeddingArrayCompleteCB failed", value);
873         } else {
874             ThrowIntelligenceErrByPromise(env, INNER_ERROR, "GetEmbeddingArrayCompleteCB failed", value);
875         }
876         napi_reject_deferred(env, textArrayCallbackData->deferred, value);
877         status = napi_delete_async_work(env, textArrayCallbackData->asyncWork);
878         if (status != napi_ok) {
879             AIP_HILOGE("napi_delete_async_work failed");
880         }
881         delete textArrayCallbackData;
882         return;
883     }
884 
885     status = napi_create_array(env, &value);
886     if (status != napi_ok) {
887         AIP_HILOGE("napi_create_array failed");
888     } else {
889         for (size_t i = 0; i < ret.size(); ++i) {
890             napi_value res = nullptr;
891             napi_create_array(env, &res);
892             for (size_t j = 0; j < ret[i].size(); ++j) {
893                 napi_value jsDouble = nullptr;
894                 napi_create_double(env, static_cast<double>(ret[i][j]), &jsDouble);
895                 napi_set_element(env, res, j, jsDouble);
896             }
897             napi_set_element(env, value, i, res);
898         }
899         status = napi_resolve_deferred(env, textArrayCallbackData->deferred, value);
900         if (status != napi_ok) {
901             AIP_HILOGE(" napi_resolve_deferred failed");
902         }
903     }
904 
905     status = napi_delete_async_work(env, textArrayCallbackData->asyncWork);
906     if (status != napi_ok) {
907         AIP_HILOGE("napi_delete_async_work failed");
908     }
909     delete textArrayCallbackData;
910 }
911 
912 
LoadModel(napi_env env,napi_callback_info info)913 napi_value TextEmbeddingNapi::LoadModel(napi_env env, napi_callback_info info)
914 {
915     AIP_HILOGD("Enter");
916     size_t argc = ARG_0;
917     napi_value args[ARG_1] = { nullptr };
918     napi_value jsThis = nullptr;
919 
920     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
921     if (status != napi_ok) {
922         AIP_HILOGE("napi_get_cb_info failed");
923         ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed");
924         return nullptr;
925     }
926 
927     if (argc != ARG_0) {
928         AIP_HILOGE("param size error");
929         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "param size error");
930         return nullptr;
931     }
932 
933     napi_value promise = nullptr;
934     napi_deferred deferred = nullptr;
935     status = napi_create_promise(env, &deferred, &promise);
936     if (status != napi_ok) {
937         ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed");
938         return nullptr;
939     }
940 
941     if (!LoadAsyncExecution(env, deferred)) {
942         ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed");
943         return nullptr;
944     }
945     AIP_HILOGD("Exit");
946     return promise;
947 }
948 
LoadAsyncExecution(napi_env env,napi_deferred deferred)949 bool TextEmbeddingNapi::LoadAsyncExecution(napi_env env, napi_deferred deferred)
950 {
951     AIP_HILOGD("Enter");
952     auto loadCallbackData = new (std::nothrow) LoadCallbackData{
953         .asyncWork = nullptr,
954         .deferred = deferred,
955     };
956     if (loadCallbackData == nullptr) {
957         AIP_HILOGE("new loadCallbackData error.");
958         return false;
959     }
960 
961     napi_value resourceName;
962     napi_status status = napi_create_string_utf8(env, "textLoad", NAPI_AUTO_LENGTH, &resourceName);
963     if (status != napi_ok) {
964         AIP_HILOGE("napi_create_string_utf8 failed");
965         delete loadCallbackData;
966         return false;
967     }
968 
969     status = napi_create_async_work(env, nullptr, resourceName, LoadExecuteCB, LoadCompleteCB,
970         static_cast<void *>(loadCallbackData), &loadCallbackData->asyncWork);
971     if (status != napi_ok) {
972         AIP_HILOGE("napi_create_async_work failed");
973         delete loadCallbackData;
974         return false;
975     }
976 
977     status = napi_queue_async_work_with_qos(env, loadCallbackData->asyncWork, napi_qos_default);
978     if (status != napi_ok) {
979         AIP_HILOGE("napi_queue_async_work_with_qos failed");
980         napi_delete_async_work(env, loadCallbackData->asyncWork);
981         delete loadCallbackData;
982         return false;
983     }
984     return true;
985 }
986 
LoadExecuteCB(napi_env env,void * data)987 void TextEmbeddingNapi::LoadExecuteCB(napi_env env, void *data)
988 {
989     AIP_HILOGD("Enter");
990     LoadCallbackData *loadCallbackData = static_cast<LoadCallbackData *>(data);
991     auto ret = textAipCoreManager_->LoadTextModel();
992     loadCallbackData->ret = ret;
993     AIP_HILOGD("Exit");
994 }
995 
LoadCompleteCB(napi_env env,napi_status status,void * data)996 void TextEmbeddingNapi::LoadCompleteCB(napi_env env, napi_status status, void *data)
997 {
998     AIP_HILOGD("Enter");
999     LoadCallbackData *loadCallbackData = static_cast<LoadCallbackData *>(data);
1000     napi_value value = nullptr;
1001     auto ret = loadCallbackData->ret;
1002     if (ret != ERR_OK) {
1003         if (ret == DEVICE_EXCEPTION) {
1004             ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "loadCallbackData failed", value);
1005         } else {
1006             ThrowIntelligenceErrByPromise(env, INNER_ERROR, "loadCallbackData failed", value);
1007         }
1008         napi_reject_deferred(env, loadCallbackData->deferred, value);
1009     } else {
1010         status = napi_get_undefined(env, &value);
1011         if (status != napi_ok) {
1012             AIP_HILOGE(" napi_get_undefined failed");
1013         }
1014         status = napi_resolve_deferred(env, loadCallbackData->deferred, value);
1015         if (status != napi_ok) {
1016             AIP_HILOGE(" napi_resolve_deferred failed");
1017         }
1018     }
1019 
1020     status = napi_delete_async_work(env, loadCallbackData->asyncWork);
1021     if (status != napi_ok) {
1022         AIP_HILOGE("napi_delete_async_work failed");
1023     }
1024     delete loadCallbackData;
1025 }
1026 
1027 
ReleaseModel(napi_env env,napi_callback_info info)1028 napi_value TextEmbeddingNapi::ReleaseModel(napi_env env, napi_callback_info info)
1029 {
1030     AIP_HILOGD("Enter");
1031     size_t argc = ARG_0;
1032     napi_value args[ARG_1] = { nullptr };
1033     napi_value jsThis = nullptr;
1034 
1035     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
1036     if (status != napi_ok) {
1037         AIP_HILOGE("napi_get_cb_info failed");
1038         ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed");
1039         return nullptr;
1040     }
1041 
1042     if (argc != ARG_0) {
1043         ThrowIntelligenceErr(env, PARAM_EXCEPTION, "param size error");
1044         return nullptr;
1045     }
1046 
1047     napi_value promise = nullptr;
1048     napi_deferred deferred = nullptr;
1049     status = napi_create_promise(env, &deferred, &promise);
1050     if (status != napi_ok) {
1051         ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed");
1052         return nullptr;
1053     }
1054 
1055     if (!ReleaseAsyncExecution(env, deferred)) {
1056         ThrowIntelligenceErr(env, INNER_ERROR, "releaseAsyncExecution failed");
1057         return nullptr;
1058     }
1059 
1060     AIP_HILOGD("Exit");
1061     return promise;
1062 }
1063 
ReleaseAsyncExecution(napi_env env,napi_deferred deferred)1064 bool TextEmbeddingNapi::ReleaseAsyncExecution(napi_env env, napi_deferred deferred)
1065 {
1066     AIP_HILOGD("Enter");
1067     auto releaseCallbackData = new (std::nothrow) ReleaseCallbackData{
1068         .asyncWork = nullptr,
1069         .deferred = deferred,
1070     };
1071     if (releaseCallbackData == nullptr) {
1072         AIP_HILOGE("new releaseCallbackData error.");
1073         return false;
1074     }
1075 
1076     napi_value resourceName;
1077     napi_status status = napi_create_string_utf8(env, "textLoad", NAPI_AUTO_LENGTH, &resourceName);
1078     if (status != napi_ok) {
1079         AIP_HILOGE("napi_create_string_utf8 failed");
1080         delete releaseCallbackData;
1081         return false;
1082     }
1083 
1084     status = napi_create_async_work(env, nullptr, resourceName, ReleaseExecuteCB, ReleaseCompleteCB,
1085         static_cast<void *>(releaseCallbackData), &releaseCallbackData->asyncWork);
1086     if (status != napi_ok) {
1087         AIP_HILOGE("napi_create_async_work failed");
1088         delete releaseCallbackData;
1089         return false;
1090     }
1091 
1092     status = napi_queue_async_work_with_qos(env, releaseCallbackData->asyncWork, napi_qos_default);
1093     if (status != napi_ok) {
1094         AIP_HILOGE("napi_queue_async_work_with_qos failed");
1095         napi_delete_async_work(env, releaseCallbackData->asyncWork);
1096         delete releaseCallbackData;
1097         return false;
1098     }
1099     return true;
1100 }
ReleaseExecuteCB(napi_env env,void * data)1101 void TextEmbeddingNapi::ReleaseExecuteCB(napi_env env, void *data)
1102 {
1103     AIP_HILOGD("Enter");
1104     ReleaseCallbackData *releaseCallbackData = static_cast<ReleaseCallbackData *>(data);
1105     auto ret = textAipCoreManager_->ReleaseTextModel();
1106     releaseCallbackData->ret = ret;
1107     AIP_HILOGD("Exit");
1108 }
1109 
ReleaseCompleteCB(napi_env env,napi_status status,void * data)1110 void TextEmbeddingNapi::ReleaseCompleteCB(napi_env env, napi_status status, void *data)
1111 {
1112     AIP_HILOGD("Enter");
1113     ReleaseCallbackData *releaseCallbackData = static_cast<ReleaseCallbackData *>(data);
1114     napi_value value = nullptr;
1115     auto ret = releaseCallbackData->ret;
1116     if (ret != ERR_OK) {
1117         if (ret == DEVICE_EXCEPTION) {
1118             ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "ReleaseCompleteCB failed", value);
1119         } else {
1120             ThrowIntelligenceErrByPromise(env, INNER_ERROR, "ReleaseCompleteCB failed", value);
1121         }
1122         napi_reject_deferred(env, releaseCallbackData->deferred, value);
1123     } else {
1124         status = napi_get_undefined(env, &value);
1125         if (status != napi_ok) {
1126             AIP_HILOGE(" napi_get_undefined failed");
1127         }
1128         status = napi_resolve_deferred(env, releaseCallbackData->deferred, value);
1129         if (status != napi_ok) {
1130             AIP_HILOGE(" napi_resolve_deferred failed");
1131         }
1132     }
1133 
1134     status = napi_delete_async_work(env, releaseCallbackData->asyncWork);
1135     if (status != napi_ok) {
1136         AIP_HILOGE("napi_delete_async_work failed");
1137     }
1138     delete releaseCallbackData;
1139 }
1140 } // namespace DataIntelligence
1141 } // namespace OHOS
1142