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