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