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