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, ¶mType), "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, ©Length),
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_PROXIMITY, { "distance" } },
168 { SENSOR_TYPE_ID_HUMIDITY, { "humidity" } },
169 { SENSOR_TYPE_ID_ORIENTATION, { "alpha", "beta", "gamma" } },
170 { SENSOR_TYPE_ID_GRAVITY, { "x", "y", "z" } },
171 { SENSOR_TYPE_ID_LINEAR_ACCELERATION, { "x", "y", "z" } },
172 { SENSOR_TYPE_ID_ROTATION_VECTOR, { "x", "y", "z", "w" } },
173 { SENSOR_TYPE_ID_AMBIENT_TEMPERATURE, { "temperature" } },
174 { SENSOR_TYPE_ID_MAGNETIC_FIELD_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } },
175 { SENSOR_TYPE_ID_GYROSCOPE_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } },
176 { SENSOR_TYPE_ID_SIGNIFICANT_MOTION, { "scalar" } },
177 { SENSOR_TYPE_ID_PEDOMETER_DETECTION, { "scalar" } },
178 { SENSOR_TYPE_ID_PEDOMETER, { "steps" } },
179 { SENSOR_TYPE_ID_HEART_RATE, { "heartRate" } },
180 { SENSOR_TYPE_ID_WEAR_DETECTION, { "value" } },
181 { SENSOR_TYPE_ID_ACCELEROMETER_UNCALIBRATED, { "x", "y", "z", "biasX", "biasY", "biasZ" } }
182 };
183
184 std::map<int32_t, ConvertDataFunc> g_convertfuncList = {
185 {FAIL, ConvertToFailData},
186 {ON_CALLBACK, ConvertToSensorData},
187 {ONCE_CALLBACK, ConvertToSensorData},
188 {GET_GEOMAGNETIC_FIELD, ConvertToGeomagneticData},
189 {GET_ALTITUDE, ConvertToNumber},
190 {GET_GEOMAGNITIC_DIP, ConvertToNumber},
191 {GET_ANGLE_MODIFY, ConvertToArray},
192 {CREATE_ROTATION_MATRIX, ConvertToArray},
193 {TRANSFORM_COORDINATE_SYSTEM, ConvertToArray},
194 {CREATE_QUATERNION, ConvertToArray},
195 {GET_DIRECTION, ConvertToArray},
196 {ROTATION_INCLINATION_MATRIX, ConvertToRotationMatrix},
197 {GET_SENSOR_LIST, ConvertToSensorInfos},
198 {GET_SINGLE_SENSOR, ConvertToSingleSensor},
199 {GET_BODY_STATE, ConvertToBodyData},
200 {SUBSCRIBE_CALLBACK, ConvertToSensorData},
201 {SUBSCRIBE_COMPASS, ConvertToCompass},
202 };
203
getJsonObject(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value & result)204 bool getJsonObject(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value &result)
205 {
206 CHKPF(asyncCallbackInfo);
207 CHKNRF(env, napi_create_object(env, &result), "napi_create_object");
208 napi_value value = nullptr;
209 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.x, &value), "napi_create_double");
210 CHKNRF(env, napi_set_named_property(env, result, "x", value), "napi_set_named_property");
211 value = nullptr;
212 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.y, &value), "napi_create_double");
213 CHKNRF(env, napi_set_named_property(env, result, "y", value), "napi_set_named_property");
214 value = nullptr;
215 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.z, &value), "napi_create_double");
216 CHKNRF(env, napi_set_named_property(env, result, "z", value), "napi_set_named_property");
217 value = nullptr;
218 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.geomagneticDip, &value),
219 "napi_create_double");
220 CHKNRF(env, napi_set_named_property(env, result, "geomagneticDip", value), "napi_set_named_property");
221 value = nullptr;
222 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.deflectionAngle, &value),
223 "napi_create_double");
224 CHKNRF(env, napi_set_named_property(env, result, "deflectionAngle", value), "napi_set_named_property");
225 value = nullptr;
226 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.levelIntensity, &value),
227 "napi_create_double");
228 CHKNRF(env, napi_set_named_property(env, result, "levelIntensity", value), "napi_set_named_property");
229 value = nullptr;
230 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.geomagneticData.totalIntensity, &value),
231 "napi_create_double");
232 CHKNRF(env, napi_set_named_property(env, result, "totalIntensity", value), "napi_set_named_property");
233 return true;
234 }
235
ConvertToSensorInfo(const napi_env & env,SensorInfo sensorInfo,napi_value & result)236 bool ConvertToSensorInfo(const napi_env &env, SensorInfo sensorInfo, napi_value &result)
237 {
238 CALL_LOG_ENTER;
239 CHKNRF(env, napi_create_object(env, &result), "napi_create_object");
240 napi_value value = nullptr;
241 CHKNRF(env, napi_create_string_latin1(env, sensorInfo.sensorName, NAPI_AUTO_LENGTH, &value),
242 "napi_create_string_latin1");
243 CHKNRF(env, napi_set_named_property(env, result, "sensorName", value), "napi_set_named_property");
244 value = nullptr;
245 CHKNRF(env, napi_create_string_latin1(env, sensorInfo.vendorName, NAPI_AUTO_LENGTH, &value),
246 "napi_create_string_latin1");
247 CHKNRF(env, napi_set_named_property(env, result, "vendorName", value), "napi_set_named_property");
248 value = nullptr;
249 CHKNRF(env, napi_create_string_latin1(env, sensorInfo.firmwareVersion, NAPI_AUTO_LENGTH, &value),
250 "napi_create_string_latin1");
251 CHKNRF(env, napi_set_named_property(env, result, "firmwareVersion", value), "napi_set_named_property");
252 value = nullptr;
253 CHKNRF(env, napi_create_string_latin1(env, sensorInfo.hardwareVersion, NAPI_AUTO_LENGTH, &value),
254 "napi_create_string_latin1");
255 CHKNRF(env, napi_set_named_property(env, result, "hardwareVersion", value), "napi_set_named_property");
256 value = nullptr;
257 CHKNRF(env, napi_create_double(env, sensorInfo.sensorId, &value), "napi_create_double");
258 CHKNRF(env, napi_set_named_property(env, result, "sensorId", value), "napi_set_named_property");
259 value = nullptr;
260 CHKNRF(env, napi_create_double(env, sensorInfo.maxRange, &value), "napi_create_double");
261 CHKNRF(env, napi_set_named_property(env, result, "maxRange", value), "napi_set_named_property");
262 value = nullptr;
263 CHKNRF(env, napi_create_double(env, sensorInfo.precision, &value), "napi_create_double");
264 CHKNRF(env, napi_set_named_property(env, result, "precision", value), "napi_set_named_property");
265 value = nullptr;
266 CHKNRF(env, napi_create_double(env, sensorInfo.power, &value), "napi_create_double");
267 CHKNRF(env, napi_set_named_property(env, result, "power", value), "napi_set_named_property");
268 value = nullptr;
269 CHKNRF(env, napi_create_int64(env, sensorInfo.minSamplePeriod, &value), "napi_create_int64");
270 CHKNRF(env, napi_set_named_property(env, result, "minSamplePeriod", value), "napi_set_named_property");
271 value = nullptr;
272 CHKNRF(env, napi_create_int64(env, sensorInfo.maxSamplePeriod, &value), "napi_create_int64");
273 CHKNRF(env, napi_set_named_property(env, result, "maxSamplePeriod", value), "napi_set_named_property");
274 return true;
275 }
276
ConvertToSingleSensor(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])277 bool ConvertToSingleSensor(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
278 {
279 CALL_LOG_ENTER;
280 CHKPF(asyncCallbackInfo);
281 return ConvertToSensorInfo(env, asyncCallbackInfo->sensorInfos[0], result[1]);
282 }
283
ConvertToSensorInfos(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])284 bool ConvertToSensorInfos(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
285 {
286 CALL_LOG_ENTER;
287 CHKPF(asyncCallbackInfo);
288 CHKNRF(env, napi_create_array(env, &result[1]), "napi_create_array");
289 auto sensorInfos = asyncCallbackInfo->sensorInfos;
290 for (uint32_t i = 0; i < sensorInfos.size(); ++i) {
291 napi_value value = nullptr;
292 CHKNCF(env, ConvertToSensorInfo(env, sensorInfos[i], value), "Convert sensor info fail");
293 CHKNRF(env, napi_set_element(env, result[1], i, value), "napi_set_element");
294 }
295 return true;
296 }
297
ConvertToFailData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])298 bool ConvertToFailData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
299 {
300 CALL_LOG_ENTER;
301 CHKPF(asyncCallbackInfo);
302 int32_t code = asyncCallbackInfo->error.code;
303 auto msg = GetNapiError(code);
304 if (!msg) {
305 SEN_HILOGE("errCode: %{public}d is invalid", code);
306 return false;
307 }
308 result[0] = CreateBusinessError(env, code, msg.value());
309 return (result[0] != nullptr);
310 }
311
ConvertToSensorData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])312 bool ConvertToSensorData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
313 {
314 CHKPF(asyncCallbackInfo);
315 int32_t sensorTypeId = asyncCallbackInfo->data.sensorData.sensorTypeId;
316 CHKNCF(env, (g_sensorAttributeList.find(sensorTypeId) != g_sensorAttributeList.end()), "Invalid sensor type");
317 if (sensorTypeId == SENSOR_TYPE_ID_WEAR_DETECTION && asyncCallbackInfo->type == SUBSCRIBE_CALLBACK) {
318 return ConvertToBodyData(env, asyncCallbackInfo, result);
319 }
320 size_t size = g_sensorAttributeList[sensorTypeId].size();
321 uint32_t dataLenth = asyncCallbackInfo->data.sensorData.dataLength / sizeof(float);
322 CHKNCF(env, (size <= dataLenth), "Data length mismatch");
323
324 CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
325 napi_value message = nullptr;
326 auto sensorAttributes = g_sensorAttributeList[sensorTypeId];
327 for (uint32_t i = 0; i < size; ++i) {
328 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.sensorData.data[i], &message),
329 "napi_create_double");
330 CHKNRF(env, napi_set_named_property(env, result[1], sensorAttributes[i].c_str(), message),
331 "napi_set_named_property");
332 message = nullptr;
333 }
334 CHKNRF(env, napi_create_int64(env, asyncCallbackInfo->data.sensorData.timestamp, &message),
335 "napi_create_int64");
336 CHKNRF(env, napi_set_named_property(env, result[1], "timestamp", message), "napi_set_named_property");
337 return true;
338 }
339
ConvertToGeomagneticData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])340 bool ConvertToGeomagneticData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
341 {
342 CALL_LOG_ENTER;
343 return getJsonObject(env, asyncCallbackInfo, result[1]);
344 }
345
ConvertToBodyData(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])346 bool ConvertToBodyData(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
347 {
348 CALL_LOG_ENTER;
349 CHKPF(asyncCallbackInfo);
350 CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
351 napi_value status = nullptr;
352 CHKNRF(env, napi_get_boolean(env, asyncCallbackInfo->data.sensorData.data[0], &status),
353 "napi_get_boolean");
354 CHKNRF(env, napi_set_named_property(env, result[1], "value", status), "napi_set_named_property");
355 return true;
356 }
357
ConvertToCompass(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])358 bool ConvertToCompass(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
359 {
360 CALL_LOG_ENTER;
361 CHKPF(asyncCallbackInfo);
362 CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
363 napi_value message = nullptr;
364 CHKNRF(env, napi_create_double(env, asyncCallbackInfo->data.sensorData.data[0], &message),
365 "napi_create_double");
366 CHKNRF(env, napi_set_named_property(env, result[1], "direction", message), "napi_set_named_property");
367 return true;
368 }
369
ConvertToNumber(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])370 bool ConvertToNumber(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
371 {
372 CALL_LOG_ENTER;
373 CHKPF(asyncCallbackInfo);
374 napi_status status =
375 napi_create_double(env, static_cast<double>(asyncCallbackInfo->data.reserveData.reserve[0]), &result[1]);
376 CHKNRF(env, status, "napi_create_double");
377 return true;
378 }
379
ConvertToArray(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])380 bool ConvertToArray(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
381 {
382 CALL_LOG_ENTER;
383 CHKPF(asyncCallbackInfo);
384 bool ret = CreateNapiArray(env, asyncCallbackInfo->data.reserveData.reserve,
385 asyncCallbackInfo->data.reserveData.length, result[1]);
386 CHKNCF(env, ret, "Create napi array fail");
387 return true;
388 }
389
ConvertToRotationMatrix(const napi_env & env,sptr<AsyncCallbackInfo> asyncCallbackInfo,napi_value result[2])390 bool ConvertToRotationMatrix(const napi_env &env, sptr<AsyncCallbackInfo> asyncCallbackInfo, napi_value result[2])
391 {
392 CALL_LOG_ENTER;
393 CHKPF(asyncCallbackInfo);
394 napi_value rotation = nullptr;
395 bool ret = CreateNapiArray(env, asyncCallbackInfo->data.rationMatrixData.rotationMatrix,
396 THREE_DIMENSIONAL_MATRIX_LENGTH, rotation);
397 CHKNCF(env, ret, "Create napi array rotation fail");
398 napi_value inclination = nullptr;
399 ret = CreateNapiArray(env, asyncCallbackInfo->data.rationMatrixData.inclinationMatrix,
400 THREE_DIMENSIONAL_MATRIX_LENGTH, inclination);
401 CHKNCF(env, ret, "Create napi array inclination fail");
402 CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object");
403 CHKNRF(env, napi_set_named_property(env, result[1], "rotation", rotation),
404 "napi_set_named_property");
405 CHKNRF(env, napi_set_named_property(env, result[1], "inclination", inclination),
406 "napi_set_named_property");
407 return true;
408 }
409
CreateNapiArray(const napi_env & env,float data[],int32_t dataLength,napi_value & result)410 bool CreateNapiArray(const napi_env &env, float data[], int32_t dataLength, napi_value &result)
411 {
412 CHKNRF(env, napi_create_array(env, &result), "napi_create_array");
413 for (int32_t i = 0; i < dataLength; ++i) {
414 napi_value message = nullptr;
415 CHKNRF(env, napi_create_double(env, data[i], &message), "napi_create_double");
416 CHKNRF(env, napi_set_element(env, result, i, message), "napi_set_element");
417 }
418 return true;
419 }
420
ReleaseCallback(sptr<AsyncCallbackInfo> asyncCallbackInfo)421 void ReleaseCallback(sptr<AsyncCallbackInfo> asyncCallbackInfo)
422 {
423 CHKPV(asyncCallbackInfo);
424 if (asyncCallbackInfo->type == ONCE_CALLBACK) {
425 napi_env env = asyncCallbackInfo->env;
426 CHKPV(env);
427 napi_ref callback = asyncCallbackInfo->callback[0];
428 if (callback != nullptr) {
429 napi_delete_reference(env, callback);
430 }
431 }
432 }
433
EmitAsyncCallbackWork(sptr<AsyncCallbackInfo> asyncCallbackInfo)434 void EmitAsyncCallbackWork(sptr<AsyncCallbackInfo> asyncCallbackInfo)
435 {
436 CALL_LOG_ENTER;
437 CHKPV(asyncCallbackInfo);
438 napi_value resourceName = nullptr;
439 napi_env env = asyncCallbackInfo->env;
440 napi_status ret = napi_create_string_latin1(env, "AsyncCallback", NAPI_AUTO_LENGTH, &resourceName);
441 CHKCV((ret == napi_ok), "napi_create_string_latin1 fail");
442 asyncCallbackInfo->IncStrongRef(nullptr);
443 napi_status status = napi_create_async_work(env, nullptr, resourceName,
444 [](napi_env env, void* data) {},
445 [](napi_env env, napi_status status, void* data) {
446 CALL_LOG_ENTER;
447 sptr<AsyncCallbackInfo> asyncCallbackInfo(static_cast<AsyncCallbackInfo *>(data));
448 /**
449 * After the asynchronous task is created, the asyncCallbackInfo reference count is reduced
450 * to 0 destructions, so you need to add 1 to the asyncCallbackInfo reference count when the
451 * asynchronous task is created, and subtract 1 from the reference count after the naked
452 * pointer is converted to a pointer when the asynchronous task is executed, the reference
453 * count of the smart pointer is guaranteed to be 1.
454 */
455 asyncCallbackInfo->DecStrongRef(nullptr);
456 napi_value callback = nullptr;
457 napi_value callResult = nullptr;
458 napi_value result[2] = {0};
459 if (asyncCallbackInfo->type == SUBSCRIBE_FAIL) {
460 CHKCV((napi_get_reference_value(env, asyncCallbackInfo->callback[1], &callback) == napi_ok),
461 "napi_get_reference_value fail");
462 CHKCV((napi_create_string_utf8(env, asyncCallbackInfo->error.message.c_str(),
463 NAPI_AUTO_LENGTH, &result[0]) == napi_ok), "napi_create_string_utf8 fail");
464 CHKCV((napi_create_int32(env, asyncCallbackInfo->error.code, &result[1]) == napi_ok),
465 "napi_create_int32 fail");
466 CHKCV((napi_call_function(env, nullptr, callback, 2, result, &callResult) == napi_ok),
467 "napi_call_function fail");
468 return;
469 }
470 CHKCV((napi_get_reference_value(env, asyncCallbackInfo->callback[0], &callback) == napi_ok),
471 "napi_get_reference_value fail");
472 CHKCV((g_convertfuncList.find(asyncCallbackInfo->type) != g_convertfuncList.end()),
473 "Callback type invalid in async work");
474 bool ret = g_convertfuncList[asyncCallbackInfo->type](env, asyncCallbackInfo, result);
475 CHKCV(ret, "Create napi data fail in async work");
476 CHKCV((napi_call_function(env, nullptr, callback, 2, result, &callResult) == napi_ok),
477 "napi_call_function fail");
478 },
479 asyncCallbackInfo.GetRefPtr(), &asyncCallbackInfo->asyncWork);
480 if (status != napi_ok
481 || napi_queue_async_work(asyncCallbackInfo->env, asyncCallbackInfo->asyncWork) != napi_ok) {
482 SEN_HILOGE("Create async work fail");
483 asyncCallbackInfo->DecStrongRef(nullptr);
484 }
485 }
486
freeWork(uv_work_t * work)487 void freeWork(uv_work_t *work)
488 {
489 CHKPV(work);
490 delete work;
491 work = nullptr;
492 }
493
EmitUvEventLoop(sptr<AsyncCallbackInfo> asyncCallbackInfo)494 void EmitUvEventLoop(sptr<AsyncCallbackInfo> asyncCallbackInfo)
495 {
496 CHKPV(asyncCallbackInfo);
497 uv_loop_s *loop(nullptr);
498 CHKCV((napi_get_uv_event_loop(asyncCallbackInfo->env, &loop) == napi_ok), "napi_get_uv_event_loop fail");
499 CHKPV(loop);
500 uv_work_t *work = new(std::nothrow) uv_work_t;
501 CHKPV(work);
502 asyncCallbackInfo->work = work;
503 asyncCallbackInfo->IncStrongRef(nullptr);
504 work->data = asyncCallbackInfo.GetRefPtr();
505 int32_t ret = uv_queue_work(loop, work, [] (uv_work_t *work) { }, [] (uv_work_t *work, int status) {
506 CHKPV(work);
507 sptr<AsyncCallbackInfo> asyncCallbackInfo(static_cast<AsyncCallbackInfo *>(work->data));
508 /**
509 * After the asynchronous task is created, the asyncCallbackInfo reference count is reduced
510 * to 0 destructions, so you need to add 1 to the asyncCallbackInfo reference count when the
511 * asynchronous task is created, and subtract 1 from the reference count after the naked
512 * pointer is converted to a pointer when the asynchronous task is executed, the reference
513 * count of the smart pointer is guaranteed to be 1.
514 */
515 asyncCallbackInfo->DecStrongRef(nullptr);
516 napi_handle_scope scope = nullptr;
517 napi_open_handle_scope(asyncCallbackInfo->env, &scope);
518 if (scope == nullptr) {
519 SEN_HILOGE("napi_handle_scope is nullptr");
520 ReleaseCallback(asyncCallbackInfo);
521 return;
522 }
523 napi_env env = asyncCallbackInfo->env;
524 napi_value callback = nullptr;
525 if (napi_get_reference_value(env, asyncCallbackInfo->callback[0], &callback) != napi_ok) {
526 SEN_HILOGE("napi_get_reference_value fail");
527 napi_throw_error(env, nullptr, "napi_get_reference_value fail");
528 ReleaseCallback(asyncCallbackInfo);
529 napi_close_handle_scope(asyncCallbackInfo->env, scope);
530 return;
531 }
532 napi_value callResult = nullptr;
533 napi_value result[2] = {0};
534 if (!(g_convertfuncList.find(asyncCallbackInfo->type) != g_convertfuncList.end())) {
535 SEN_HILOGE("asyncCallbackInfo type is invalid");
536 napi_throw_error(env, nullptr, "asyncCallbackInfo type is invalid");
537 ReleaseCallback(asyncCallbackInfo);
538 napi_close_handle_scope(asyncCallbackInfo->env, scope);
539 return;
540 }
541 g_convertfuncList[asyncCallbackInfo->type](env, asyncCallbackInfo, result);
542 if (napi_call_function(env, nullptr, callback, 1, &result[1], &callResult) != napi_ok) {
543 SEN_HILOGE("napi_call_function callback fail");
544 napi_throw_error(env, nullptr, "napi_call_function callback fail");
545 ReleaseCallback(asyncCallbackInfo);
546 napi_close_handle_scope(asyncCallbackInfo->env, scope);
547 return;
548 }
549 ReleaseCallback(asyncCallbackInfo);
550 napi_close_handle_scope(asyncCallbackInfo->env, scope);
551 asyncCallbackInfo->work = nullptr;
552 freeWork(work);
553 });
554 if (ret != 0) {
555 SEN_HILOGE("uv_queue_work fail");
556 asyncCallbackInfo->DecStrongRef(nullptr);
557 asyncCallbackInfo->work = nullptr;
558 freeWork(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 destructions, 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