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