1 /*
2  * Copyright (c) 2021-2022 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 "input/camera_input_napi.h"
17 
18 #include <cstdint>
19 #include <memory>
20 #include <uv.h>
21 
22 #include "camera_device.h"
23 #include "camera_error_code.h"
24 #include "camera_log.h"
25 #include "camera_napi_const.h"
26 #include "camera_napi_param_parser.h"
27 #include "camera_napi_security_utils.h"
28 #include "camera_napi_utils.h"
29 #include "camera_napi_worker_queue_keeper.h"
30 #include "input/camera_napi.h"
31 #include "js_native_api.h"
32 #include "napi/native_common.h"
33 
34 namespace OHOS {
35 namespace CameraStandard {
36 namespace {
AsyncCompleteCallback(napi_env env,napi_status status,void * data)37 void AsyncCompleteCallback(napi_env env, napi_status status, void* data)
38 {
39     auto context = static_cast<CameraInputAsyncContext*>(data);
40     CHECK_ERROR_RETURN_LOG(context == nullptr, "CameraInputNapi AsyncCompleteCallback context is null");
41     MEDIA_INFO_LOG("CameraInputNapi AsyncCompleteCallback %{public}s, status = %{public}d", context->funcName.c_str(),
42         context->status);
43     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
44     jsContext->status = context->status;
45     if (!context->status) {
46         CameraNapiUtils::CreateNapiErrorObject(env, context->errorCode, context->errorMsg.c_str(), jsContext);
47     } else {
48         if (context->isEnableSecCam) {
49             napi_create_bigint_uint64(env, context->secureCameraSeqId, &jsContext->data);
50         } else {
51             napi_get_undefined(env, &jsContext->data);
52         }
53     }
54     if (!context->funcName.empty() && context->taskId > 0) {
55         // Finish async trace
56         CAMERA_FINISH_ASYNC_TRACE(context->funcName, context->taskId);
57         jsContext->funcName = context->funcName.c_str();
58     }
59     if (context->work != nullptr) {
60         CameraNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef, context->work, *jsContext);
61     }
62     context->FreeHeldNapiValue(env);
63     delete context;
64 }
65 } // namespace
66 
67 using namespace std;
68 thread_local napi_ref CameraInputNapi::sConstructor_ = nullptr;
69 thread_local sptr<CameraInput> CameraInputNapi::sCameraInput_ = nullptr;
70 thread_local uint32_t CameraInputNapi::cameraInputTaskId = CAMERA_INPUT_TASKID;
71 
OnErrorCallbackAsync(const int32_t errorType,const int32_t errorMsg) const72 void ErrorCallbackListener::OnErrorCallbackAsync(const int32_t errorType, const int32_t errorMsg) const
73 {
74     MEDIA_DEBUG_LOG("OnErrorCallbackAsync is called");
75     uv_loop_s* loop = nullptr;
76     napi_get_uv_event_loop(env_, &loop);
77     if (!loop) {
78         MEDIA_ERR_LOG("failed to get event loop");
79         return;
80     }
81     uv_work_t* work = new(std::nothrow) uv_work_t;
82     if (!work) {
83         MEDIA_ERR_LOG("failed to allocate work");
84         return;
85     }
86     std::unique_ptr<ErrorCallbackInfo> callbackInfo =
87         std::make_unique<ErrorCallbackInfo>(errorType, errorMsg, shared_from_this());
88     work->data = callbackInfo.get();
89     int ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t* work) {}, [] (uv_work_t* work, int status) {
90         ErrorCallbackInfo* callbackInfo = reinterpret_cast<ErrorCallbackInfo *>(work->data);
91         if (callbackInfo) {
92             auto listener = callbackInfo->listener_.lock();
93             if (listener) {
94                 listener->OnErrorCallback(callbackInfo->errorType_, callbackInfo->errorMsg_);
95             }
96             delete callbackInfo;
97         }
98         delete work;
99     }, uv_qos_user_initiated);
100     if (ret) {
101         MEDIA_ERR_LOG("failed to execute work");
102         delete work;
103     } else {
104         callbackInfo.release();
105     }
106 }
107 
OnErrorCallback(const int32_t errorType,const int32_t errorMsg) const108 void ErrorCallbackListener::OnErrorCallback(const int32_t errorType, const int32_t errorMsg) const
109 {
110     MEDIA_DEBUG_LOG("OnErrorCallback is called");
111     napi_value result;
112     napi_value retVal;
113     napi_value propValue;
114 
115     napi_create_int32(env_, errorType, &propValue);
116     napi_create_object(env_, &result);
117     napi_set_named_property(env_, result, "code", propValue);
118     ExecuteCallbackNapiPara callbackNapiPara { .recv = nullptr, .argc = ARGS_ONE, .argv = &result, .result = &retVal };
119     ExecuteCallback("error", callbackNapiPara);
120 }
121 
OnError(const int32_t errorType,const int32_t errorMsg) const122 void ErrorCallbackListener::OnError(const int32_t errorType, const int32_t errorMsg) const
123 {
124     MEDIA_DEBUG_LOG("OnError is called!, errorType: %{public}d", errorType);
125     OnErrorCallbackAsync(errorType, errorMsg);
126 }
127 
OnCameraOcclusionDetectedCallback(const uint8_t isCameraOcclusion,const uint8_t isCameraLensDirty) const128 void OcclusionDetectCallbackListener::OnCameraOcclusionDetectedCallback(const uint8_t isCameraOcclusion,
129     const uint8_t isCameraLensDirty) const
130 {
131     MEDIA_DEBUG_LOG("OnCameraOcclusionDetectedCallback is called");
132     napi_value result[ARGS_TWO];
133     napi_value retVal;
134     napi_value propValue;
135 
136     napi_get_undefined(env_, &result[PARAM0]);
137     napi_create_object(env_, &result[PARAM1]);
138     napi_get_boolean(env_, isCameraOcclusion == 1 ? true : false, &propValue);
139     napi_set_named_property(env_, result[PARAM1], "isCameraOccluded", propValue);
140 
141     napi_value propValueForLensDirty = nullptr;
142     napi_get_boolean(env_, isCameraLensDirty == 1 ? true : false, &propValueForLensDirty);
143     napi_set_named_property(env_, result[PARAM1], "isCameraLensDirty", propValueForLensDirty);
144 
145     ExecuteCallbackNapiPara callbackNapiPara { .recv = nullptr, .argc = ARGS_TWO, .argv = result, .result = &retVal };
146     ExecuteCallback("cameraOcclusionDetect", callbackNapiPara);
147 }
148 
OnCameraOcclusionDetectedCallbackAsync(const uint8_t isCameraOcclusion,const uint8_t isCameraLensDirty) const149 void OcclusionDetectCallbackListener::OnCameraOcclusionDetectedCallbackAsync(
150     const uint8_t isCameraOcclusion, const uint8_t isCameraLensDirty) const
151 {
152     MEDIA_DEBUG_LOG("OnCameraOcclusionDetectedCallbackAsync is called");
153     uv_loop_s* loop = nullptr;
154     napi_get_uv_event_loop(env_, &loop);
155     if (!loop) {
156         MEDIA_ERR_LOG("failed to get event loop");
157         return;
158     }
159     uv_work_t* work = new(std::nothrow) uv_work_t;
160     if (!work) {
161         MEDIA_ERR_LOG("failed to allocate work");
162         return;
163     }
164     std::unique_ptr<CameraOcclusionDetectResult> callbackInfo =
165         std::make_unique<CameraOcclusionDetectResult>(isCameraOcclusion, isCameraLensDirty, shared_from_this());
166     work->data = callbackInfo.get();
167     int ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t* work) {}, [] (uv_work_t* work, int status) {
168         CameraOcclusionDetectResult* callbackInfo = reinterpret_cast<CameraOcclusionDetectResult *>(work->data);
169         if (callbackInfo) {
170             auto listener = callbackInfo->listener_.lock();
171             if (listener) {
172                 listener->OnCameraOcclusionDetectedCallback(callbackInfo->isCameraOccluded_,
173                                                             callbackInfo->isCameraLensDirty_);
174             }
175             delete callbackInfo;
176         }
177         delete work;
178     }, uv_qos_user_initiated);
179     if (ret) {
180         MEDIA_ERR_LOG("failed to execute work");
181         delete work;
182     } else {
183         callbackInfo.release();
184     }
185 }
186 
OnCameraOcclusionDetected(const uint8_t isCameraOcclusion,const uint8_t isCameraLensDirty) const187 void OcclusionDetectCallbackListener::OnCameraOcclusionDetected(const uint8_t isCameraOcclusion,
188     const uint8_t isCameraLensDirty) const
189 {
190     MEDIA_DEBUG_LOG("OnCameraOcclusionDetected is called!, "
191                     "isCameraOcclusion: %{public}u, isCameraLensDirty: %{public}u",
192                     isCameraOcclusion, isCameraLensDirty);
193     OnCameraOcclusionDetectedCallbackAsync(isCameraOcclusion, isCameraLensDirty);
194 }
195 
CameraInputNapi()196 CameraInputNapi::CameraInputNapi() : env_(nullptr)
197 {
198 }
199 
~CameraInputNapi()200 CameraInputNapi::~CameraInputNapi()
201 {
202     MEDIA_INFO_LOG("~CameraInputNapi is called");
203 }
204 
CameraInputNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)205 void CameraInputNapi::CameraInputNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
206 {
207     MEDIA_INFO_LOG("CameraInputNapiDestructor is called");
208     CameraInputNapi* cameraObj = reinterpret_cast<CameraInputNapi*>(nativeObject);
209     if (cameraObj != nullptr) {
210         delete cameraObj;
211     }
212 }
213 
Init(napi_env env,napi_value exports)214 napi_value CameraInputNapi::Init(napi_env env, napi_value exports)
215 {
216     MEDIA_DEBUG_LOG("Init is called");
217     napi_status status;
218     napi_value ctorObj;
219     int32_t refCount = 1;
220 
221     // todo: Open and Close in native have not implemented
222     napi_property_descriptor camera_input_props[] = {
223         DECLARE_NAPI_FUNCTION("open", Open),
224         DECLARE_NAPI_FUNCTION("close", Close),
225         DECLARE_NAPI_FUNCTION("release", Release),
226         DECLARE_NAPI_FUNCTION("on", On),
227         DECLARE_NAPI_FUNCTION("once", Once),
228         DECLARE_NAPI_FUNCTION("off", Off),
229         DECLARE_NAPI_FUNCTION("usedAsPosition", UsedAsPosition)
230     };
231 
232     status = napi_define_class(env, CAMERA_INPUT_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
233                                CameraInputNapiConstructor, nullptr,
234                                sizeof(camera_input_props) / sizeof(camera_input_props[PARAM0]),
235                                camera_input_props, &ctorObj);
236     if (status == napi_ok) {
237         status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
238         if (status == napi_ok) {
239             status = napi_set_named_property(env, exports, CAMERA_INPUT_NAPI_CLASS_NAME, ctorObj);
240             if (status == napi_ok) {
241                 return exports;
242             }
243         }
244     }
245     MEDIA_ERR_LOG("Init call Failed!");
246     return nullptr;
247 }
248 
249 // Constructor callback
CameraInputNapiConstructor(napi_env env,napi_callback_info info)250 napi_value CameraInputNapi::CameraInputNapiConstructor(napi_env env, napi_callback_info info)
251 {
252     MEDIA_INFO_LOG("CameraInputNapiConstructor is called");
253     napi_status status;
254     napi_value result = nullptr;
255     napi_value thisVar = nullptr;
256 
257     napi_get_undefined(env, &result);
258     CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
259 
260     if (status == napi_ok && thisVar != nullptr) {
261         std::unique_ptr<CameraInputNapi> obj = std::make_unique<CameraInputNapi>();
262         obj->env_ = env;
263         obj->cameraInput_ = sCameraInput_;
264         status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
265                            CameraInputNapi::CameraInputNapiDestructor, nullptr, nullptr);
266         if (status == napi_ok) {
267             obj.release();
268             return thisVar;
269         } else {
270             MEDIA_ERR_LOG("Failure wrapping js to native napi");
271         }
272     }
273     MEDIA_ERR_LOG("CameraInputNapiConstructor call Failed!");
274     return result;
275 }
276 
CreateCameraInput(napi_env env,sptr<CameraInput> cameraInput)277 napi_value CameraInputNapi::CreateCameraInput(napi_env env, sptr<CameraInput> cameraInput)
278 {
279     MEDIA_INFO_LOG("CreateCameraInput is called");
280     CAMERA_SYNC_TRACE;
281     napi_status status;
282     napi_value result = nullptr;
283     napi_value constructor;
284     if (cameraInput == nullptr) {
285         return result;
286     }
287     status = napi_get_reference_value(env, sConstructor_, &constructor);
288     if (status == napi_ok) {
289         sCameraInput_ = cameraInput;
290         status = napi_new_instance(env, constructor, 0, nullptr, &result);
291         sCameraInput_ = nullptr;
292         if (status == napi_ok && result != nullptr) {
293             return result;
294         } else {
295             MEDIA_ERR_LOG("Failed to create Camera input instance");
296         }
297     }
298     napi_get_undefined(env, &result);
299     MEDIA_ERR_LOG("CreateCameraInput call Failed!");
300     return result;
301 }
302 
GetCameraInput()303 sptr<CameraInput> CameraInputNapi::GetCameraInput()
304 {
305     return cameraInput_;
306 }
307 
Open(napi_env env,napi_callback_info info)308 napi_value CameraInputNapi::Open(napi_env env, napi_callback_info info)
309 {
310     MEDIA_INFO_LOG("Open is called");
311     std::unique_ptr<CameraInputAsyncContext> asyncContext = std::make_unique<CameraInputAsyncContext>(
312         "CameraInputNapi::Open", CameraNapiUtils::IncrementAndGet(cameraInputTaskId));
313     bool isEnableSecureCamera = false;
314     auto asyncFunction =
315         std::make_shared<CameraNapiAsyncFunction>(env, "Open", asyncContext->callbackRef, asyncContext->deferred);
316     CameraNapiParamParser jsParamParser(env, info, asyncContext->objectInfo, asyncFunction, isEnableSecureCamera);
317     if (jsParamParser.IsStatusOk()) {
318         CameraNapiUtils::IsEnableSecureCamera(isEnableSecureCamera);
319         MEDIA_DEBUG_LOG("set  EnableSecureCamera CameraInputNapi::Open");
320     } else {
321         MEDIA_WARNING_LOG("CameraInputNapi::Open check secure parameter fail, try open without secure flag");
322         jsParamParser = CameraNapiParamParser(env, info, asyncContext->objectInfo, asyncFunction);
323     }
324     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "invalid argument")) {
325         MEDIA_ERR_LOG("CameraInputNapi::Open invalid argument");
326         return nullptr;
327     }
328     asyncContext->HoldNapiValue(env, jsParamParser.GetThisVar());
329     napi_status status = napi_create_async_work(
330         env, nullptr, asyncFunction->GetResourceName(),
331         [](napi_env env, void* data) {
332             MEDIA_INFO_LOG("CameraInputNapi::Open running on worker");
333             auto context = static_cast<CameraInputAsyncContext*>(data);
334             CHECK_ERROR_RETURN_LOG(context->objectInfo == nullptr, "CameraInputNapi::Open async info is nullptr");
335             CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
336             CameraNapiWorkerQueueKeeper::GetInstance()->ConsumeWorkerQueueTask(context->queueTask, [&context]() {
337                 context->isEnableSecCam = CameraNapiUtils::GetEnableSecureCamera();
338                 MEDIA_DEBUG_LOG("CameraInputNapi::Open context->isEnableSecCam %{public}d", context->isEnableSecCam);
339                 if (context->isEnableSecCam) {
340                     context->errorCode = context->objectInfo->GetCameraInput()->Open(true, &context->secureCameraSeqId);
341                     MEDIA_INFO_LOG("CameraInputNapi::Open, SeqId = %{public}" PRIu64 "", context->secureCameraSeqId);
342                 } else {
343                     context->errorCode = context->objectInfo->GetCameraInput()->Open();
344                 }
345                 context->status = context->errorCode == CameraErrorCode::SUCCESS;
346                 CameraNapiUtils::IsEnableSecureCamera(false);
347             });
348         },
349         AsyncCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
350     if (status != napi_ok) {
351         MEDIA_ERR_LOG("Failed to create napi_create_async_work for CameraInputNapi::Open");
352         asyncFunction->Reset();
353     } else {
354         asyncContext->queueTask =
355             CameraNapiWorkerQueueKeeper::GetInstance()->AcquireWorkerQueueTask("CameraInputNapi::Open");
356         napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
357         asyncContext.release();
358     }
359     if (asyncFunction->GetAsyncFunctionType() == ASYNC_FUN_TYPE_PROMISE) {
360         return asyncFunction->GetPromise();
361     }
362     return CameraNapiUtils::GetUndefinedValue(env);
363 }
364 
Close(napi_env env,napi_callback_info info)365 napi_value CameraInputNapi::Close(napi_env env, napi_callback_info info)
366 {
367     MEDIA_INFO_LOG("Close is called");
368     std::unique_ptr<CameraInputAsyncContext> asyncContext = std::make_unique<CameraInputAsyncContext>(
369         "CameraInputNapi::Close", CameraNapiUtils::IncrementAndGet(cameraInputTaskId));
370     auto asyncFunction =
371         std::make_shared<CameraNapiAsyncFunction>(env, "Close", asyncContext->callbackRef, asyncContext->deferred);
372     CameraNapiParamParser jsParamParser(env, info, asyncContext->objectInfo, asyncFunction);
373     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "invalid argument")) {
374         MEDIA_ERR_LOG("CameraInputNapi::Close invalid argument");
375         return nullptr;
376     }
377     asyncContext->HoldNapiValue(env, jsParamParser.GetThisVar());
378     napi_status status = napi_create_async_work(
379         env, nullptr, asyncFunction->GetResourceName(),
380         [](napi_env env, void* data) {
381             MEDIA_INFO_LOG("CameraInputNapi::Close running on worker");
382             auto context = static_cast<CameraInputAsyncContext*>(data);
383             CHECK_ERROR_RETURN_LOG(context->objectInfo == nullptr, "CameraInputNapi::Close async info is nullptr");
384             CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
385             CameraNapiWorkerQueueKeeper::GetInstance()->ConsumeWorkerQueueTask(context->queueTask, [&context]() {
386                 context->errorCode = context->objectInfo->GetCameraInput()->Close();
387                 context->status = context->errorCode == CameraErrorCode::SUCCESS;
388                 CameraNapiUtils::IsEnableSecureCamera(false);
389             });
390         },
391         AsyncCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
392     if (status != napi_ok) {
393         MEDIA_ERR_LOG("Failed to create napi_create_async_work for CameraInputNapi::Close");
394         asyncFunction->Reset();
395     } else {
396         asyncContext->queueTask =
397             CameraNapiWorkerQueueKeeper::GetInstance()->AcquireWorkerQueueTask("CameraInputNapi::Close");
398         napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
399         asyncContext.release();
400     }
401     if (asyncFunction->GetAsyncFunctionType() == ASYNC_FUN_TYPE_PROMISE) {
402         return asyncFunction->GetPromise();
403     }
404     return CameraNapiUtils::GetUndefinedValue(env);
405 }
406 
Release(napi_env env,napi_callback_info info)407 napi_value CameraInputNapi::Release(napi_env env, napi_callback_info info)
408 {
409     MEDIA_INFO_LOG("Release is called");
410     std::unique_ptr<CameraInputAsyncContext> asyncContext = std::make_unique<CameraInputAsyncContext>(
411         "CameraInputNapi::Release", CameraNapiUtils::IncrementAndGet(cameraInputTaskId));
412     auto asyncFunction =
413         std::make_shared<CameraNapiAsyncFunction>(env, "Release", asyncContext->callbackRef, asyncContext->deferred);
414     CameraNapiParamParser jsParamParser(env, info, asyncContext->objectInfo, asyncFunction);
415     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "invalid argument")) {
416         MEDIA_ERR_LOG("CameraInputNapi::Release invalid argument");
417         return nullptr;
418     }
419     asyncContext->HoldNapiValue(env, jsParamParser.GetThisVar());
420     napi_status status = napi_create_async_work(
421         env, nullptr, asyncFunction->GetResourceName(),
422         [](napi_env env, void* data) {
423             MEDIA_INFO_LOG("CameraInputNapi::Release running on worker");
424             auto context = static_cast<CameraInputAsyncContext*>(data);
425             CHECK_ERROR_RETURN_LOG(context->objectInfo == nullptr, "CameraInputNapi::Release async info is nullptr");
426             CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
427             CameraNapiWorkerQueueKeeper::GetInstance()->ConsumeWorkerQueueTask(context->queueTask, [&context]() {
428                 context->errorCode = context->objectInfo->GetCameraInput()->Release();
429                 context->status = context->errorCode == CameraErrorCode::SUCCESS;
430             });
431         },
432         AsyncCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
433     if (status != napi_ok) {
434         MEDIA_ERR_LOG("Failed to create napi_create_async_work for CameraInputNapi::Release");
435         asyncFunction->Reset();
436     } else {
437         asyncContext->queueTask =
438             CameraNapiWorkerQueueKeeper::GetInstance()->AcquireWorkerQueueTask("CameraInputNapi::Release");
439         napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
440         asyncContext.release();
441     }
442     if (asyncFunction->GetAsyncFunctionType() == ASYNC_FUN_TYPE_PROMISE) {
443         return asyncFunction->GetPromise();
444     }
445     return CameraNapiUtils::GetUndefinedValue(env);
446 }
447 
RegisterErrorCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)448 void CameraInputNapi::RegisterErrorCallbackListener(
449     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
450 {
451     MEDIA_INFO_LOG("CameraInputNapi::RegisterErrorCallbackListener arg size is %{public}zu", args.size());
452     CameraNapiObject emptyDevice { {} };
453     CameraNapiParamParser jsParamParser(env, args, emptyDevice);
454     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "Could not able to read cameraDevice argument!")) {
455         MEDIA_ERR_LOG("CameraInputNapi::RegisterErrorCallbackListener Could not able to read cameraDevice argument!");
456         return;
457     }
458 
459     // Set callback for error
460     if (errorCallback_ == nullptr) {
461         errorCallback_ = make_shared<ErrorCallbackListener>(env);
462         cameraInput_->SetErrorCallback(errorCallback_);
463     }
464     errorCallback_->SaveCallbackReference(eventName, callback, isOnce);
465     MEDIA_INFO_LOG("CameraInputNapi::RegisterErrorCallbackListener success");
466 }
467 
UnregisterErrorCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)468 void CameraInputNapi::UnregisterErrorCallbackListener(
469     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
470 {
471     MEDIA_INFO_LOG("CameraInputNapi::UnregisterErrorCallbackListener arg size is %{public}zu", args.size());
472     CameraNapiObject emptyDevice { {} };
473     CameraNapiParamParser jsParamParser(env, args, emptyDevice);
474     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "Could not able to read cameraDevice argument!")) {
475         MEDIA_ERR_LOG("CameraInputNapi::UnregisterErrorCallbackListener Could not able to read cameraDevice argument!");
476         return;
477     }
478 
479     if (errorCallback_ == nullptr) {
480         MEDIA_ERR_LOG("errorCallback is null");
481         return;
482     }
483     errorCallback_->RemoveCallbackRef(eventName, callback);
484     MEDIA_INFO_LOG("CameraInputNapi::UnregisterErrorCallbackListener success");
485 }
486 
RegisterOcclusionDetectCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)487 void CameraInputNapi::RegisterOcclusionDetectCallbackListener(
488     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
489 {
490     if (!CameraNapiSecurity::CheckSystemApp(env)) {
491         MEDIA_ERR_LOG("SystemApi RegisterOcclusionDetectCallbackListener is called!");
492         return;
493     }
494     if (occlusionDetectCallback_ == nullptr) {
495         occlusionDetectCallback_ = make_shared<OcclusionDetectCallbackListener>(env);
496         cameraInput_->SetOcclusionDetectCallback(occlusionDetectCallback_);
497     }
498     occlusionDetectCallback_->SaveCallbackReference(eventName, callback, isOnce);
499     MEDIA_INFO_LOG("CameraInputNapi::RegisterOcclusionDetectCallbackListener success");
500 }
501 
UnregisterOcclusionDetectCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)502 void CameraInputNapi::UnregisterOcclusionDetectCallbackListener(
503     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
504 {
505     if (!CameraNapiSecurity::CheckSystemApp(env)) {
506         MEDIA_ERR_LOG("SystemApi UnregisterOcclusionDetectCallbackListener is called!");
507         return;
508     }
509     if (occlusionDetectCallback_ == nullptr) {
510         MEDIA_ERR_LOG("occlusionDetectCallback is null");
511         return;
512     }
513     occlusionDetectCallback_->RemoveCallbackRef(eventName, callback);
514     MEDIA_INFO_LOG("CameraInputNapi::RegisterOcclusionDetectCallbackListener success");
515 }
516 
GetEmitterFunctions()517 const CameraInputNapi::EmitterFunctions& CameraInputNapi::GetEmitterFunctions()
518 {
519     static const EmitterFunctions funMap = {
520         { "error", {
521             &CameraInputNapi::RegisterErrorCallbackListener,
522             &CameraInputNapi::UnregisterErrorCallbackListener } },
523         { "cameraOcclusionDetect", {
524             &CameraInputNapi::RegisterOcclusionDetectCallbackListener,
525             &CameraInputNapi::UnregisterOcclusionDetectCallbackListener } } };
526     return funMap;
527 }
528 
On(napi_env env,napi_callback_info info)529 napi_value CameraInputNapi::On(napi_env env, napi_callback_info info)
530 {
531     return ListenerTemplate<CameraInputNapi>::On(env, info);
532 }
533 
Once(napi_env env,napi_callback_info info)534 napi_value CameraInputNapi::Once(napi_env env, napi_callback_info info)
535 {
536     return ListenerTemplate<CameraInputNapi>::Once(env, info);
537 }
538 
Off(napi_env env,napi_callback_info info)539 napi_value CameraInputNapi::Off(napi_env env, napi_callback_info info)
540 {
541     return ListenerTemplate<CameraInputNapi>::Off(env, info);
542 }
543 
UsedAsPosition(napi_env env,napi_callback_info info)544 napi_value CameraInputNapi::UsedAsPosition(napi_env env, napi_callback_info info)
545 {
546     MEDIA_INFO_LOG("CameraInputNapi::UsedAsPosition is called");
547     CameraInputNapi* cameraInputNapi = nullptr;
548     int32_t cameraPosition;
549     CameraNapiParamParser jsParamParser(env, info, cameraInputNapi, cameraPosition);
550     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "input usedAsPosition with invalid arguments!")) {
551         MEDIA_ERR_LOG("CameraInputNapi::UsedAsPosition invalid arguments");
552         return nullptr;
553     }
554     MEDIA_INFO_LOG("CameraInputNapi::UsedAsPosition params: %{public}d", cameraPosition);
555     cameraInputNapi->cameraInput_->SetInputUsedAsPosition(static_cast<const CameraPosition>(cameraPosition));
556     return CameraNapiUtils::GetUndefinedValue(env);
557 }
558 } // namespace CameraStandard
559 } // namespace OHOS
560