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