• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 20212 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 "sensor_napi_utils.h"
17 
18 #include <map>
19 #include <string>
20 #include <vector>
21 
22 #include "sensor_napi_error.h"
23 
24 namespace OHOS {
25 namespace Sensors {
26 namespace {
27     constexpr int32_t STRING_LENGTH_MAX = 64;
28 }
IsSameValue(const napi_env & env,const napi_value & lhs,const napi_value & rhs)29 bool IsSameValue(const napi_env &env, const napi_value &lhs, const napi_value &rhs)
30 {
31     CALL_LOG_ENTER;
32     bool result = false;
33     CHKNRF(env, napi_strict_equals(env, lhs, rhs, &result), "napi_strict_equals");
34     return result;
35 }
36 
IsMatchType(const napi_env & env,const napi_value & value,const napi_valuetype & type)37 bool IsMatchType(const napi_env &env, const napi_value &value, const napi_valuetype &type)
38 {
39     CALL_LOG_ENTER;
40     napi_valuetype paramType = napi_undefined;
41     CHKNRF(env, napi_typeof(env, value, &paramType), "napi_typeof");
42     return paramType == type;
43 }
44 
IsMatchArrayType(const napi_env & env,const napi_value & value)45 bool IsMatchArrayType(const napi_env &env, const napi_value &value)
46 {
47     CALL_LOG_ENTER;
48     bool result = false;
49     CHKNRF(env, napi_is_array(env, value, &result), "napi_is_array");
50     return result;
51 }
52 
GetFloatArray(const napi_env & env,const napi_value & value,vector<float> & array)53 bool GetFloatArray(const napi_env &env, const napi_value &value, vector<float> &array)
54 {
55     CALL_LOG_ENTER;
56     uint32_t arrayLength = 0;
57     CHKNRF(env, napi_get_array_length(env, value, &arrayLength), "napi_get_array_length");
58     for (size_t i = 0; i < arrayLength; ++i) {
59         napi_value element = nullptr;
60         CHKNRF(env, napi_get_element(env, value, i, &element), "napi_get_element");
61         CHKNCF(env, IsMatchType(env, element, napi_number), "Wrong argument type. Number or function expected");
62         double number = 0;
63         CHKNCF(env, GetNativeDouble(env, element, number), "Wrong argument type. get double fail");
64         array.push_back(static_cast<float>(number));
65     }
66     return true;
67 }
68 
GetNamedProperty(const napi_env & env,const napi_value & object,string name)69 napi_value GetNamedProperty(const napi_env &env, const napi_value &object, string name)
70 {
71     CALL_LOG_ENTER;
72     bool status = false;
73     CHKNRP(env, napi_has_named_property(env, object, name.c_str(), &status), "napi_has_named_property");
74     if (!status) {
75         SEN_HILOGW("%{public}s not exists on the object", name.c_str());
76         return nullptr;
77     }
78     napi_value value = nullptr;
79     CHKNRP(env, napi_get_named_property(env, object, name.c_str(), &value),
80         "napi_get_named_property");
81     return value;
82 }
83 
GetNativeDouble(const napi_env & env,const napi_value & value,double & number)84 bool GetNativeDouble(const napi_env &env, const napi_value &value, double &number)
85 {
86     CALL_LOG_ENTER;
87     CHKNRF(env, napi_get_value_double(env, value, &number), "napi_get_value_double");
88     return true;
89 }
90 
GetNativeFloat(const napi_env & env,const napi_value & value,float & number)91 bool GetNativeFloat(const napi_env &env, const napi_value &value, float &number)
92 {
93     CALL_LOG_ENTER;
94     double result = 0;
95     CHKNCF(env, GetNativeDouble(env, value, result), "Get cpp double fail");
96     number = static_cast<float>(result);
97     return true;
98 }
99 
GetNativeInt32(const napi_env & env,const napi_value & value,int32_t & number)100 bool GetNativeInt32(const napi_env &env, const napi_value &value, int32_t &number)
101 {
102     CALL_LOG_ENTER;
103     CHKNRF(env, napi_get_value_int32(env, value, &number), "napi_get_value_int32");
104     return true;
105 }
106 
GetNativeInt64(const napi_env & env,const napi_value & value,int64_t & number)107 bool GetNativeInt64(const napi_env &env, const napi_value &value, int64_t &number)
108 {
109     CALL_LOG_ENTER;
110     CHKNRF(env, napi_get_value_int64(env, value, &number), "napi_get_value_int64");
111     return true;
112 }
113 
GetNativeBool(const napi_env & env,const napi_value & value)114 bool GetNativeBool(const napi_env &env, const napi_value &value)
115 {
116     CALL_LOG_ENTER;
117     bool number = false;
118     CHKNRF(env, napi_get_value_bool(env, value, &number), "napi_get_value_bool");
119     return number;
120 }
121 
GetNapiInt32(const napi_env & env,int32_t number)122 napi_value GetNapiInt32(const napi_env &env, int32_t number)
123 {
124     napi_value value = nullptr;
125     CHKNRP(env, napi_create_int32(env, number, &value), "napi_create_int32");
126     return value;
127 }
128 
GetStringValue(const napi_env & env,const napi_value & value,string & result)129 bool GetStringValue(const napi_env &env, const napi_value &value, string &result)
130 {
131     CALL_LOG_ENTER;
132     CHKNCF(env, IsMatchType(env, value, napi_string), "Wrong argument type. String or function expected");
133     char buf[STRING_LENGTH_MAX] = { 0 };
134     size_t copyLength = 0;
135     CHKNRF(env, napi_get_value_string_utf8(env, value, buf, STRING_LENGTH_MAX, &copyLength),
136         "napi_get_value_string_utf8");
137     result = std::string(buf);
138     return true;
139 }
140 
RegisterNapiCallback(const napi_env & env,const napi_value & value,napi_ref & callback)141 bool RegisterNapiCallback(const napi_env &env, const napi_value &value,
142     napi_ref &callback)
143 {
144     CHKNCF(env, IsMatchType(env, value, napi_function), "Wrong argument type, should be function");
145     CHKNRF(env, napi_create_reference(env, value, 1, &callback), "napi_create_reference");
146     return true;
147 }
148 
CreateFailMessage(CallbackDataType type,int32_t code,string message,sptr<AsyncCallbackInfo> & asyncCallbackInfo)149 bool CreateFailMessage(CallbackDataType type, int32_t code, string message,
150     sptr<AsyncCallbackInfo> &asyncCallbackInfo)
151 {
152     CHKPF(asyncCallbackInfo);
153     asyncCallbackInfo->type = type;
154     asyncCallbackInfo->error.code = code;
155     asyncCallbackInfo->error.message = message;
156     return true;
157 }
158 
159 std::map<int32_t, vector<string>> g_sensorAttributeList = {
160     { 0, { "x" } },
161     { SENSOR_TYPE_ID_ACCELEROMETER, { "x", "y", "z" } },
162     { SENSOR_TYPE_ID_GYROSCOPE, { "x", "y", "z" } },
163     { SENSOR_TYPE_ID_AMBIENT_LIGHT, { "intensity" } },
164     { SENSOR_TYPE_ID_MAGNETIC_FIELD, { "x", "y", "z" } },
165     { SENSOR_TYPE_ID_BAROMETER, { "pressure" } },
166     { SENSOR_TYPE_ID_HALL, { "status" } },
167     { SENSOR_TYPE_ID_TEMPERATURE, { "temperature" } },
168     { SENSOR_TYPE_ID_PROXIMITY, { "distance" } },
169     { SENSOR_TYPE_ID_HUMIDITY, { "humidity" } },
170     { SENSOR_TYPE_ID_ORIENTATION, { "alpha", "beta", "gamma" } },
171     { SENSOR_TYPE_ID_GRAVITY, { "x", "y", "z" } },
172     { SENSOR_TYPE_ID_LINEAR_ACCELERATION, { "x", "y", "z" } },
173     { SENSOR_TYPE_ID_ROTATION_VECTOR, { "x", "y", "z", "w" } },
174     { SENSOR_TYPE_ID_AMBIENT_TEMPERATURE, { "temperature" } },
175     { SENSOR_TYPE_ID_MAGNETIC_FIELD_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } },
176     { SENSOR_TYPE_ID_GYROSCOPE_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } },
177     { SENSOR_TYPE_ID_SIGNIFICANT_MOTION, { "scalar" } },
178     { SENSOR_TYPE_ID_PEDOMETER_DETECTION, { "scalar" } },
179     { SENSOR_TYPE_ID_PEDOMETER, { "steps" } },
180     { SENSOR_TYPE_ID_HEART_RATE, { "heartRate" } },
181     { SENSOR_TYPE_ID_WEAR_DETECTION, { "value" } },
182     { SENSOR_TYPE_ID_ACCELEROMETER_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } },
183     { SENSOR_TYPE_ID_COLOR, { "lightIntensity", "colorTemperature" } },
184     { SENSOR_TYPE_ID_SAR, { "absorptionRatio" } }
185 };
186 
187 std::map<int32_t, ConvertDataFunc> g_convertfuncList = {
188     {FAIL, ConvertToFailData},
189     {ON_CALLBACK, ConvertToSensorData},
190     {ONCE_CALLBACK, ConvertToSensorData},
191     {GET_GEOMAGNETIC_FIELD, ConvertToGeomagneticData},
192     {GET_ALTITUDE, ConvertToNumber},
193     {GET_GEOMAGNETIC_DIP, ConvertToNumber},
194     {GET_ANGLE_MODIFY, ConvertToArray},
195     {CREATE_ROTATION_MATRIX, ConvertToArray},
196     {TRANSFORM_COORDINATE_SYSTEM, ConvertToArray},
197     {CREATE_QUATERNION, ConvertToArray},
198     {GET_DIRECTION, ConvertToArray},
199     {ROTATION_INCLINATION_MATRIX, ConvertToRotationMatrix},
200     {GET_SENSOR_LIST, ConvertToSensorInfos},
201     {GET_SINGLE_SENSOR, ConvertToSingleSensor},
202     {GET_BODY_STATE, ConvertToBodyData},
203     {SUBSCRIBE_CALLBACK, ConvertToSensorData},
204     {SUBSCRIBE_COMPASS, ConvertToCompass},
205 };
206 
getJsonObject(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value & result)207 bool getJsonObject(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value &result)
208 {
209     CHKPF(asyncCallbackInfo);
210     CHKNRF(env, napi_create_object(env, &result), "napi_create_object");
211     napi_value value = nullptr;
212     CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.x, &value), "napi_create_double");
213     CHKNRF(env, napi_set_named_property(env, result, "x", value), "napi_set_named_property");
214     value = nullptr;
215     CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.y, &value), "napi_create_double");
216     CHKNRF(env, napi_set_named_property(env, result, "y", value), "napi_set_named_property");
217     value = nullptr;
218     CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.z, &value), "napi_create_double");
219     CHKNRF(env, napi_set_named_property(env, result, "z", value), "napi_set_named_property");
220     value = nullptr;
221     CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.geomagneticDip, &value),
222         "napi_create_double");
223     CHKNRF(env, napi_set_named_property(env, result, "geomagneticDip", value), "napi_set_named_property");
224     value = nullptr;
225     CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.deflectionAngle, &value),
226         "napi_create_double");
227     CHKNRF(env, napi_set_named_property(env, result, "deflectionAngle", value), "napi_set_named_property");
228     value = nullptr;
229     CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.levelIntensity, &value),
230         "napi_create_double");
231     CHKNRF(env, napi_set_named_property(env, result, "levelIntensity", value), "napi_set_named_property");
232     value = nullptr;
233     CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.totalIntensity, &value),
234         "napi_create_double");
235     CHKNRF(env, napi_set_named_property(env, result, "totalIntensity", value), "napi_set_named_property");
236     return true;
237 }
238 
ConvertToSensorInfo(const napi_env & env,SensorInfo sensorInfo,napi_value & result)239 bool ConvertToSensorInfo(const napi_env &env, SensorInfo sensorInfo, napi_value &result)
240 {
241     CALL_LOG_ENTER;
242     CHKNRF(env, napi_create_object(env, &result), "napi_create_object");
243     napi_value value = nullptr;
244     CHKNRF(env, napi_create_string_latin1(env, sensorInfo.sensorName, NAPI_AUTO_LENGTH, &value),
245         "napi_create_string_latin1");
246     CHKNRF(env, napi_set_named_property(env, result, "sensorName", value), "napi_set_named_property");
247     value = nullptr;
248     CHKNRF(env, napi_create_string_latin1(env, sensorInfo.vendorName, NAPI_AUTO_LENGTH, &value),
249         "napi_create_string_latin1");
250     CHKNRF(env, napi_set_named_property(env, result, "vendorName", value), "napi_set_named_property");
251     value = nullptr;
252     CHKNRF(env, napi_create_string_latin1(env, sensorInfo.firmwareVersion, NAPI_AUTO_LENGTH, &value),
253         "napi_create_string_latin1");
254     CHKNRF(env, napi_set_named_property(env, result, "firmwareVersion", value), "napi_set_named_property");
255     value = nullptr;
256     CHKNRF(env, napi_create_string_latin1(env, sensorInfo.hardwareVersion, NAPI_AUTO_LENGTH, &value),
257         "napi_create_string_latin1");
258     CHKNRF(env, napi_set_named_property(env, result, "hardwareVersion", value), "napi_set_named_property");
259     value = nullptr;
260     CHKNRF(env, napi_create_double(env, sensorInfo.sensorId, &value), "napi_create_double");
261     CHKNRF(env, napi_set_named_property(env, result, "sensorId", value), "napi_set_named_property");
262     value = nullptr;
263     CHKNRF(env, napi_create_double(env, sensorInfo.maxRange, &value), "napi_create_double");
264     CHKNRF(env, napi_set_named_property(env, result, "maxRange", value), "napi_set_named_property");
265     value = nullptr;
266     CHKNRF(env, napi_create_double(env, sensorInfo.precision, &value), "napi_create_double");
267     CHKNRF(env, napi_set_named_property(env, result, "precision", value), "napi_set_named_property");
268     value = nullptr;
269     CHKNRF(env, napi_create_double(env, sensorInfo.power, &value), "napi_create_double");
270     CHKNRF(env, napi_set_named_property(env, result, "power", value), "napi_set_named_property");
271     value = nullptr;
272     CHKNRF(env, napi_create_int64(env, sensorInfo.minSamplePeriod, &value), "napi_create_int64");
273     CHKNRF(env, napi_set_named_property(env, result, "minSamplePeriod", value), "napi_set_named_property");
274     value = nullptr;
275     CHKNRF(env, napi_create_int64(env, sensorInfo.maxSamplePeriod, &value), "napi_create_int64");
276     CHKNRF(env, napi_set_named_property(env, result, "maxSamplePeriod", value), "napi_set_named_property");
277     return true;
278 }
279 
ConvertToSingleSensor(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])280 bool ConvertToSingleSensor(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
281 {
282     CALL_LOG_ENTER;
283     CHKPF(asyncCallbackInfo);
284     return ConvertToSensorInfo(env, asyncCallbackInfo->sensorInfos[0], result[1]);
285 }
286 
ConvertToSensorInfos(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])287 bool ConvertToSensorInfos(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
288 {
289     CALL_LOG_ENTER;
290     CHKPF(asyncCallbackInfo);
291     CHKNRF(env, napi_create_array(env, &result[1]), "napi_create_array");
292     auto sensorInfos = asyncCallbackInfo->sensorInfos;
293     for (uint32_t i = 0; i < sensorInfos.size(); ++i) {
294         napi_value value = nullptr;
295         CHKNCF(env, ConvertToSensorInfo(env, sensorInfos[i], value), "Convert sensor info fail");
296         CHKNRF(env, napi_set_element(env, result[1], i, value), "napi_set_element");
297     }
298     return true;
299 }
300 
ConvertToFailData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])301 bool ConvertToFailData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
302 {
303     CALL_LOG_ENTER;
304     CHKPF(asyncCallbackInfo);
305     int32_t code = asyncCallbackInfo->error.code;
306     auto msg = GetNapiError(code);
307     if (!msg) {
308         SEN_HILOGE("ErrCode:%{public}d is invalid", code);
309         return false;
310     }
311     result[0] = CreateBusinessError(env, code, msg.value());
312     return (result[0] != nullptr);
313 }
314 
ConvertToSensorData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])315 bool ConvertToSensorData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
316 {
317     CHKPF(asyncCallbackInfo);
318     int32_t sensorTypeId = asyncCallbackInfo->data.sensorData.sensorTypeId;
319     CHKNCF(env, (g_sensorAttributeList.find(sensorTypeId) != g_sensorAttributeList.end()), "Invalid sensor type");
320     if (sensorTypeId == SENSOR_TYPE_ID_WEAR_DETECTION && asyncCallbackInfo->type == SUBSCRIBE_CALLBACK) {
321         return ConvertToBodyData(env, asyncCallbackInfo, result);
322     }
323     size_t size = g_sensorAttributeList[sensorTypeId].size();
324     uint32_t dataLength = asyncCallbackInfo->data.sensorData.dataLength / sizeof(float);
325     CHKNCF(env, (size <= dataLength), "Data length mismatch");
326 
327     CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
328     napi_value message = nullptr;
329     auto sensorAttributes = g_sensorAttributeList[sensorTypeId];
330     for (uint32_t i = 0; i < size; ++i) {
331         CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.sensorData.data[i], &message),
332             "napi_create_double");
333         CHKNRF(env, napi_set_named_property(env, result[1], sensorAttributes[i].c_str(), message),
334             "napi_set_named_property");
335         message = nullptr;
336     }
337     CHKNRF(env, napi_create_int64(env, asyncCallbackInfo->data.sensorData.timestamp, &message),
338         "napi_create_int64");
339     CHKNRF(env, napi_set_named_property(env, result[1], "timestamp", message), "napi_set_named_property");
340     return true;
341 }
342 
ConvertToGeomagneticData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])343 bool ConvertToGeomagneticData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
344 {
345     CALL_LOG_ENTER;
346     return getJsonObject(env, asyncCallbackInfo, result[1]);
347 }
348 
ConvertToBodyData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])349 bool ConvertToBodyData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
350 {
351     CALL_LOG_ENTER;
352     CHKPF(asyncCallbackInfo);
353     CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
354     napi_value status = nullptr;
355     CHKNRF(env, napi_get_boolean(env, asyncCallbackInfo->data.sensorData.data[0], &status),
356         "napi_get_boolean");
357     CHKNRF(env, napi_set_named_property(env, result[1], "value", status), "napi_set_named_property");
358     return true;
359 }
360 
ConvertToCompass(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])361 bool ConvertToCompass(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
362 {
363     CALL_LOG_ENTER;
364     CHKPF(asyncCallbackInfo);
365     CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
366     napi_value message = nullptr;
367     CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.sensorData.data[0], &message),
368         "napi_create_double");
369     CHKNRF(env, napi_set_named_property(env, result[1], "direction", message), "napi_set_named_property");
370     return true;
371 }
372 
ConvertToNumber(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])373 bool ConvertToNumber(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
374 {
375     CALL_LOG_ENTER;
376     CHKPF(asyncCallbackInfo);
377     napi_status status =
378         napi_create_double(env, static_cast<double>(asyncCallbackInfo->data.reserveData.reserve[0]), &result[1]);
379     CHKNRF(env, status, "napi_create_double");
380     return true;
381 }
382 
ConvertToArray(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])383 bool ConvertToArray(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
384 {
385     CALL_LOG_ENTER;
386     CHKPF(asyncCallbackInfo);
387     bool ret = CreateNapiArray(env, asyncCallbackInfo->data.reserveData.reserve,
388         asyncCallbackInfo->data.reserveData.length, result[1]);
389     CHKNCF(env, ret, "Create napi array fail");
390     return true;
391 }
392 
ConvertToRotationMatrix(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])393 bool ConvertToRotationMatrix(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
394 {
395     CALL_LOG_ENTER;
396     CHKPF(asyncCallbackInfo);
397     napi_value rotation = nullptr;
398     bool ret = CreateNapiArray(env, asyncCallbackInfo->data.rationMatrixData.rotationMatrix,
399         THREE_DIMENSIONAL_MATRIX_LENGTH, rotation);
400     CHKNCF(env, ret, "Create napi array rotation fail");
401     napi_value inclination = nullptr;
402     ret = CreateNapiArray(env, asyncCallbackInfo->data.rationMatrixData.inclinationMatrix,
403         THREE_DIMENSIONAL_MATRIX_LENGTH, inclination);
404     CHKNCF(env, ret, "Create napi array inclination fail");
405     CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
406     CHKNRF(env, napi_set_named_property(env, result[1], "rotation", rotation),
407         "napi_set_named_property");
408     CHKNRF(env, napi_set_named_property(env, result[1], "inclination", inclination),
409         "napi_set_named_property");
410     return true;
411 }
412 
CreateNapiArray(const napi_env & env,float data[],int32_t dataLength,napi_value & result)413 bool CreateNapiArray(const napi_env &env, float data[], int32_t dataLength, napi_value &result)
414 {
415     CHKNRF(env, napi_create_array(env, &result), "napi_create_array");
416     for (int32_t i = 0; i < dataLength; ++i) {
417         napi_value message = nullptr;
418         CHKNRF(env, napi_create_double(env, data[i], &message), "napi_create_double");
419         CHKNRF(env, napi_set_element(env, result, i, message), "napi_set_element");
420     }
421     return true;
422 }
423 
ReleaseCallback(sptr<AsyncCallbackInfo> asyncCallbackInfo)424 void ReleaseCallback(sptr<AsyncCallbackInfo> asyncCallbackInfo)
425 {
426     CHKPV(asyncCallbackInfo);
427     if (asyncCallbackInfo->type == ONCE_CALLBACK) {
428         napi_env env = asyncCallbackInfo->env;
429         CHKPV(env);
430         napi_ref callback = asyncCallbackInfo->callback[0];
431         if (callback != nullptr) {
432             napi_delete_reference(env, callback);
433         }
434     }
435 }
436 
EmitAsyncCallbackWork(sptr<AsyncCallbackInfo> asyncCallbackInfo)437 void EmitAsyncCallbackWork(sptr<AsyncCallbackInfo> asyncCallbackInfo)
438 {
439     CALL_LOG_ENTER;
440     CHKPV(asyncCallbackInfo);
441     napi_value resourceName = nullptr;
442     napi_env env = asyncCallbackInfo->env;
443     napi_status ret = napi_create_string_latin1(env, "AsyncCallback", NAPI_AUTO_LENGTH, &resourceName);
444     CHKCV((ret == napi_ok), "napi_create_string_latin1 fail");
445     asyncCallbackInfo->IncStrongRef(nullptr);
446     napi_status status = napi_create_async_work(env, nullptr, resourceName,
447         [](napi_env env, void* data) {},
448         [](napi_env env, napi_status status, void* data) {
449             CALL_LOG_ENTER;
450             sptr<AsyncCallbackInfo> asyncCallbackInfo(static_cast<AsyncCallbackInfo *>(data));
451             /**
452              * After the asynchronous task is created, the asyncCallbackInfo reference count is reduced
453              * to 0 destruction, so you need to add 1 to the asyncCallbackInfo reference count when the
454              * asynchronous task is created, and subtract 1 from the reference count after the naked
455              * pointer is converted to a pointer when the asynchronous task is executed, the reference
456              * count of the smart pointer is guaranteed to be 1.
457              */
458             asyncCallbackInfo->DecStrongRef(nullptr);
459             napi_value callback = nullptr;
460             napi_value callResult = nullptr;
461             napi_value result[2] = {0};
462             if (asyncCallbackInfo->type == SUBSCRIBE_FAIL) {
463                 CHKCV((napi_get_reference_value(env, asyncCallbackInfo->callback[1], &callback) == napi_ok),
464                     "napi_get_reference_value fail");
465                 CHKCV((napi_create_string_utf8(env, asyncCallbackInfo->error.message.c_str(),
466                     NAPI_AUTO_LENGTH, &result[0]) == napi_ok), "napi_create_string_utf8 fail");
467                 CHKCV((napi_create_int32(env, asyncCallbackInfo->error.code, &result[1]) == napi_ok),
468                     "napi_create_int32 fail");
469                 CHKCV((napi_call_function(env, nullptr, callback, 2, result, &callResult) == napi_ok),
470                     "napi_call_function fail");
471                 return;
472             }
473             CHKCV((napi_get_reference_value(env, asyncCallbackInfo->callback[0], &callback) == napi_ok),
474                 "napi_get_reference_value fail");
475             CHKCV((g_convertfuncList.find(asyncCallbackInfo->type) != g_convertfuncList.end()),
476                 "Callback type invalid in async work");
477             bool ret = g_convertfuncList[asyncCallbackInfo->type](env, asyncCallbackInfo, result);
478             CHKCV(ret, "Create napi data fail in async work");
479             CHKCV((napi_call_function(env, nullptr, callback, 2, result, &callResult) == napi_ok),
480                 "napi_call_function fail");
481         },
482         asyncCallbackInfo.GetRefPtr(), &asyncCallbackInfo->asyncWork);
483     if (status != napi_ok
484         || napi_queue_async_work(asyncCallbackInfo->env, asyncCallbackInfo->asyncWork) != napi_ok) {
485         SEN_HILOGE("Create async work fail");
486         asyncCallbackInfo->DecStrongRef(nullptr);
487     }
488 }
489 
DeleteWork(uv_work_t * work)490 void DeleteWork(uv_work_t *work)
491 {
492     CHKPV(work);
493     delete work;
494     work = nullptr;
495 }
496 
EmitUvEventLoop(sptr<AsyncCallbackInfo> asyncCallbackInfo)497 void EmitUvEventLoop(sptr<AsyncCallbackInfo> asyncCallbackInfo)
498 {
499     CHKPV(asyncCallbackInfo);
500     uv_loop_s *loop(nullptr);
501     CHKCV((napi_get_uv_event_loop(asyncCallbackInfo->env, &loop) == napi_ok), "napi_get_uv_event_loop fail");
502     CHKPV(loop);
503     uv_work_t *work = new(std::nothrow) uv_work_t;
504     CHKPV(work);
505     asyncCallbackInfo->IncStrongRef(nullptr);
506     work->data = asyncCallbackInfo.GetRefPtr();
507     int32_t ret = uv_queue_work(loop, work, [] (uv_work_t *work) { }, [] (uv_work_t *work, int status) {
508         CHKPV(work);
509         sptr<AsyncCallbackInfo> asyncCallbackInfo(static_cast<AsyncCallbackInfo *>(work->data));
510         DeleteWork(work);
511         /**
512          * After the asynchronous task is created, the asyncCallbackInfo reference count is reduced
513          * to 0 destruction, so you need to add 1 to the asyncCallbackInfo reference count when the
514          * asynchronous task is created, and subtract 1 from the reference count after the naked
515          * pointer is converted to a pointer when the asynchronous task is executed, the reference
516          * count of the smart pointer is guaranteed to be 1.
517          */
518         asyncCallbackInfo->DecStrongRef(nullptr);
519         napi_handle_scope scope = nullptr;
520         napi_open_handle_scope(asyncCallbackInfo->env, &scope);
521         if (scope == nullptr) {
522             SEN_HILOGE("napi_handle_scope is nullptr");
523             ReleaseCallback(asyncCallbackInfo);
524             return;
525         }
526         napi_env env = asyncCallbackInfo->env;
527         napi_value callback = nullptr;
528         if (napi_get_reference_value(env, asyncCallbackInfo->callback[0], &callback) != napi_ok) {
529             SEN_HILOGE("napi_get_reference_value fail");
530             napi_throw_error(env, nullptr, "napi_get_reference_value fail");
531             ReleaseCallback(asyncCallbackInfo);
532             napi_close_handle_scope(asyncCallbackInfo->env, scope);
533             return;
534         }
535         napi_value callResult = nullptr;
536         napi_value result[2] = {0};
537         if (!(g_convertfuncList.find(asyncCallbackInfo->type) != g_convertfuncList.end())) {
538             SEN_HILOGE("asyncCallbackInfo type is invalid");
539             napi_throw_error(env, nullptr, "asyncCallbackInfo type is invalid");
540             ReleaseCallback(asyncCallbackInfo);
541             napi_close_handle_scope(asyncCallbackInfo->env, scope);
542             return;
543         }
544         g_convertfuncList[asyncCallbackInfo->type](env, asyncCallbackInfo, result);
545         if (napi_call_function(env, nullptr, callback, 1, &result[1], &callResult) != napi_ok) {
546             SEN_HILOGE("napi_call_function callback fail");
547             napi_throw_error(env, nullptr, "napi_call_function callback fail");
548             ReleaseCallback(asyncCallbackInfo);
549             napi_close_handle_scope(asyncCallbackInfo->env, scope);
550             return;
551         }
552         ReleaseCallback(asyncCallbackInfo);
553         napi_close_handle_scope(asyncCallbackInfo->env, scope);
554     });
555     if (ret != 0) {
556         SEN_HILOGE("uv_queue_work fail");
557         asyncCallbackInfo->DecStrongRef(nullptr);
558         DeleteWork(work);
559     }
560 }
561 
EmitPromiseWork(sptr<AsyncCallbackInfo> asyncCallbackInfo)562 void EmitPromiseWork(sptr<AsyncCallbackInfo> asyncCallbackInfo)
563 {
564     CALL_LOG_ENTER;
565     CHKPV(asyncCallbackInfo);
566     napi_value resourceName = nullptr;
567     napi_env env = asyncCallbackInfo->env;
568     napi_status ret = napi_create_string_latin1(env, "Promise", NAPI_AUTO_LENGTH, &resourceName);
569     CHKCV((ret == napi_ok), "napi_create_string_latin1 fail");
570     asyncCallbackInfo->IncStrongRef(nullptr);
571     napi_status status = napi_create_async_work(env, nullptr, resourceName,
572         [](napi_env env, void* data) {},
573         [](napi_env env, napi_status status, void* data) {
574             CALL_LOG_ENTER;
575             sptr<AsyncCallbackInfo> asyncCallbackInfo(static_cast<AsyncCallbackInfo *>(data));
576             /**
577              * After the asynchronous task is created, the asyncCallbackInfo reference count is reduced
578              * to 0 destruction, so you need to add 1 to the asyncCallbackInfo reference count when the
579              * asynchronous task is created, and subtract 1 from the reference count after the naked
580              * pointer is converted to a pointer when the asynchronous task is executed, the reference
581              * count of the smart pointer is guaranteed to be 1.
582              */
583             asyncCallbackInfo->DecStrongRef(nullptr);
584             napi_value result[2] = {0};
585             CHKCV((g_convertfuncList.find(asyncCallbackInfo->type) != g_convertfuncList.end()),
586                 "Callback type invalid in promise");
587             bool ret = g_convertfuncList[asyncCallbackInfo->type](env, asyncCallbackInfo, result);
588             CHKCV(ret, "Callback type invalid in promise");
589             if (asyncCallbackInfo->type == FAIL) {
590                 CHKCV((napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]) == napi_ok),
591                     "napi_reject_deferred fail");
592             } else {
593                 CHKCV((napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[1]) == napi_ok),
594                     "napi_resolve_deferred fail");
595             }
596         },
597         asyncCallbackInfo.GetRefPtr(), &asyncCallbackInfo->asyncWork);
598     if (status != napi_ok
599         || napi_queue_async_work(asyncCallbackInfo->env, asyncCallbackInfo->asyncWork) != napi_ok) {
600         SEN_HILOGE("Create async work fail");
601         asyncCallbackInfo->DecStrongRef(nullptr);
602     }
603 }
604 }  // namespace Sensors
605 }  // namespace OHOS