1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "devicestatus_napi.h"
17 
18 #include <js_native_api.h>
19 
20 #include "napi/native_api.h"
21 #include "napi/native_node_api.h"
22 
23 #include "devicestatus_client.h"
24 #include "devicestatus_define.h"
25 #include "devicestatus_napi_error.h"
26 #include "stationary_manager.h"
27 
28 #undef LOG_TAG
29 #define LOG_TAG "DeviceStatusNapi"
30 
31 namespace OHOS {
32 namespace Msdp {
33 namespace DeviceStatus {
34 namespace {
35 constexpr size_t ARG_0 { 0 };
36 constexpr size_t ARG_1 { 1 };
37 constexpr size_t ARG_2 { 2 };
38 constexpr size_t ARG_3 { 3 };
39 constexpr size_t ARG_4 { 4 };
40 constexpr int32_t NAPI_BUF_LENGTH { 256 };
41 constexpr int32_t NANO { 1000000000 };
42 const std::vector<std::string> vecDeviceStatusValue {
43     "VALUE_ENTER", "VALUE_EXIT"
44 };
45 thread_local DeviceStatusNapi *g_obj = nullptr;
46 } // namespace
47 std::map<int32_t, sptr<IRemoteDevStaCallback>> DeviceStatusNapi::callbacks_;
48 napi_ref DeviceStatusNapi::devicestatusValueRef_ = nullptr;
49 
OnDeviceStatusChanged(const Data & devicestatusData)50 void DeviceStatusCallback::OnDeviceStatusChanged(const Data& devicestatusData)
51 {
52     CALL_DEBUG_ENTER;
53     std::lock_guard<std::mutex> guard(mutex_);
54     uv_loop_s *loop = nullptr;
55     napi_get_uv_event_loop(env_, &loop);
56     CHKPV(loop);
57     uv_work_t *work = new (std::nothrow) uv_work_t;
58     CHKPV(work);
59     FI_HILOGD("devicestatusData.type:%{public}d, devicestatusData.value:%{public}d",
60         devicestatusData.type, devicestatusData.value);
61     data_ = devicestatusData;
62     work->data = static_cast<void *>(&data_);
63     int32_t ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t *work) {}, EmitOnEvent, uv_qos_default);
64     if (ret != 0) {
65         FI_HILOGE("Failed to uv_queue_work_with_qos");
66     }
67 }
68 
EmitOnEvent(uv_work_t * work,int32_t status)69 void DeviceStatusCallback::EmitOnEvent(uv_work_t *work, int32_t status)
70 {
71     CHKPV(work);
72     Data* data = static_cast<Data*>(work->data);
73     delete work;
74     CHKPV(data);
75     DeviceStatusNapi* deviceStatusNapi = DeviceStatusNapi::GetDeviceStatusNapi();
76     CHKPV(deviceStatusNapi);
77     int32_t type = static_cast<int32_t>(data->type);
78     int32_t value = static_cast<int32_t>(data->value);
79     FI_HILOGD("type:%{public}d, value:%{public}d", type, value);
80     deviceStatusNapi->OnDeviceStatusChangedDone(type, value, false);
81 }
82 
GetDeviceStatusNapi()83 DeviceStatusNapi* DeviceStatusNapi::GetDeviceStatusNapi()
84 {
85     return g_obj;
86 }
87 
DeviceStatusNapi(napi_env env)88 DeviceStatusNapi::DeviceStatusNapi(napi_env env) : DeviceStatusEvent(env)
89 {
90     env_ = env;
91     devicestatusValueRef_ = nullptr;
92     DeviceStatusClient::GetInstance().RegisterDeathListener([this] {
93         FI_HILOGI("Receive death notification");
94         callbacks_.clear();
95         ClearEventMap();
96     });
97 }
98 
~DeviceStatusNapi()99 DeviceStatusNapi::~DeviceStatusNapi()
100 {
101     if (devicestatusValueRef_ != nullptr) {
102         napi_delete_reference(env_, devicestatusValueRef_);
103     }
104     if (g_obj != nullptr) {
105         delete g_obj;
106         g_obj = nullptr;
107     }
108 }
109 
OnDeviceStatusChangedDone(int32_t type,int32_t value,bool isOnce)110 void DeviceStatusNapi::OnDeviceStatusChangedDone(int32_t type, int32_t value, bool isOnce)
111 {
112     CALL_DEBUG_ENTER;
113     FI_HILOGD("value:%{public}d", value);
114     OnEvent(type, ARG_1, value, isOnce);
115 }
116 
ConvertTypeToInt(const std::string & type)117 int32_t DeviceStatusNapi::ConvertTypeToInt(const std::string &type)
118 {
119     if (type == "absoluteStill") {
120         return Type::TYPE_ABSOLUTE_STILL;
121     } else if (type == "horizontalPosition") {
122         return Type::TYPE_HORIZONTAL_POSITION;
123     } else if (type == "verticalPosition") {
124         return Type::TYPE_VERTICAL_POSITION;
125     } else if (type == "still") {
126         return Type::TYPE_STILL;
127     } else if (type == "relativeStill") {
128         return Type::TYPE_RELATIVE_STILL;
129     } else if (type == "carBluetooth") {
130         return Type::TYPE_CAR_BLUETOOTH;
131     } else {
132         return Type::TYPE_INVALID;
133     }
134 }
135 
CheckArguments(napi_env env,napi_callback_info info)136 bool DeviceStatusNapi::CheckArguments(napi_env env, napi_callback_info info)
137 {
138     CALL_DEBUG_ENTER;
139     int32_t arr[ARG_4] = { 0 };
140     size_t argc = ARG_4;
141     napi_value args[ARG_4] = { nullptr };
142     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
143     if (status != napi_ok) {
144         FI_HILOGE("Failed to get_cb_info");
145         return false;
146     }
147     for (size_t i = 0; i < ARG_4; i++) {
148         napi_valuetype valueType = napi_undefined;
149         status = napi_typeof(env, args[i], &valueType);
150         if (status != napi_ok) {
151             FI_HILOGE("Failed to get valueType");
152             return false;
153         }
154         FI_HILOGD("valueType:%{public}d", valueType);
155         arr[i] = valueType;
156     }
157     if (arr[ARG_0] != napi_string || arr[ARG_1] != napi_number || arr[ARG_2] != napi_number ||
158         arr[ARG_3] != napi_function) {
159         FI_HILOGE("Failed to get arguements");
160         return false;
161     }
162     return true;
163 }
164 
IsMatchType(napi_env env,napi_value value,napi_valuetype type)165 bool DeviceStatusNapi::IsMatchType(napi_env env, napi_value value, napi_valuetype type)
166 {
167     CALL_DEBUG_ENTER;
168     napi_valuetype valueType = napi_undefined;
169     napi_status status = napi_typeof(env, value, &valueType);
170     if (status != napi_ok) {
171         FI_HILOGE("Failed to get valueType");
172         return false;
173     }
174     return valueType == type;
175 }
176 
CheckGetArguments(napi_env env,napi_callback_info info)177 bool DeviceStatusNapi::CheckGetArguments(napi_env env, napi_callback_info info)
178 {
179     CALL_DEBUG_ENTER;
180     int32_t arr[ARG_2] = { 0 };
181     size_t argc = ARG_2;
182     napi_value args[ARG_2] = { nullptr };
183     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
184     if (status != napi_ok) {
185         FI_HILOGE("Failed to get_cb_info");
186         return false;
187     }
188     for (size_t i = 0; i < ARG_2; i++) {
189         napi_valuetype valueType = napi_undefined;
190         status = napi_typeof(env, args[i], &valueType);
191         if (status != napi_ok) {
192             FI_HILOGE("Failed to get valueType");
193             return false;
194         }
195         FI_HILOGD("valueType:%{public}d", valueType);
196         arr[i] = valueType;
197     }
198     if (arr[ARG_0] != napi_string || arr[ARG_1] != napi_function) {
199         FI_HILOGE("Failed to get arguements");
200         return false;
201     }
202     return true;
203 }
204 
CheckSubscribeParam(napi_env env,napi_callback_info info)205 std::tuple<bool, napi_value, std::string, int32_t, int32_t> DeviceStatusNapi::CheckSubscribeParam(napi_env env,
206     napi_callback_info info)
207 {
208     std::tuple<bool, napi_value, std::string, int32_t, int32_t> result { false, nullptr, "", -1, -1 };
209     size_t argc = ARG_4;
210     napi_value args[ARG_4] = { nullptr };
211     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
212     if ((status != napi_ok) || (argc < ARG_4)) {
213         ThrowErr(env, PARAM_ERROR, "Bad parameters");
214         return result;
215     }
216     if (!CheckArguments(env, info)) {
217         ThrowErr(env, PARAM_ERROR, "Failed to get on arguments");
218         return result;
219     }
220     size_t modLen = 0;
221     status = napi_get_value_string_utf8(env, args[ARG_0], nullptr, 0, &modLen);
222     if (status != napi_ok) {
223         ThrowErr(env, PARAM_ERROR, "Failed to get string item");
224         return result;
225     }
226     char mode[NAPI_BUF_LENGTH] = { 0 };
227     status = napi_get_value_string_utf8(env, args[ARG_0], mode, modLen + 1, &modLen);
228     if (status != napi_ok) {
229         ThrowErr(env, PARAM_ERROR, "Failed to get mode");
230         return result;
231     }
232     int32_t eventMode = 0;
233     status = napi_get_value_int32(env, args[ARG_1], &eventMode);
234     if (status != napi_ok) {
235         ThrowErr(env, PARAM_ERROR, "Failed to get event value item");
236         return result;
237     }
238     int32_t latencyMode = 0;
239     status = napi_get_value_int32(env, args[ARG_2], &latencyMode);
240     if (status != napi_ok) {
241         ThrowErr(env, PARAM_ERROR, "Failed to get latency value item");
242         return result;
243     }
244     latencyMode = latencyMode / NANO;
245     return std::make_tuple(true, args[ARG_3], std::string(mode), eventMode, latencyMode);
246 }
247 
CheckGetParam(napi_env env,napi_callback_info info)248 std::tuple<bool, napi_value, int32_t> DeviceStatusNapi::CheckGetParam(napi_env env, napi_callback_info info)
249 {
250     std::tuple<bool, napi_value, int32_t> result { false, nullptr, -1 };
251     size_t argc = ARG_2;
252     napi_value args[ARG_2] = { nullptr };
253     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
254     if ((status != napi_ok) || (argc < ARG_2)) {
255         ThrowErr(env, PARAM_ERROR, "Bad parameters");
256         return result;
257     }
258     if (!CheckGetArguments(env, info)) {
259         ThrowErr(env, PARAM_ERROR, "Failed to get once arguments");
260         return result;
261     }
262     size_t modLen = 0;
263     napi_status napiStatus = napi_get_value_string_utf8(env, args[ARG_0], nullptr, 0, &modLen);
264     if (napiStatus != napi_ok) {
265         ThrowErr(env, PARAM_ERROR, "Failed to get string item");
266         return result;
267     }
268     char mode[NAPI_BUF_LENGTH] = { 0 };
269     napiStatus = napi_get_value_string_utf8(env, args[ARG_0], mode, modLen + 1, &modLen);
270     if (napiStatus != napi_ok) {
271         ThrowErr(env, PARAM_ERROR, "Failed to get mode");
272         return result;
273     }
274     int32_t type = ConvertTypeToInt(mode);
275     if ((type < Type::TYPE_ABSOLUTE_STILL) || (type > Type::TYPE_LID_OPEN)) {
276         ThrowErr(env, PARAM_ERROR, "Type is illegal");
277         return result;
278     }
279     return std::make_tuple(true, args[ARG_1], type);
280 }
281 
GetParameters(napi_env env,size_t argc,const napi_value * args)282 napi_value DeviceStatusNapi::GetParameters(napi_env env, size_t argc, const napi_value* args)
283 {
284     CALL_DEBUG_ENTER;
285     size_t modLen = 0;
286     napi_status status = napi_get_value_string_utf8(env, args[0], nullptr, 0, &modLen);
287     if (status != napi_ok) {
288         ThrowErr(env, PARAM_ERROR, "Failed to get string item");
289         return nullptr;
290     }
291     char mode[NAPI_BUF_LENGTH] = { 0 };
292     status = napi_get_value_string_utf8(env, args[0], mode, modLen + 1, &modLen);
293     if (status != napi_ok) {
294         ThrowErr(env, PARAM_ERROR, "Failed to get mode");
295         return nullptr;
296     }
297     int32_t type = DeviceStatusNapi::ConvertTypeToInt(mode);
298     if ((type < Type::TYPE_ABSOLUTE_STILL) || (type > Type::TYPE_LID_OPEN)) {
299         ThrowErr(env, PARAM_ERROR, "Type is illegal");
300         return nullptr;
301     }
302     int32_t event = 0;
303     status = napi_get_value_int32(env, args[1], &event);
304     if (status != napi_ok) {
305         ThrowErr(env, PARAM_ERROR, "Failed to get int32 item");
306         return nullptr;
307     }
308     if ((event < ActivityEvent::ENTER) || (event > ActivityEvent::ENTER_EXIT)) {
309         ThrowErr(env, PARAM_ERROR, "Event is illegal");
310         return nullptr;
311     }
312     if ((argc < 3) || IsMatchType(env, args[2], napi_undefined) || IsMatchType(env, args[2], napi_null)) {
313         if (!g_obj->RemoveAllCallback(type)) {
314             FI_HILOGE("Callback type is not exist");
315             return nullptr;
316         }
317         UnsubscribeCallback(env, type, event);
318         return nullptr;
319     }
320     FI_HILOGD("type:%{public}d, event:%{public}d", type, event);
321     if (!IsMatchType(env, args[2], napi_function)) {
322         ThrowErr(env, PARAM_ERROR, "get error callback type");
323         return nullptr;
324     }
325     if (!g_obj->Off(type, args[2])) {
326         FI_HILOGE("Not ready to unsubscribe for type:%{public}d", type);
327         return nullptr;
328     }
329     UnsubscribeCallback(env, type, event);
330     return nullptr;
331 }
332 
SubscribeDeviceStatusCallback(napi_env env,napi_callback_info info,napi_value handler,int32_t type,int32_t event,int32_t latency)333 napi_value DeviceStatusNapi::SubscribeDeviceStatusCallback(napi_env env, napi_callback_info info, napi_value handler,
334     int32_t type, int32_t event, int32_t latency)
335 {
336     CALL_DEBUG_ENTER;
337     if (g_obj == nullptr) {
338         g_obj = new (std::nothrow) DeviceStatusNapi(env);
339         CHKPP(g_obj);
340         FI_HILOGD("Didn't find object, so created it");
341     }
342     napi_wrap(env, nullptr, reinterpret_cast<void *>(g_obj),
343         [](napi_env env, void *data, void *hint) {
344             (void)env;
345             (void)hint;
346             DeviceStatusNapi *devicestatus = static_cast<DeviceStatusNapi *>(data);
347             delete devicestatus;
348         },
349         nullptr, nullptr);
350     if (!g_obj->On(type, handler, false)) {
351         FI_HILOGE("type:%{public}d already exists", type);
352         return nullptr;
353     }
354     std::lock_guard<std::mutex> guard(g_obj->mutex_);
355     auto callbackIter = callbacks_.find(type);
356     if (callbackIter != callbacks_.end()) {
357         FI_HILOGD("Callback exists");
358         return nullptr;
359     }
360     sptr<IRemoteDevStaCallback> callback = new (std::nothrow) DeviceStatusCallback(env);
361     CHKPP(callback);
362     int32_t subscribeRet = StationaryManager::GetInstance()->SubscribeCallback(static_cast<Type>(type),
363         static_cast<ActivityEvent>(event), static_cast<ReportLatencyNs>(latency), callback);
364     if (subscribeRet != RET_OK) {
365         ThrowErr(env, SERVICE_EXCEPTION, "On:Failed to SubscribeCallback");
366         return nullptr;
367     }
368     auto ret = callbacks_.insert(std::pair<int32_t, sptr<IRemoteDevStaCallback>>(type, callback));
369     if (!ret.second) {
370         FI_HILOGE("Failed to insert");
371     }
372     return nullptr;
373 }
374 
SubscribeDeviceStatus(napi_env env,napi_callback_info info)375 napi_value DeviceStatusNapi::SubscribeDeviceStatus(napi_env env, napi_callback_info info)
376 {
377     CALL_DEBUG_ENTER;
378     const auto [ret, handler, typeMode, event, latency] = CheckSubscribeParam(env, info);
379     if (!ret) {
380         FI_HILOGE("On:Failed to SubscribeDeviceStatus");
381         return nullptr;
382     }
383     int32_t type = ConvertTypeToInt(typeMode);
384     FI_HILOGD("type:%{public}d, event:%{public}d, latency:%{public}d", type, event, latency);
385     if ((type < Type::TYPE_ABSOLUTE_STILL) || (type > Type::TYPE_LID_OPEN)) {
386         ThrowErr(env, PARAM_ERROR, "Type is illegal");
387         return nullptr;
388     }
389     if ((event < ActivityEvent::ENTER) || (event > ActivityEvent::ENTER_EXIT)) {
390         ThrowErr(env, PARAM_ERROR, "Event is illegal");
391         return nullptr;
392     }
393     if ((latency < ReportLatencyNs::SHORT) || (latency > ReportLatencyNs::LONG)) {
394         ThrowErr(env, PARAM_ERROR, "Latency is illegal");
395         return nullptr;
396     }
397     return SubscribeDeviceStatusCallback(env, info, handler, type, event, latency);
398 }
399 
UnsubscribeDeviceStatus(napi_env env,napi_callback_info info)400 napi_value DeviceStatusNapi::UnsubscribeDeviceStatus(napi_env env, napi_callback_info info)
401 {
402     CALL_DEBUG_ENTER;
403     CHKPP(g_obj);
404     size_t argc = 3;
405     napi_value args[3] = { nullptr };
406     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
407     if (status != napi_ok) {
408         ThrowErr(env, PARAM_ERROR, "Bad parameters");
409         return nullptr;
410     }
411     if (argc < 2) {
412         ThrowErr(env, PARAM_ERROR, "Param number is invalid");
413         return nullptr;
414     }
415     return GetParameters(env, argc, args);
416 }
417 
UnsubscribeCallback(napi_env env,int32_t type,int32_t event)418 napi_value DeviceStatusNapi::UnsubscribeCallback(napi_env env, int32_t type, int32_t event)
419 {
420     CALL_DEBUG_ENTER;
421     std::lock_guard<std::mutex> guard(g_obj->mutex_);
422     auto callbackIter = callbacks_.find(type);
423     if (callbackIter == callbacks_.end()) {
424         NAPI_ASSERT(env, false, "No existed callback");
425         return nullptr;
426     }
427     int32_t unsubscribeRet = StationaryManager::GetInstance()->UnsubscribeCallback(static_cast<Type>(type),
428         static_cast<ActivityEvent>(event), callbackIter->second);
429     if (unsubscribeRet != RET_OK) {
430         ThrowErr(env, SERVICE_EXCEPTION, "Off:Failed to UnsubscribeCallback");
431     }
432     callbacks_.erase(type);
433     return nullptr;
434 }
435 
GetDeviceStatus(napi_env env,napi_callback_info info)436 napi_value DeviceStatusNapi::GetDeviceStatus(napi_env env, napi_callback_info info)
437 {
438     CALL_DEBUG_ENTER;
439     const auto [ret, handler, type] = CheckGetParam(env, info);
440     if (!ret) {
441         FI_HILOGE("Once:Failed to GetDeviceStatus");
442         return nullptr;
443     }
444     if (g_obj == nullptr) {
445         g_obj = new (std::nothrow) DeviceStatusNapi(env);
446         CHKPP(g_obj);
447         napi_wrap(env, nullptr, reinterpret_cast<void *>(g_obj),
448             [](napi_env env, void *data, void *hint) {
449                 (void)env;
450                 (void)hint;
451                 DeviceStatusNapi *devicestatus = static_cast<DeviceStatusNapi *>(data);
452                 delete devicestatus;
453             },
454             nullptr, nullptr);
455     }
456     if (!g_obj->On(type, handler, true)) {
457         FI_HILOGE("type:%{public}d already exists", type);
458         return nullptr;
459     }
460     Data devicestatusData = StationaryManager::GetInstance()->GetDeviceStatusData(static_cast<Type>(type));
461     if (devicestatusData.type == Type::TYPE_INVALID) {
462         ThrowErr(env, SERVICE_EXCEPTION, "Once:Failed to get device status data");
463     }
464     g_obj->OnDeviceStatusChangedDone(devicestatusData.type, devicestatusData.value, true);
465     g_obj->OffOnce(devicestatusData.type, handler);
466     return nullptr;
467 }
468 
EnumActivityEventConstructor(napi_env env,napi_callback_info info)469 napi_value DeviceStatusNapi::EnumActivityEventConstructor(napi_env env, napi_callback_info info)
470 {
471     CALL_DEBUG_ENTER;
472     napi_value thisArg = nullptr;
473     void *data = nullptr;
474     napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
475     if (status != napi_ok) {
476         FI_HILOGE("Failed to get_cb_info item");
477         return nullptr;
478     }
479     napi_value global = nullptr;
480     status = napi_get_global(env, &global);
481     if (status != napi_ok) {
482         FI_HILOGE("Failed to get_global item");
483         return nullptr;
484     }
485     return thisArg;
486 }
487 
DeclareEventTypeInterface(napi_env env,napi_value exports)488 napi_value DeviceStatusNapi::DeclareEventTypeInterface(napi_env env, napi_value exports)
489 {
490     CALL_DEBUG_ENTER;
491     napi_value enter = nullptr;
492     napi_status status = napi_create_int32(env, static_cast<int32_t>(ActivityEvent::ENTER), &enter);
493     if (status != napi_ok) {
494         FI_HILOGE("Failed to create ENTER item");
495         return nullptr;
496     }
497     napi_value exit = nullptr;
498     status = napi_create_int32(env, static_cast<int32_t>(ActivityEvent::EXIT), &exit);
499     if (status != napi_ok) {
500         FI_HILOGE("Failed to create EXIT item");
501         return nullptr;
502     }
503     napi_value enter_exit = nullptr;
504     status = napi_create_int32(env, static_cast<int32_t>(ActivityEvent::ENTER_EXIT), &enter_exit);
505     if (status != napi_ok) {
506         FI_HILOGE("Failed to create ENTER_EXIT item");
507         return nullptr;
508     }
509     napi_property_descriptor desc[] = {
510         DECLARE_NAPI_STATIC_PROPERTY("ENTER", enter),
511         DECLARE_NAPI_STATIC_PROPERTY("EXIT", exit),
512         DECLARE_NAPI_STATIC_PROPERTY("ENTER_EXIT", enter_exit)
513     };
514     napi_value result = nullptr;
515     status = napi_define_class(env, "ActivityEvent", NAPI_AUTO_LENGTH,
516         EnumActivityEventConstructor, nullptr, sizeof(desc) / sizeof(*desc), desc, &result);
517     if (status != napi_ok) {
518         FI_HILOGE("Failed to define_class item");
519         return nullptr;
520     }
521     status = napi_set_named_property(env, exports, "ActivityEvent", result);
522     if (status != napi_ok) {
523         FI_HILOGE("Failed to set_named_property item");
524         return nullptr;
525     }
526     return exports;
527 }
528 
Init(napi_env env,napi_value exports)529 napi_value DeviceStatusNapi::Init(napi_env env, napi_value exports)
530 {
531     CALL_DEBUG_ENTER;
532     napi_property_descriptor desc[] = {
533         DECLARE_NAPI_FUNCTION("on", SubscribeDeviceStatus),
534         DECLARE_NAPI_FUNCTION("off", UnsubscribeDeviceStatus),
535         DECLARE_NAPI_FUNCTION("once", GetDeviceStatus)
536     };
537     DeclareEventTypeInterface(env, exports);
538     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
539     return exports;
540 }
541 
542 EXTERN_C_START
543 /*
544  * function for module exports
545  */
DeviceStatusInit(napi_env env,napi_value exports)546 static napi_value DeviceStatusInit(napi_env env, napi_value exports)
547 {
548     CALL_DEBUG_ENTER;
549     napi_value ret = DeviceStatusNapi::Init(env, exports);
550     return ret;
551 }
552 EXTERN_C_END
553 
554 /*
555  * Module definition
556  */
557 static napi_module g_module = {
558     .nm_version = 1,
559     .nm_flags = 0,
560     .nm_filename = "stationary",
561     .nm_register_func = DeviceStatusInit,
562     .nm_modname = "stationary",
563     .nm_priv = (static_cast<void *>(0)),
564     .reserved = {0}
565 };
566 
567 /*
568  * Module registration
569  */
RegisterModule(void)570 extern "C" __attribute__((constructor)) void RegisterModule(void)
571 {
572     napi_module_register(&g_module);
573 }
574 } // namespace DeviceStatus
575 } // namespace Msdp
576 } // namespace OHOS
577