• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 <map>
17 #include "camera_napi_utils.h"
18 #include "camera_error_code.h"
19 #include "camera_log.h"
20 #include "napi/native_api.h"
21 
22 namespace OHOS {
23 namespace CameraStandard {
24 bool CameraNapiUtils::mEnableSecure = false;
25 static const std::map<int32_t, std::string> errorCodeToMessage = {
26     {7400102, "Operation not allowed."},
27     {7400103, "Session not config."},
28     {7400201, "Camera service fatal error."},
29 };
30 
GetErrorMessage(int32_t errorCode)31 std::string CameraNapiUtils::GetErrorMessage(int32_t errorCode)
32 {
33     auto it = errorCodeToMessage.find(errorCode);
34     if (it != errorCodeToMessage.end()) {
35         return it->second;
36     } else {
37         return "";
38     }
39 }
40 
CreateNapiErrorObject(napi_env env,int32_t errorCode,const char * errString,std::unique_ptr<JSAsyncContextOutput> & jsContext)41 void CameraNapiUtils::CreateNapiErrorObject(napi_env env, int32_t errorCode, const char* errString,
42     std::unique_ptr<JSAsyncContextOutput> &jsContext)
43 {
44     napi_get_undefined(env, &jsContext->data);
45     napi_value napiErrorCode = nullptr;
46     napi_value napiErrorMsg = nullptr;
47     if (errString == nullptr || strlen(errString) == 0) {
48         napi_create_string_utf8(env, GetErrorMessage(errorCode).c_str(), NAPI_AUTO_LENGTH, &napiErrorMsg);
49     } else {
50         napi_create_string_utf8(env, errString, NAPI_AUTO_LENGTH, &napiErrorMsg);
51     }
52     std::string errorCodeStr = std::to_string(errorCode);
53     napi_create_string_utf8(env, errorCodeStr.c_str(), NAPI_AUTO_LENGTH, &napiErrorCode);
54 
55     napi_create_object(env, &jsContext->error);
56     napi_set_named_property(env, jsContext->error, "code", napiErrorCode);
57     napi_set_named_property(env, jsContext->error, "message", napiErrorMsg);
58 
59     jsContext->status = false;
60 }
61 
InvokeJSAsyncMethod(napi_env env,napi_deferred deferred,napi_ref callbackRef,napi_async_work work,const JSAsyncContextOutput & asyncContext)62 void CameraNapiUtils::InvokeJSAsyncMethod(napi_env env, napi_deferred deferred,
63     napi_ref callbackRef, napi_async_work work, const JSAsyncContextOutput &asyncContext)
64 {
65     napi_value retVal;
66     napi_value callback = nullptr;
67     std::string funcName = asyncContext.funcName;
68     MEDIA_INFO_LOG("%{public}s, context->InvokeJSAsyncMethod start", funcName.c_str());
69     /* Deferred is used when JS Callback method expects a promise value */
70     if (deferred) {
71         if (asyncContext.status) {
72             napi_resolve_deferred(env, deferred, asyncContext.data);
73             MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod napi_resolve_deferred", funcName.c_str());
74         } else {
75             napi_reject_deferred(env, deferred, asyncContext.error);
76             MEDIA_ERR_LOG("%{public}s, InvokeJSAsyncMethod napi_reject_deferred", funcName.c_str());
77         }
78         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod end deferred", funcName.c_str());
79     } else {
80         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod callback", funcName.c_str());
81         napi_value result[ARGS_TWO];
82         result[PARAM0] = asyncContext.error;
83         result[PARAM1] = asyncContext.data;
84         napi_get_reference_value(env, callbackRef, &callback);
85         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod napi_call_function start", funcName.c_str());
86         napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
87         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod napi_call_function end", funcName.c_str());
88         napi_delete_reference(env, callbackRef);
89     }
90     napi_delete_async_work(env, work);
91     MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod inner end", funcName.c_str());
92 }
93 
InvokeJSAsyncMethodWithUvWork(napi_env env,napi_deferred deferred,napi_ref callbackRef,const JSAsyncContextOutput & asyncContext)94 void CameraNapiUtils::InvokeJSAsyncMethodWithUvWork(napi_env env, napi_deferred deferred,
95     napi_ref callbackRef, const JSAsyncContextOutput &asyncContext)
96 {
97     napi_value retVal;
98     napi_value callback = nullptr;
99     std::string funcName = asyncContext.funcName;
100     MEDIA_INFO_LOG("%{public}s, context->InvokeJSAsyncMethodWithUvWork start", funcName.c_str());
101     /* Deferred is used when JS Callback method expects a promise value */
102     if (deferred) {
103         if (asyncContext.status) {
104             napi_resolve_deferred(env, deferred, asyncContext.data);
105             MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethodWithUvWork napi_resolve_deferred", funcName.c_str());
106         } else {
107             napi_reject_deferred(env, deferred, asyncContext.error);
108             MEDIA_ERR_LOG("%{public}s, InvokeJSAsyncMethodWithUvWork napi_reject_deferred", funcName.c_str());
109         }
110         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethodWithUvWork end deferred", funcName.c_str());
111     } else {
112         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethodWithUvWork callback", funcName.c_str());
113         napi_value result[ARGS_TWO];
114         result[PARAM0] = asyncContext.error;
115         result[PARAM1] = asyncContext.data;
116         napi_get_reference_value(env, callbackRef, &callback);
117         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethodWithUvWork napi_call_function start", funcName.c_str());
118         napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
119         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethodWithUvWork napi_call_function end", funcName.c_str());
120         napi_delete_reference(env, callbackRef);
121     }
122     MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethodWithUvWork inner end", funcName.c_str());
123 }
124 
IncrementAndGet(uint32_t & num)125 int32_t CameraNapiUtils::IncrementAndGet(uint32_t& num)
126 {
127     int32_t temp = num & 0x00ffffff;
128     if (temp >= 0xffff) {
129         num = num & 0xff000000;
130     }
131     num++;
132     return num;
133 }
134 
GetEnableSecureCamera()135 bool CameraNapiUtils::GetEnableSecureCamera()
136 {
137     return mEnableSecure;
138 }
139 
IsEnableSecureCamera(bool isEnable)140 void CameraNapiUtils::IsEnableSecureCamera(bool isEnable)
141 {
142     mEnableSecure = isEnable;
143 }
144 
CheckInvalidArgument(napi_env env,size_t argc,int32_t length,napi_value * argv,CameraSteps step)145 bool CameraNapiUtils::CheckInvalidArgument(napi_env env, size_t argc, int32_t length,
146     napi_value *argv, CameraSteps step)
147 {
148     bool isPass = true;
149     napi_valuetype valueTypeArray[length];
150     for (int32_t i = 0; i < length; i++) {
151         napi_typeof(env, argv[i], &valueTypeArray[i]);
152     }
153     switch (step) {
154         case CREATE_CAMERA_INPUT_INSTANCE:
155             if (argc == ARGS_ONE) {
156                 isPass = valueTypeArray[0] == napi_object;
157             } else if (argc == ARGS_TWO) {
158                 isPass = (valueTypeArray[0] == napi_number) && (valueTypeArray[1] == napi_number);
159             } else {
160                 isPass = false;
161             }
162             break;
163 
164         case CREATE_PREVIEW_OUTPUT_INSTANCE:
165             isPass = (argc == ARGS_TWO) &&
166                         (valueTypeArray[0] == napi_object) && (valueTypeArray[1] == napi_string);
167             break;
168 
169         case CREATE_PHOTO_OUTPUT_INSTANCE:
170             isPass = (argc >= ARGS_ONE) && (valueTypeArray[0] == napi_object);
171             break;
172 
173         case CREATE_VIDEO_OUTPUT_INSTANCE:
174             isPass = (argc == ARGS_TWO) &&
175                         (valueTypeArray[0] == napi_object) && (valueTypeArray[1] == napi_string);
176             break;
177 
178         case CREATE_METADATA_OUTPUT_INSTANCE:
179             isPass = argc == ARGS_ONE;
180             if (argc == ARGS_ONE) {
181                 napi_is_array(env, argv[0], &isPass);
182             } else {
183                 isPass = false;
184             }
185             break;
186 
187         case ADD_INPUT:
188             isPass = (argc == ARGS_ONE) && (valueTypeArray[0] == napi_object);
189             break;
190 
191         case REMOVE_INPUT:
192             isPass = (argc == ARGS_ONE) && (valueTypeArray[0] == napi_object);
193             break;
194 
195         case ADD_OUTPUT:
196             isPass = (argc == ARGS_ONE) && (valueTypeArray[0] == napi_object);
197             break;
198 
199         case REMOVE_OUTPUT:
200             isPass = (argc == ARGS_ONE) && (valueTypeArray[0] == napi_object);
201             break;
202 
203         case PHOTO_OUT_CAPTURE:
204             if (argc == ARGS_ZERO) {
205                 isPass = true;
206             } else if (argc == ARGS_ONE) {
207                 isPass = (valueTypeArray[0] == napi_object) || (valueTypeArray[0] == napi_function) ||
208                     (valueTypeArray[0] == napi_undefined);
209             } else if (argc == ARGS_TWO) {
210                 isPass = (valueTypeArray[0] == napi_object) && (valueTypeArray[1] == napi_function);
211             } else {
212                 isPass = false;
213             }
214             break;
215 
216         case PHOTO_OUT_BURST_CAPTURE:
217             if (argc == ARGS_ONE) {
218                 isPass = valueTypeArray[0] == napi_object;
219             }  else {
220                 isPass = false;
221             }
222             break;
223 
224         case ADD_DEFERRED_SURFACE:
225             if (argc == ARGS_ONE) {
226                 isPass = valueTypeArray[0] == napi_string;
227             } else if (argc == ARGS_TWO) {
228                 isPass = (valueTypeArray[0] == napi_string) && (valueTypeArray[1] == napi_function);
229             } else {
230                 isPass = false;
231             }
232             break;
233 
234         case CREATE_DEFERRED_PREVIEW_OUTPUT:
235             if (argc == ARGS_ONE) {
236                 isPass = valueTypeArray[0] == napi_object;
237             }  else {
238                 isPass = false;
239             }
240             break;
241 
242         default:
243             break;
244     }
245     if (!isPass) {
246         std::string errorCode = std::to_string(CameraErrorCode::INVALID_ARGUMENT);
247         napi_throw_type_error(env, errorCode.c_str(), "Parameter missing or parameter type incorrect.");
248     }
249     return isPass;
250 }
251 
CheckError(napi_env env,int32_t retCode)252 bool CameraNapiUtils::CheckError(napi_env env, int32_t retCode)
253 {
254     if ((retCode != 0)) {
255         std::string errorCode = std::to_string(retCode);
256         napi_throw_error(env, errorCode.c_str(), GetErrorMessage(retCode).c_str());
257         return false;
258     }
259     return true;
260 }
261 
FloatToDouble(float val)262 double CameraNapiUtils::FloatToDouble(float val)
263 {
264     const double precision = 1000000.0;
265     return std::round(val * precision) / precision;
266 }
267 
GetStringArgument(napi_env env,napi_value value)268 std::string CameraNapiUtils::GetStringArgument(napi_env env, napi_value value)
269 {
270     napi_valuetype valueNapiType = napi_undefined;
271     napi_typeof(env, value, &valueNapiType);
272     CHECK_RETURN_RET(valueNapiType != napi_string, "");
273     size_t stringSize = 0;
274     napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &stringSize);
275     CHECK_RETURN_RET(status != napi_ok || stringSize == 0, "");
276     std::string strValue = std::string(stringSize, '\0');
277     status = napi_get_value_string_utf8(env, value, strValue.data(), stringSize + 1, &stringSize);
278     CHECK_RETURN_RET(status != napi_ok || stringSize == 0, "");
279     return strValue;
280 }
281 
IsSameNapiValue(napi_env env,napi_value valueSrc,napi_value valueDst)282 bool CameraNapiUtils::IsSameNapiValue(napi_env env, napi_value valueSrc, napi_value valueDst)
283 {
284     CHECK_RETURN_RET(valueSrc == nullptr && valueDst == nullptr, true);
285     CHECK_RETURN_RET(valueSrc == nullptr || valueDst == nullptr, false);
286     bool isEquals = false;
287     CHECK_RETURN_RET_ELOG(napi_strict_equals(env, valueSrc, valueDst, &isEquals) != napi_ok, false,
288         "get napi_strict_equals failed");
289     return isEquals;
290 }
291 
CallPromiseFun(napi_env env,napi_value promiseValue,void * data,napi_callback thenCallback,napi_callback catchCallback)292 napi_status CameraNapiUtils::CallPromiseFun(
293     napi_env env, napi_value promiseValue, void* data, napi_callback thenCallback, napi_callback catchCallback)
294 {
295     MEDIA_DEBUG_LOG("CallPromiseFun Start");
296     bool isPromise = false;
297     napi_is_promise(env, promiseValue, &isPromise);
298     CHECK_RETURN_RET_ELOG(!isPromise, napi_invalid_arg, "CallPromiseFun promiseValue is not promise");
299     // Create promiseThen
300     napi_value promiseThen = nullptr;
301     napi_get_named_property(env, promiseValue, "then", &promiseThen);
302     CHECK_RETURN_RET_ELOG(promiseThen == nullptr, napi_invalid_arg, "CallPromiseFun get promiseThen failed");
303     napi_value thenValue;
304     napi_status ret = napi_create_function(env, "thenCallback", NAPI_AUTO_LENGTH, thenCallback, data, &thenValue);
305     CHECK_RETURN_RET_ELOG(ret != napi_ok, ret, "CallPromiseFun thenCallback got exception");
306     napi_value catchValue;
307     ret = napi_create_function(env, "catchCallback", NAPI_AUTO_LENGTH, catchCallback, data, &catchValue);
308     CHECK_RETURN_RET_ELOG(ret != napi_ok, ret, "CallPromiseFun catchCallback got exception");
309     napi_value thenReturnValue;
310     constexpr uint32_t THEN_ARGC = 2;
311     napi_value thenArgv[THEN_ARGC] = { thenValue, catchValue };
312     ret = napi_call_function(env, promiseValue, promiseThen, THEN_ARGC, thenArgv, &thenReturnValue);
313     CHECK_RETURN_RET_ELOG(ret != napi_ok, ret, "CallPromiseFun PromiseThen got exception");
314     MEDIA_DEBUG_LOG("CallPromiseFun End");
315     return napi_ok;
316 }
317 
GetPropertyDescriptor(std::vector<std::vector<napi_property_descriptor>> descriptors)318 std::vector<napi_property_descriptor> CameraNapiUtils::GetPropertyDescriptor(
319     std::vector<std::vector<napi_property_descriptor>> descriptors)
320 {
321     MEDIA_DEBUG_LOG("GetPropertyDescriptor Start %zu", descriptors.size());
322     std::vector<napi_property_descriptor> properties = {};
323     std::for_each(descriptors.begin(), descriptors.end(),
324                   [&properties](const std::vector<napi_property_descriptor> descriptor) {
325                       properties.insert(properties.end(), descriptor.begin(), descriptor.end());
326                   });
327     return properties;
328 };
329 
CreateObjectWithPropName(napi_env env,napi_value * result,size_t property_count,const char ** keys)330 napi_status CameraNapiUtils::CreateObjectWithPropName(
331     napi_env env, napi_value* result, size_t property_count, const char** keys)
332 {
333     napi_value values[property_count];
334     for (size_t i = 0; i < property_count; i++) {
335         napi_get_undefined(env, &values[i]);
336     }
337     return napi_create_object_with_named_properties(env, result, property_count, keys, values);
338 }
339 
CreateObjectWithPropNameAndValues(napi_env env,napi_value * result,size_t property_count,const char ** keys,const std::vector<std::string> values)340 napi_status CameraNapiUtils::CreateObjectWithPropNameAndValues(
341     napi_env env, napi_value* result, size_t property_count, const char** keys, const std::vector<std::string> values)
342 {
343     napi_value napiValues[property_count];
344     for (size_t i = 0; i < property_count; i++) {
345         napi_create_string_utf8(env, values[i].data(), values[i].size(), &napiValues[i]);
346     }
347     return napi_create_object_with_named_properties(env, result, property_count, keys, napiValues);
348 }
349 
GetNapiArgs(napi_env env,napi_callback_info callbackInfo)350 size_t CameraNapiUtils::GetNapiArgs(napi_env env, napi_callback_info callbackInfo)
351 {
352     size_t argsSize = 0;
353     napi_get_cb_info(env, callbackInfo, &argsSize, nullptr, nullptr, nullptr);
354     return argsSize;
355 }
356 
CreateFrameRateJSArray(napi_env env,std::vector<int32_t> frameRateRange,napi_value & result)357 void CameraNapiUtils::CreateFrameRateJSArray(napi_env env, std::vector<int32_t> frameRateRange, napi_value &result)
358 {
359     MEDIA_DEBUG_LOG("CreateFrameRateJSArray called");
360     CHECK_PRINT_ELOG(frameRateRange.empty(), "frameRateRange is empty");
361 
362     napi_status status = napi_create_object(env, &result);
363     if (status == napi_ok) {
364         napi_value minRate;
365         status = napi_create_int32(env, frameRateRange[0], &minRate);
366         napi_value maxRate;
367         status = napi_create_int32(env, frameRateRange[1], &maxRate);
368         CHECK_PRINT_ELOG(status != napi_ok || napi_set_named_property(env, result, "min", minRate) != napi_ok ||
369             napi_set_named_property(env, result, "max", maxRate) != napi_ok,
370             "Failed to create frameRateArray with napi wrapper object.");
371     }
372 }
373 
CreateSupportFrameRatesJSArray(napi_env env,std::vector<std::vector<int32_t>> supportedFrameRatesRange)374 napi_value CameraNapiUtils::CreateSupportFrameRatesJSArray(
375     napi_env env, std::vector<std::vector<int32_t>> supportedFrameRatesRange)
376 {
377     MEDIA_DEBUG_LOG("CreateFrameRateJSArray called");
378     napi_value supportedFrameRateArray = nullptr;
379     CHECK_PRINT_ELOG(supportedFrameRatesRange.empty(), "frameRateRange is empty");
380 
381     napi_status status = napi_create_array(env, &supportedFrameRateArray);
382     if (status == napi_ok) {
383         for (size_t i = 0; i < supportedFrameRatesRange.size(); i++) {
384             napi_value supportedFrameRateItem;
385             CreateFrameRateJSArray(env, supportedFrameRatesRange[i], supportedFrameRateItem);
386             CHECK_RETURN_RET_ELOG(napi_set_element(env, supportedFrameRateArray, i, supportedFrameRateItem) !=
387                 napi_ok, nullptr, "Failed to create supportedFrameRateArray with napi wrapper object.");
388         }
389     }
390     return supportedFrameRateArray;
391 }
392 
ProcessingPhysicalApertures(napi_env env,std::vector<std::vector<float>> physicalApertures)393 napi_value CameraNapiUtils::ProcessingPhysicalApertures(napi_env env, std::vector<std::vector<float>> physicalApertures)
394 {
395     napi_value result = nullptr;
396     napi_create_array(env, &result);
397     size_t zoomRangeSize = 2;
398     size_t zoomMinIndex = 0;
399     size_t zoomMaxIndex = 1;
400     for (size_t i = 0; i < physicalApertures.size(); i++) {
401         if (physicalApertures[i].size() <= zoomRangeSize) {
402             continue;
403         }
404         napi_value zoomRange;
405         napi_create_array(env, &zoomRange);
406         napi_value physicalApertureRange;
407         napi_create_array(env, &physicalApertureRange);
408         for (size_t y = 0; y < physicalApertures[i].size(); y++) {
409             napi_value value;
410             napi_create_double(env, CameraNapiUtils::FloatToDouble(physicalApertures[i][y]), &value);
411             if (y == zoomMinIndex) {
412                 napi_set_element(env, zoomRange, y, value);
413                 napi_set_named_property(env, zoomRange, "min", value);
414                 continue;
415             }
416             if (y == zoomMaxIndex) {
417                 napi_set_element(env, zoomRange, y, value);
418                 napi_set_named_property(env, zoomRange, "max", value);
419                 continue;
420             }
421             napi_set_element(env, physicalApertureRange, y - zoomRangeSize, value);
422         }
423         napi_value obj;
424         napi_create_object(env, &obj);
425         napi_set_named_property(env, obj, "zoomRange", zoomRange);
426         napi_set_named_property(env, obj, "apertures", physicalApertureRange);
427         napi_set_element(env, result, i, obj);
428     }
429     return result;
430 }
431 
CreateJSArray(napi_env env,napi_status & status,std::vector<int32_t> nativeArray)432 napi_value CameraNapiUtils::CreateJSArray(napi_env env, napi_status &status,
433     std::vector<int32_t> nativeArray)
434 {
435     MEDIA_DEBUG_LOG("CameraNapiUtils::CreateJSArray is called");
436 
437     napi_value item = nullptr;
438     napi_value jsArray = nullptr;
439 
440     if (nativeArray.empty()) {
441         MEDIA_ERR_LOG("nativeArray is empty");
442         for (size_t i = 0; i < nativeArray.size(); i++) {
443             napi_create_int32(env, nativeArray[i], &item);
444             if (napi_set_element(env, jsArray, i, item) != napi_ok) {
445                 MEDIA_ERR_LOG("CameraNapiUtils::CreateJSArray Failed to create profile napi wrapper object");
446                 return nullptr;
447             }
448         }
449     }
450     return jsArray;
451 }
452 
ParseMetadataObjectTypes(napi_env env,napi_value arrayParam,std::vector<MetadataObjectType> & metadataObjectTypes)453 napi_value CameraNapiUtils::ParseMetadataObjectTypes(napi_env env, napi_value arrayParam,
454     std::vector<MetadataObjectType> &metadataObjectTypes)
455 {
456     MEDIA_DEBUG_LOG("ParseMetadataObjectTypes is called");
457     napi_value result;
458     uint32_t length = 0;
459     napi_value value;
460     int32_t metadataType = 0;
461     napi_get_array_length(env, arrayParam, &length);
462     napi_valuetype type = napi_undefined;
463     const int32_t invalidType = -1;
464     for (uint32_t i = 0; i < length; i++) {
465         napi_get_element(env, arrayParam, i, &value);
466         napi_typeof(env, value, &type);
467         CHECK_RETURN_RET(type != napi_number, nullptr);
468         napi_get_value_int32(env, value, &metadataType);
469         if (metadataType < static_cast<int32_t>(MetadataObjectType::INVALID) &&
470             metadataType > static_cast<int32_t>(MetadataObjectType::MAX_VALUE)) {
471             MEDIA_ERR_LOG("ParseMetadataObjectTypes metadataType is out of range!");
472             metadataType = invalidType;
473         }
474         metadataObjectTypes.push_back(static_cast<MetadataObjectType>(metadataType));
475     }
476     napi_get_boolean(env, true, &result);
477     return result;
478 }
479 } // namespace CameraStandard
480 } // namespace OHOS
481