• 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 "boomerang_napi.h"
17 
18 #include <js_native_api.h>
19 
20 #include "napi/native_api.h"
21 #include "napi/native_node_api.h"
22 #include "image_pixel_map_napi.h"
23 #include "image_pixel_map_mdk.h"
24 #include "pixel_map_napi.h"
25 
26 #include "boomerang_manager.h"
27 #include "boomerang_napi_error.h"
28 #include "devicestatus_client.h"
29 #include "devicestatus_define.h"
30 #include "napi_constants.h"
31 #include "util_napi_error.h"
32 
33 #undef LOG_TAG
34 #define LOG_TAG "BoomerangNapi"
35 
36 namespace OHOS {
37 namespace Msdp {
38 namespace DeviceStatus {
39 namespace {
40 constexpr size_t ARG_0{0};
41 constexpr size_t ARG_1{1};
42 constexpr size_t ARG_2{2};
43 constexpr size_t ARG_3{3};
44 inline constexpr size_t MAX_STRING_LEN{1024};
45 const std::vector<std::string> vecDeviceStatusValue{"VALUE_ENTER", "VALUE_EXIT"};
46 thread_local BoomerangNapi *g_obj = nullptr;
47 constexpr int32_t VALIDATA_ON_PARAM = 1;
48 constexpr int32_t VALIDATA_OFF_PARAM = 2;
49 constexpr int32_t MAX_LENGTH = 128;
50 constexpr int32_t MIN_IMAGE_PIXEL = 1080;
51 constexpr char const *URL_CHARACTERES =
52     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=|%";
53 }  // namespace
54 std::map<int32_t, sptr<IRemoteBoomerangCallback>> BoomerangNapi::callbacks_;
55 napi_ref BoomerangNapi::boomerangValueRef_ = nullptr;
56 
OnScreenshotResult(const BoomerangData & screenshotData)57 void BoomerangCallback::OnScreenshotResult(const BoomerangData &screenshotData)
58 {
59     CALL_DEBUG_ENTER;
60     std::lock_guard<std::mutex> guard(mutex_);
61     data_ = screenshotData;
62     auto task = [this]() {
63         FI_HILOGI("Execute lamdba");
64         EmitOnEvent(&this->data_);
65     };
66     if (napi_status::napi_ok != napi_send_event(env_, task, napi_eprio_immediate)) {
67         FI_HILOGE("Failed to SendEvent");
68     }
69 }
70 
OnNotifyMetadata(const std::string & metadata)71 void BoomerangCallback::OnNotifyMetadata(const std::string &metadata)
72 {
73     CALL_DEBUG_ENTER;
74     std::lock_guard<std::mutex> guard(mutex_);
75     metadata_ = metadata;
76     auto task = [this]() {
77         FI_HILOGI("Execute lamdba");
78         EmitOnMetadata(this->env_, this->metadata_, this->deferred_);
79     };
80     if (napi_status::napi_ok != napi_send_event(env_, task, napi_eprio_immediate)) {
81         FI_HILOGE("Failed to SendEvent");
82     }
83 }
84 
OnEncodeImageResult(std::shared_ptr<Media::PixelMap> pixelMap)85 void BoomerangCallback::OnEncodeImageResult(std::shared_ptr<Media::PixelMap> pixelMap)
86 {
87     CALL_DEBUG_ENTER;
88     std::lock_guard<std::mutex> guard(mutex_);
89     pixelMap_ = pixelMap;
90     auto task = [this]() {
91         FI_HILOGI("Execute lamdba");
92         EmitOnEncodeImage(this->env_, this->pixelMap_, this->deferred_);
93     };
94     if (napi_status::napi_ok != napi_send_event(env_, task, napi_eprio_immediate)) {
95         FI_HILOGE("Failed to SendEvent");
96     }
97 }
98 
EmitOnEvent(BoomerangData * data)99 void BoomerangCallback::EmitOnEvent(BoomerangData *data)
100 {
101     BoomerangNapi *boomerangNapi = BoomerangNapi::GetDeviceStatusNapi();
102     CHKPV(boomerangNapi);
103     int32_t type = static_cast<int32_t>(data->type);
104     int32_t status = static_cast<int32_t>(data->status);
105     boomerangNapi->OnScreenshot(type, status, false);
106 }
107 
EmitOnMetadata(napi_env env,std::string metadata,napi_deferred deferred)108 void BoomerangCallback::EmitOnMetadata(napi_env env, std::string metadata, napi_deferred deferred)
109 {
110     BoomerangNapi *boomerangNapi = BoomerangNapi::GetDeviceStatusNapi();
111     CHKPV(boomerangNapi);
112     boomerangNapi->OnMetadata(env, metadata, false, deferred);
113 }
114 
EmitOnEncodeImage(napi_env env,std::shared_ptr<Media::PixelMap> pixelMap,napi_deferred deferred)115 void BoomerangCallback::EmitOnEncodeImage(napi_env env, std::shared_ptr<Media::PixelMap> pixelMap,
116     napi_deferred deferred)
117 {
118     if (env == nullptr || pixelMap == nullptr) {
119         FI_HILOGI("EmitOnEncodeImage pixelMap is nullptr");
120         return;
121     }
122     BoomerangNapi *boomerangNapi = BoomerangNapi::GetDeviceStatusNapi();
123     CHKPV(boomerangNapi);
124     boomerangNapi->OnEncodeImage(env, pixelMap, deferred);
125 }
126 
OnScreenshot(int32_t type,int32_t status,bool isOnce)127 void BoomerangNapi::OnScreenshot(int32_t type, int32_t status, bool isOnce)
128 {
129     CALL_DEBUG_ENTER;
130     OnEvent(type, ARG_1, status, isOnce);
131 }
132 
OnMetadata(napi_env env,std::string metadata,bool isOnce,napi_deferred deferred)133 void BoomerangNapi::OnMetadata(napi_env env, std::string metadata, bool isOnce, napi_deferred deferred)
134 {
135     CALL_DEBUG_ENTER;
136     auto processContext = [](napi_env env, napi_deferred deferred, const std::string &metadata) -> void {
137         if (env == nullptr || deferred == nullptr) {
138             return;
139         }
140 
141         napi_value result;
142         napi_status status = napi_create_string_utf8(env, metadata.c_str(), NAPI_AUTO_LENGTH, &result);
143         if (status != napi_ok) {
144             FI_HILOGE("Failed to create string utf8");
145             return;
146         }
147 
148         status = napi_resolve_deferred(env, deferred, result);
149         if (status != napi_ok) {
150             FI_HILOGE("Failed to resolve deferred");
151             return;
152         }
153     };
154 
155     processContext(env, deferred, metadata);
156 }
157 
OnEncodeImage(napi_env env,std::shared_ptr<Media::PixelMap> pixelMap,napi_deferred deferred)158 void BoomerangNapi::OnEncodeImage(napi_env env, std::shared_ptr<Media::PixelMap> pixelMap, napi_deferred deferred)
159 {
160     CALL_DEBUG_ENTER;
161     std::lock_guard<std::mutex> guard(encodeMutex_);
162     CHKPV(pixelMap);
163     CHKPV(deferred);
164 
165     napi_value pixelMapNapi = Media::PixelMapNapi::CreatePixelMap(env, pixelMap);
166     CHKPV(pixelMapNapi);
167     napi_resolve_deferred(env, deferred, pixelMapNapi);
168 }
169 
GetDeviceStatusNapi()170 BoomerangNapi *BoomerangNapi::GetDeviceStatusNapi()
171 {
172     return g_obj;
173 }
174 
BoomerangNapi(napi_env env)175 BoomerangNapi::BoomerangNapi(napi_env env) : BoomerangEvent(env)
176 {
177     env_ = env;
178     boomerangValueRef_ = nullptr;
179     DeviceStatusClient::GetInstance().RegisterDeathListener([this] {
180         FI_HILOGI("Receive death notification");
181         callbacks_.clear();
182         ClearEventMap();
183     });
184 }
185 
~BoomerangNapi()186 BoomerangNapi::~BoomerangNapi()
187 {
188     if (boomerangValueRef_ != nullptr) {
189         napi_delete_reference(env_, boomerangValueRef_);
190     }
191 }
192 
Register(napi_env env,napi_callback_info info)193 napi_value BoomerangNapi::Register(napi_env env, napi_callback_info info)
194 {
195     CALL_INFO_TRACE;
196     std::lock_guard<std::mutex> guard(mutex_);
197     size_t argc = 3;
198     napi_value argv[3] = {nullptr};
199     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
200     if (argc < ARG_2) {
201         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
202         return nullptr;
203     }
204     if (!CheckArguments(env, info, VALIDATA_ON_PARAM)) {
205         ThrowErr(env, PARAM_ERROR, "Failed to get on arguments");
206         return nullptr;
207     }
208 
209     char eventType[MAX_STRING_LEN] = {0};
210     size_t eventLength = 0;
211     CHKRP(napi_get_value_string_utf8(env, argv[0], eventType, sizeof(eventType), &eventLength), CREATE_STRING_UTF8);
212 
213     int32_t type = ConvertTypeToInt(eventType);
214 
215     char bundleName[MAX_STRING_LEN] = {0};
216     size_t strLength = 0;
217     CHKRP(napi_get_value_string_utf8(env, argv[1], bundleName, sizeof(bundleName), &strLength), CREATE_STRING_UTF8);
218     return SubscribeMeatadataCallback(env, info, argv[ARG_2], type, bundleName);
219 }
220 
SubscribeMeatadataCallback(napi_env env,napi_callback_info info,napi_value handler,int32_t type,std::string bundleName)221 napi_value BoomerangNapi::SubscribeMeatadataCallback(
222     napi_env env, napi_callback_info info, napi_value handler, int32_t type, std::string bundleName)
223 {
224     CALL_DEBUG_ENTER;
225     if (!InitNapiObject(env, info)) {
226         return nullptr;
227     }
228     if (!g_obj->On(type, handler, false)) {
229         FI_HILOGE("type:%{public}d already exists", type);
230         return nullptr;
231     }
232 
233     auto callbackIter = callbacks_.find(type);
234     if (callbackIter != callbacks_.end()) {
235         FI_HILOGD("Callback exists");
236         return nullptr;
237     }
238 
239     sptr<IRemoteBoomerangCallback> callback = new (std::nothrow) BoomerangCallback(env, nullptr);
240     CHKPP(callback);
241     int32_t subscribeRet =
242         BoomerangManager::GetInstance().SubscribeCallback(static_cast<BoomerangType>(type), bundleName, callback);
243     if (subscribeRet != RET_OK) {
244         ThrowErr(env,
245             SUBSCRIBE_FAILED,
246             "Subscribe Failed. Possible causes: 1. Abnormal system capability; 2. IPC communication abnormality; 3. "
247             "Algorithm loading exception.");
248         return nullptr;
249     }
250     auto ret = callbacks_.insert(std::pair<int32_t, sptr<IRemoteBoomerangCallback>>(type, callback));
251     if (!ret.second) {
252         FI_HILOGE("Failed to insert");
253     }
254     return nullptr;
255 }
256 
NotifyMetadataBindingEvent(napi_env env,napi_callback_info info)257 napi_value BoomerangNapi::NotifyMetadataBindingEvent(napi_env env, napi_callback_info info)
258 {
259     CALL_INFO_TRACE;
260     std::lock_guard<std::mutex> guard(mutex_);
261     size_t argc = 1;
262     napi_value argv[1] = {nullptr};
263     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
264     if (argc < 1) {
265         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
266         return nullptr;
267     }
268     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
269         THROWERR(env, COMMON_PARAMETER_ERROR, "type", "string");
270         return nullptr;
271     }
272 
273     char bundleName[MAX_STRING_LEN] = {0};
274     size_t strLength = 0;
275     CHKRP(napi_get_value_string_utf8(env, argv[0], bundleName, sizeof(bundleName), &strLength), CREATE_STRING_UTF8);
276 
277     if (!InitNapiObject(env, info)) {
278         THROWERR_CUSTOM(env, HANDLER_FAILD, "Internal handling failed. File creation failed.");
279         return nullptr;
280     }
281 
282     auto asyncContext = new (std::nothrow) AsyncContext();
283     CHKPP(asyncContext);
284     asyncContext->env = env;
285     napi_value promise = nullptr;
286     napi_deferred deferred = nullptr;
287     napi_status status = napi_create_promise(env, &deferred, &promise);
288     if (status != napi_ok) {
289         THROWERR_CUSTOM(env, HANDLER_FAILD, "Internal handling failed. File creation failed.");
290         return nullptr;
291     }
292 
293     asyncContext->deferred = deferred;
294     sptr<IRemoteBoomerangCallback> callback = new (std::nothrow) BoomerangCallback(env, deferred);
295     CHKPP(callback);
296     bool result = CreateMetadataExecution(env, asyncContext, bundleName, callback);
297     if (!result) {
298         FI_HILOGE("notify metadataBinding event error by Create execution");
299         delete asyncContext;
300     }
301     return promise;
302 }
303 
SubmitMetadata(napi_env env,napi_callback_info info)304 napi_value BoomerangNapi::SubmitMetadata(napi_env env, napi_callback_info info)
305 {
306     CALL_INFO_TRACE;
307     std::lock_guard<std::mutex> guard(mutex_);
308     size_t argc = 1;
309     napi_value argv[1] = {nullptr};
310     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
311     if (argc < 1) {
312         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
313         return nullptr;
314     }
315     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
316         THROWERR(env, COMMON_PARAMETER_ERROR, "type", "string");
317         return nullptr;
318     }
319 
320     char metadata[MAX_STRING_LEN] = {0};
321     size_t strLength = 0;
322     CHKRP(napi_get_value_string_utf8(env, argv[0], metadata, sizeof(metadata), &strLength), CREATE_STRING_UTF8);
323 
324     int32_t result = BoomerangManager::GetInstance().SubmitMetadata(metadata);
325     if (result != RET_OK) {
326         ThrowErr(env, HANDLER_FAILD, "Internal handling failed. File creation failed.");
327     }
328     return nullptr;
329 }
330 
BoomerangEncodeImage(napi_env env,napi_callback_info info)331 napi_value BoomerangNapi::BoomerangEncodeImage(napi_env env, napi_callback_info info)
332 {
333     CALL_INFO_TRACE;
334     std::lock_guard<std::mutex> guard(encodeMutex_);
335     size_t argc = 2;
336     napi_value argv[2] = {nullptr};
337     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
338     if (argc < ARG_2) {
339         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
340         return nullptr;
341     }
342     if (UtilNapi::TypeOf(env, argv[0], napi_undefined) || UtilNapi::TypeOf(env, argv[0], napi_null)) {
343         THROWERR(env, COMMON_PARAMETER_ERROR, "data", "pixelmap");
344         return nullptr;
345     }
346     if (!UtilNapi::TypeOf(env, argv[1], napi_string)) {
347         THROWERR(env, COMMON_PARAMETER_ERROR, "type", "string");
348         return nullptr;
349     }
350 
351     std::shared_ptr<Media::PixelMap> pixelMap = Media::PixelMapNapi::GetPixelMap(env, argv[0]);
352     CHKPP(pixelMap);
353 
354     char metadata[MAX_STRING_LEN] = {0};
355     size_t strLength = 0;
356     CHKRP(napi_get_value_string_utf8(env, argv[1], metadata, sizeof(metadata), &strLength), CREATE_STRING_UTF8);
357 
358     if (!ValidateEncodeParam(metadata, pixelMap)) {
359         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "The parameters do not meet the requirements");
360         return nullptr;
361     }
362     if (!InitNapiObject(env, info)) {
363         THROWERR_CUSTOM(env, HANDLER_FAILD, "Internal handling failed. File creation failed.");
364         return nullptr;
365     }
366     return HandleBoomerangEncodeImage(env, pixelMap, metadata);
367 }
368 
DecodeImage(napi_env env,napi_callback_info info)369 napi_value BoomerangNapi::DecodeImage(napi_env env, napi_callback_info info)
370 {
371     CALL_INFO_TRACE;
372     std::lock_guard<std::mutex> guard(mutex_);
373     size_t argc = 1;
374     napi_value argv[1] = {nullptr};
375     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
376     if (argc < 1) {
377         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Wrong number of parameters");
378         return nullptr;
379     }
380     if (UtilNapi::TypeOf(env, argv[0], napi_undefined) || UtilNapi::TypeOf(env, argv[0], napi_null)) {
381         THROWERR(env, COMMON_PARAMETER_ERROR, "data", "pixelmap");
382         return nullptr;
383     }
384 
385     std::shared_ptr<Media::PixelMap> pixelMap = Media::PixelMapNapi::GetPixelMap(env, argv[0]);
386     CHKPP(pixelMap);
387     if (!InitNapiObject(env, info)) {
388         THROWERR_CUSTOM(env, HANDLER_FAILD, "Internal handling failed. File creation failed.");
389         return nullptr;
390     }
391 
392     auto asyncContext = new (std::nothrow) AsyncContext();
393     CHKPP(asyncContext);
394     napi_value promise = nullptr;
395     napi_deferred deferred = nullptr;
396     napi_status status = napi_create_promise(env, &deferred, &promise);
397     if (status != napi_ok) {
398         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "decode image error by create promise");
399         return nullptr;
400     }
401 
402     asyncContext->deferred = deferred;
403     asyncContext->env = env;
404     sptr<IRemoteBoomerangCallback> callback = new (std::nothrow) BoomerangCallback(env, deferred);
405     CHKPP(callback);
406     bool result = CreateDecodeImageExecution(env, asyncContext, pixelMap, callback);
407     if (!result) {
408         FI_HILOGE("decode image error by Create execution");
409         delete asyncContext;
410     }
411     return promise;
412 }
413 
UnRegister(napi_env env,napi_callback_info info)414 napi_value BoomerangNapi::UnRegister(napi_env env, napi_callback_info info)
415 {
416     CALL_INFO_TRACE;
417     std::lock_guard<std::mutex> guard(mutex_);
418     size_t argc = 3;
419     napi_value argv[3] = {nullptr};
420     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
421 
422     if (!CheckArguments(env, info, VALIDATA_OFF_PARAM)) {
423         ThrowErr(env, PARAM_ERROR, "failed to get on arguments");
424         return nullptr;
425     }
426     char eventType[MAX_STRING_LEN] = {0};
427     size_t eventLength = 0;
428     CHKRP(napi_get_value_string_utf8(env, argv[0], eventType, sizeof(eventType), &eventLength), CREATE_STRING_UTF8);
429 
430     int32_t type = ConvertTypeToInt(eventType);
431 
432     char bundleName[MAX_STRING_LEN] = {0};
433     size_t strLength = 0;
434     CHKRP(napi_get_value_string_utf8(env, argv[1], bundleName, sizeof(bundleName), &strLength), CREATE_STRING_UTF8);
435 
436     CHKPP(g_obj);
437     if (!g_obj->Off(type)) {
438         FI_HILOGE("Not ready to unsubscribe for type:%{public}d", type);
439         return nullptr;
440     }
441     auto callbackIter = callbacks_.find(type);
442     if (callbackIter == callbacks_.end()) {
443         NAPI_ASSERT(env, false, "No existed callback");
444         return nullptr;
445     }
446     int32_t unsubscribeRet = BoomerangManager::GetInstance().UnsubscribeCallback(
447         static_cast<BoomerangType>(type), bundleName, callbackIter->second);
448     if (unsubscribeRet != RET_OK) {
449         ThrowErr(env,
450             UNSUBSCRIBE_FAILED,
451             "Unsubscribe Failed. Possible causes: 1. Abnormal system capability; 2. IPC communication abnormality.");
452     }
453     callbacks_.erase(type);
454     return nullptr;
455 }
456 
ValidateEncodeParam(const std::string & metadata,std::shared_ptr<Media::PixelMap> & pixelMap)457 bool BoomerangNapi::ValidateEncodeParam(const std::string& metadata, std::shared_ptr<Media::PixelMap>& pixelMap)
458 {
459     if (metadata.empty() || metadata.size() > MAX_LENGTH) {
460         FI_HILOGE("The metadata data size does not comply with the specifications");
461         return false;
462     }
463 
464     size_t pos = metadata.find_first_not_of(URL_CHARACTERES);
465     if (pos != std::string::npos) {
466         FI_HILOGE("There are illegal characters present in metadata");
467         return false;
468     }
469 
470     if (pixelMap->GetWidth() < MIN_IMAGE_PIXEL || pixelMap->GetHeight() < MIN_IMAGE_PIXEL) {
471         FI_HILOGE("The image size does not meet the requirements");
472         return false;
473     }
474     return true;
475 }
476 
HandleBoomerangEncodeImage(napi_env env,std::shared_ptr<Media::PixelMap> & pixelMap,const std::string & metadata)477 napi_value BoomerangNapi::HandleBoomerangEncodeImage(napi_env env, std::shared_ptr<Media::PixelMap>& pixelMap,
478     const std::string& metadata)
479 {
480     napi_value promise = nullptr;
481     napi_deferred deferred = nullptr;
482     napi_status status = napi_create_promise(env, &deferred, &promise);
483     if (status != napi_ok) {
484         THROWERR_CUSTOM(env, HANDLER_FAILD, "Internal handling failed. File creation failed.");
485         return nullptr;
486     }
487 
488     sptr<IRemoteBoomerangCallback> callback = new (std::nothrow) BoomerangCallback(env, deferred);
489     CHKPP(callback);
490     auto asyncContext = new (std::nothrow) AsyncContext();
491     CHKPP(asyncContext);
492     asyncContext->env = env;
493     asyncContext->deferred = deferred;
494     bool result = CreateEncodeImageExecution(env, asyncContext, metadata, pixelMap, callback);
495     if (!result) {
496         FI_HILOGE("encode image error by Create execution");
497         delete asyncContext;
498         return nullptr;
499     }
500     return promise;
501 }
502 
InitNapiObject(napi_env env,napi_callback_info info)503 bool BoomerangNapi::InitNapiObject(napi_env env, napi_callback_info info)
504 {
505     if (g_obj == nullptr) {
506         g_obj = new (std::nothrow) BoomerangNapi(env);
507         CHKPF(g_obj);
508         FI_HILOGD("Didn't find object, so created it");
509     }
510     napi_value thisArg = nullptr;
511     void *data = nullptr;
512     napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
513     if (status != napi_ok) {
514         FI_HILOGE("Failed to get_cb_info item");
515         delete g_obj;
516         g_obj = nullptr;
517         return false;
518     }
519     status = napi_wrap(
520         env,
521         thisArg,
522         reinterpret_cast<void *>(g_obj),
523         [](napi_env env, void *data, void *hint) {
524             (void)env;
525             (void)hint;
526             CHKPV(data);
527             BoomerangNapi *deviceStatus = static_cast<BoomerangNapi *>(data);
528             delete deviceStatus;
529             g_obj = nullptr;
530         },
531         nullptr,
532         nullptr);
533     if (status != napi_ok) {
534         FI_HILOGE("napi_wrap failed");
535         delete g_obj;
536         g_obj = nullptr;
537         return false;
538     }
539     return true;
540 }
541 
CheckArguments(napi_env env,napi_callback_info info,int32_t validataType)542 bool BoomerangNapi::CheckArguments(napi_env env, napi_callback_info info, int32_t validataType)
543 {
544     CALL_DEBUG_ENTER;
545     int32_t arr[ARG_3] = {0};
546     size_t argc = ARG_3;
547     napi_value args[ARG_3] = {nullptr};
548     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
549     if (status != napi_ok) {
550         FI_HILOGE("Failed to get_cb_info");
551         return false;
552     }
553     for (size_t i = 0; i < ARG_3; i++) {
554         napi_valuetype valueType = napi_undefined;
555         status = napi_typeof(env, args[i], &valueType);
556         if (status != napi_ok) {
557             FI_HILOGE("Failed to get valueType");
558             return false;
559         }
560         FI_HILOGD("valueType:%{public}d", valueType);
561         arr[i] = valueType;
562     }
563     if (validataType == VALIDATA_ON_PARAM) {
564         if (arr[ARG_0] != napi_string || arr[ARG_1] != napi_string || arr[ARG_2] != napi_function) {
565             FI_HILOGE("Failed to get arguments");
566             return false;
567         }
568     }
569     if (validataType == VALIDATA_OFF_PARAM) {
570         if (arr[ARG_0] != napi_string || arr[ARG_1] != napi_string) {
571             FI_HILOGE("Failed to get arguments");
572             return false;
573         }
574     }
575     return true;
576 }
577 
CreateMetadataExecution(napi_env env,AsyncContext * asyncContext,std::string bundleName,sptr<IRemoteBoomerangCallback> callback)578 bool BoomerangNapi::CreateMetadataExecution(napi_env env, AsyncContext *asyncContext,
579     std::string bundleName, sptr<IRemoteBoomerangCallback> callback)
580 {
581     if (asyncContext == nullptr || callback == nullptr) {
582         FI_HILOGE("not init notify metadata asyncContext");
583         return false;
584     }
585     asyncContext->callback = callback;
586     asyncContext->bundleName = bundleName;
587     napi_value resource = nullptr;
588     std::string funcName = "NotifyMetadata";
589     napi_create_string_utf8(env, "NotifyMetadata", funcName.length(), &resource);
590     CHKRF(napi_create_async_work(env, nullptr, resource, NotifyMetadataExecuteCB, NotifyMetadataCompleteCB,
591         static_cast<void*>(asyncContext), &asyncContext->work), CREAT_ASYNC_WORK);
592     CHKRF(napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default), QUEUE_ASYNC_WORK);
593     return true;
594 }
595 
CreateEncodeImageExecution(napi_env env,AsyncContext * asyncContext,std::string metadata,std::shared_ptr<Media::PixelMap> pixelMap,sptr<IRemoteBoomerangCallback> callback)596 bool BoomerangNapi::CreateEncodeImageExecution(napi_env env, AsyncContext *asyncContext,
597     std::string metadata, std::shared_ptr<Media::PixelMap> pixelMap, sptr<IRemoteBoomerangCallback> callback)
598 {
599     if (asyncContext == nullptr) {
600         FI_HILOGE("not init encode image asyncContext");
601         return false;
602     }
603     asyncContext->callback = callback;
604     asyncContext->metadata = metadata;
605     asyncContext->pixelMap = pixelMap;
606     napi_value resource = nullptr;
607     std::string funcName = "EncodeImage";
608     napi_create_string_utf8(env, "EncodeImage", funcName.length(), &resource);
609     CHKRF(napi_create_async_work(env, nullptr, resource, EncodeImageExecuteCB, EncodeImageCompleteCB,
610         static_cast<void*>(asyncContext), &asyncContext->work), CREAT_ASYNC_WORK);
611     CHKRF(napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default), QUEUE_ASYNC_WORK);
612     return true;
613 }
614 
CreateDecodeImageExecution(napi_env env,AsyncContext * asyncContext,std::shared_ptr<Media::PixelMap> pixelMap,sptr<IRemoteBoomerangCallback> callback)615 bool BoomerangNapi::CreateDecodeImageExecution(napi_env env, AsyncContext *asyncContext,
616     std::shared_ptr<Media::PixelMap> pixelMap, sptr<IRemoteBoomerangCallback> callback)
617 {
618     if (env == nullptr || asyncContext == nullptr) {
619         FI_HILOGE("not init env or encode image asyncContext");
620         return false;
621     }
622     asyncContext->callback = callback;
623     asyncContext->pixelMap = pixelMap;
624     napi_value resource = nullptr;
625     std::string funcName = "DecodeImage";
626     napi_create_string_utf8(env, "DecodeImage", funcName.length(), &resource);
627     CHKRF(napi_create_async_work(env, nullptr, resource, DecodeImageExecuteCB, DecodeImageCompleteCB,
628         static_cast<void*>(asyncContext), &asyncContext->work), CREAT_ASYNC_WORK);
629     CHKRF(napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_default), QUEUE_ASYNC_WORK);
630     return true;
631 }
632 
NotifyMetadataExecuteCB(napi_env env,void * data)633 void BoomerangNapi::NotifyMetadataExecuteCB(napi_env env, void* data)
634 {
635     std::lock_guard<std::mutex> guard(mutex_);
636     auto innerAsyncContext = static_cast<AsyncContext*>(data);
637     std::string bundleName = static_cast<std::string>(innerAsyncContext->bundleName);
638     sptr<IRemoteBoomerangCallback> callback = static_cast<sptr<IRemoteBoomerangCallback>>(innerAsyncContext->callback);
639     if (bundleName.empty() || callback == nullptr) {
640         FI_HILOGE("bundleName or callback is error");
641         return;
642     }
643     innerAsyncContext->result = BoomerangManager::GetInstance().NotifyMetadataBindingEvent(bundleName, callback);
644 }
645 
NotifyMetadataCompleteCB(napi_env env,napi_status status,void * data)646 void BoomerangNapi::NotifyMetadataCompleteCB(napi_env env, napi_status status, void* data)
647 {
648     std::lock_guard<std::mutex> guard(mutex_);
649     auto outerAsyncContext = static_cast<AsyncContext*>(data);
650     int32_t result = static_cast<int32_t>(outerAsyncContext->result);
651     if (result != RET_OK) {
652         ProcessErrorResult(env, result, HANDLER_FAILD, outerAsyncContext);
653     }
654     napi_delete_async_work(outerAsyncContext->env, outerAsyncContext->work);
655     delete outerAsyncContext;
656     outerAsyncContext = nullptr;
657 }
658 
EncodeImageExecuteCB(napi_env env,void * data)659 void BoomerangNapi::EncodeImageExecuteCB(napi_env env, void* data)
660 {
661     std::lock_guard<std::mutex> guard(encodeMutex_);
662     auto  innerAsyncContext = static_cast<AsyncContext*>(data);
663     std::string metadata = static_cast<std::string>(innerAsyncContext->metadata);
664     sptr<IRemoteBoomerangCallback> callback = static_cast<sptr<IRemoteBoomerangCallback>>(innerAsyncContext->callback);
665     auto pixelMap = static_cast<std::shared_ptr<Media::PixelMap>>(innerAsyncContext->pixelMap);
666     if (metadata.empty() || callback == nullptr || pixelMap == nullptr) {
667         FI_HILOGE("bundleName or callback or pixelMap is error");
668         return;
669     }
670     innerAsyncContext->result = BoomerangManager::GetInstance().BoomerangEncodeImage(pixelMap, metadata, callback);
671 }
672 
EncodeImageCompleteCB(napi_env env,napi_status status,void * data)673 void BoomerangNapi::EncodeImageCompleteCB(napi_env env, napi_status status, void* data)
674 {
675     std::lock_guard<std::mutex> guard(encodeMutex_);
676     auto outerAsyncContext = static_cast<AsyncContext*>(data);
677     int32_t result = static_cast<int32_t>(outerAsyncContext->result);
678     ProcessErrorResult(env, result, ENCODE_FAILED, outerAsyncContext);
679     napi_delete_async_work(outerAsyncContext->env, outerAsyncContext->work);
680     delete outerAsyncContext;
681     outerAsyncContext = nullptr;
682 }
683 
DecodeImageExecuteCB(napi_env env,void * data)684 void BoomerangNapi::DecodeImageExecuteCB(napi_env env, void* data)
685 {
686     AsyncContext*  innerAsyncContext = static_cast<AsyncContext*>(data);
687     auto pixelMap = static_cast<std::shared_ptr<Media::PixelMap>>(innerAsyncContext->pixelMap);
688     sptr<IRemoteBoomerangCallback> callback = static_cast<sptr<IRemoteBoomerangCallback>>(innerAsyncContext->callback);
689     if (pixelMap == nullptr || callback == nullptr) {
690         FI_HILOGE("callback or pixelMap is error");
691         return;
692     }
693     innerAsyncContext->result = BoomerangManager::GetInstance().BoomerangDecodeImage(pixelMap, callback);
694 }
695 
DecodeImageCompleteCB(napi_env env,napi_status status,void * data)696 void BoomerangNapi::DecodeImageCompleteCB(napi_env env, napi_status status, void* data)
697 {
698     std::lock_guard<std::mutex> guard(encodeMutex_);
699     auto outerAsyncContext = static_cast<AsyncContext*>(data);
700     int32_t result = static_cast<int32_t>(outerAsyncContext->result);
701     if (result != RET_OK) {
702         ProcessErrorResult(env, result, DECODE_FAILED, outerAsyncContext);
703     }
704     napi_delete_async_work(outerAsyncContext->env, outerAsyncContext->work);
705     delete outerAsyncContext;
706     outerAsyncContext = nullptr;
707 }
708 
IsSameHandle(napi_env env,napi_value handle,napi_ref ref)709 bool BoomerangNapi::IsSameHandle(napi_env env, napi_value handle, napi_ref ref)
710 {
711     CALL_INFO_TRACE;
712     napi_handle_scope scope = nullptr;
713     napi_open_handle_scope(env, &scope);
714     CHKPF(scope);
715     napi_value handlerTemp = nullptr;
716     CHKRF_SCOPE(env, napi_get_reference_value(env, ref, &handlerTemp), GET_REFERENCE_VALUE, scope);
717     bool isEqual = false;
718     CHKRF_SCOPE(env, napi_strict_equals(env, handle, handlerTemp, &isEqual), STRICT_EQUALS, scope);
719     napi_close_handle_scope(env, scope);
720     return isEqual;
721 }
722 
ConvertTypeToInt(const std::string & type)723 int32_t BoomerangNapi::ConvertTypeToInt(const std::string &type)
724 {
725     if (type == "operationSubmitMetadata") {
726         return BoomerangType::BOOMERANG_TYPE_BOOMERANG;
727     } else {
728         return BoomerangType::BOOMERANG_TYPE_INVALID;
729     }
730 }
731 
ProcessErrorResult(napi_env env,int32_t result,int32_t code,AsyncContext * asyncContext)732 void BoomerangNapi::ProcessErrorResult(napi_env env, int32_t result, int32_t code, AsyncContext* asyncContext)
733 {
734     if (env == nullptr || asyncContext == nullptr || !asyncContext->deferred) {
735         FI_HILOGE("Parameter error for %{public}d. Please check", code);
736         return;
737     }
738 
739     if (result == RET_OK) {
740         FI_HILOGI("handler requset success");
741         return;
742     }
743 
744     napi_value intValue;
745     int32_t callResult = (result == RET_ERR) ? code : result;
746     napi_create_int32(env, callResult, &intValue);
747     FI_HILOGI("callback the error result:%{public}d", callResult);
748     napi_reject_deferred(env, asyncContext->deferred, intValue);
749 }
750 
Init(napi_env env,napi_value exports)751 napi_value BoomerangNapi::Init(napi_env env, napi_value exports)
752 {
753     CALL_DEBUG_ENTER;
754     napi_property_descriptor desc[] = {
755         DECLARE_NAPI_STATIC_FUNCTION("on", Register),
756         DECLARE_NAPI_STATIC_FUNCTION("off", UnRegister),
757         DECLARE_NAPI_STATIC_FUNCTION("notifyMetadataBindingEvent", NotifyMetadataBindingEvent),
758         DECLARE_NAPI_STATIC_FUNCTION("submitMetadata", SubmitMetadata),
759         DECLARE_NAPI_STATIC_FUNCTION("encodeImage", BoomerangEncodeImage),
760         DECLARE_NAPI_STATIC_FUNCTION("decodeImage", DecodeImage),
761     };
762     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
763     return exports;
764 }
765 
766 EXTERN_C_START
767 /*
768  * function for module exports
769  */
DeviceStatusInit(napi_env env,napi_value exports)770 static napi_value DeviceStatusInit(napi_env env, napi_value exports)
771 {
772     CALL_DEBUG_ENTER;
773     napi_value ret = BoomerangNapi::Init(env, exports);
774     return ret;
775 }
776 EXTERN_C_END
777 
778 /*
779  * Module definition
780  */
781 static napi_module g_module = {.nm_version = 1,
782     .nm_flags = 0,
783     .nm_filename = "multimodalAwareness.metadataBinding",
784     .nm_register_func = DeviceStatusInit,
785     .nm_modname = "multimodalAwareness.metadataBinding",
786     .nm_priv = (static_cast<void *>(0)),
787     .reserved = {0}};
788 
789 /*
790  * Module registration
791  */
RegisterModule(void)792 extern "C" __attribute__((constructor)) void RegisterModule(void)
793 {
794     napi_module_register(&g_module);
795 }
796 }  // namespace DeviceStatus
797 }  // namespace Msdp
798 }  // namespace OHOS