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 }
105 
OnDeviceStatusChangedDone(int32_t type, int32_t value, bool isOnce)106 void DeviceStatusNapi::OnDeviceStatusChangedDone(int32_t type, int32_t value, bool isOnce)
107 {
108     CALL_DEBUG_ENTER;
109     FI_HILOGD("value:%{public}d", value);
110     OnEvent(type, ARG_1, value, isOnce);
111 }
112 
ConvertTypeToInt(const std::string &type)113 int32_t DeviceStatusNapi::ConvertTypeToInt(const std::string &type)
114 {
115     if (type == "absoluteStill") {
116         return Type::TYPE_ABSOLUTE_STILL;
117     } else if (type == "horizontalPosition") {
118         return Type::TYPE_HORIZONTAL_POSITION;
119     } else if (type == "verticalPosition") {
120         return Type::TYPE_VERTICAL_POSITION;
121     } else if (type == "still") {
122         return Type::TYPE_STILL;
123     } else if (type == "relativeStill") {
124         return Type::TYPE_RELATIVE_STILL;
125     } else if (type == "carBluetooth") {
126         return Type::TYPE_CAR_BLUETOOTH;
127     } else {
128         return Type::TYPE_INVALID;
129     }
130 }
131 
CheckArguments(napi_env env, napi_callback_info info)132 bool DeviceStatusNapi::CheckArguments(napi_env env, napi_callback_info info)
133 {
134     CALL_DEBUG_ENTER;
135     int32_t arr[ARG_4] = { 0 };
136     size_t argc = ARG_4;
137     napi_value args[ARG_4] = { nullptr };
138     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
139     if (status != napi_ok) {
140         FI_HILOGE("Failed to get_cb_info");
141         return false;
142     }
143     for (size_t i = 0; i < ARG_4; i++) {
144         napi_valuetype valueType = napi_undefined;
145         status = napi_typeof(env, args[i], &valueType);
146         if (status != napi_ok) {
147             FI_HILOGE("Failed to get valueType");
148             return false;
149         }
150         FI_HILOGD("valueType:%{public}d", valueType);
151         arr[i] = valueType;
152     }
153     if (arr[ARG_0] != napi_string || arr[ARG_1] != napi_number || arr[ARG_2] != napi_number ||
154         arr[ARG_3] != napi_function) {
155         FI_HILOGE("Failed to get arguements");
156         return false;
157     }
158     return true;
159 }
160 
IsMatchType(napi_env env, napi_value value, napi_valuetype type)161 bool DeviceStatusNapi::IsMatchType(napi_env env, napi_value value, napi_valuetype type)
162 {
163     CALL_DEBUG_ENTER;
164     napi_valuetype valueType = napi_undefined;
165     napi_status status = napi_typeof(env, value, &valueType);
166     if (status != napi_ok) {
167         FI_HILOGE("Failed to get valueType");
168         return false;
169     }
170     return valueType == type;
171 }
172 
CheckGetArguments(napi_env env, napi_callback_info info)173 bool DeviceStatusNapi::CheckGetArguments(napi_env env, napi_callback_info info)
174 {
175     CALL_DEBUG_ENTER;
176     int32_t arr[ARG_2] = { 0 };
177     size_t argc = ARG_2;
178     napi_value args[ARG_2] = { nullptr };
179     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
180     if (status != napi_ok) {
181         FI_HILOGE("Failed to get_cb_info");
182         return false;
183     }
184     for (size_t i = 0; i < ARG_2; i++) {
185         napi_valuetype valueType = napi_undefined;
186         status = napi_typeof(env, args[i], &valueType);
187         if (status != napi_ok) {
188             FI_HILOGE("Failed to get valueType");
189             return false;
190         }
191         FI_HILOGD("valueType:%{public}d", valueType);
192         arr[i] = valueType;
193     }
194     if (arr[ARG_0] != napi_string || arr[ARG_1] != napi_function) {
195         FI_HILOGE("Failed to get arguements");
196         return false;
197     }
198     return true;
199 }
200 
CheckSubscribeParam(napi_env env, napi_callback_info info)201 std::tuple<bool, napi_value, std::string, int32_t, int32_t> DeviceStatusNapi::CheckSubscribeParam(napi_env env,
202     napi_callback_info info)
203 {
204     std::tuple<bool, napi_value, std::string, int32_t, int32_t> result { false, nullptr, "", -1, -1 };
205     size_t argc = ARG_4;
206     napi_value args[ARG_4] = { nullptr };
207     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
208     if ((status != napi_ok) || (argc < ARG_4)) {
209         ThrowErr(env, PARAM_ERROR, "Bad parameters");
210         return result;
211     }
212     if (!CheckArguments(env, info)) {
213         ThrowErr(env, PARAM_ERROR, "Failed to get on arguments");
214         return result;
215     }
216     size_t modLen = 0;
217     status = napi_get_value_string_utf8(env, args[ARG_0], nullptr, 0, &modLen);
218     if (status != napi_ok) {
219         ThrowErr(env, PARAM_ERROR, "Failed to get string item");
220         return result;
221     }
222     char mode[NAPI_BUF_LENGTH] = { 0 };
223     status = napi_get_value_string_utf8(env, args[ARG_0], mode, modLen + 1, &modLen);
224     if (status != napi_ok) {
225         ThrowErr(env, PARAM_ERROR, "Failed to get mode");
226         return result;
227     }
228     int32_t eventMode = 0;
229     status = napi_get_value_int32(env, args[ARG_1], &eventMode);
230     if (status != napi_ok) {
231         ThrowErr(env, PARAM_ERROR, "Failed to get event value item");
232         return result;
233     }
234     int32_t latencyMode = 0;
235     status = napi_get_value_int32(env, args[ARG_2], &latencyMode);
236     if (status != napi_ok) {
237         ThrowErr(env, PARAM_ERROR, "Failed to get latency value item");
238         return result;
239     }
240     latencyMode = latencyMode / NANO;
241     return std::make_tuple(true, args[ARG_3], std::string(mode), eventMode, latencyMode);
242 }
243 
CheckGetParam(napi_env env, napi_callback_info info)244 std::tuple<bool, napi_value, int32_t> DeviceStatusNapi::CheckGetParam(napi_env env, napi_callback_info info)
245 {
246     std::tuple<bool, napi_value, int32_t> result { false, nullptr, -1 };
247     size_t argc = ARG_2;
248     napi_value args[ARG_2] = { nullptr };
249     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
250     if ((status != napi_ok) || (argc < ARG_2)) {
251         ThrowErr(env, PARAM_ERROR, "Bad parameters");
252         return result;
253     }
254     if (!CheckGetArguments(env, info)) {
255         ThrowErr(env, PARAM_ERROR, "Failed to get once arguments");
256         return result;
257     }
258     size_t modLen = 0;
259     napi_status napiStatus = napi_get_value_string_utf8(env, args[ARG_0], nullptr, 0, &modLen);
260     if (napiStatus != napi_ok) {
261         ThrowErr(env, PARAM_ERROR, "Failed to get string item");
262         return result;
263     }
264     char mode[NAPI_BUF_LENGTH] = { 0 };
265     napiStatus = napi_get_value_string_utf8(env, args[ARG_0], mode, modLen + 1, &modLen);
266     if (napiStatus != napi_ok) {
267         ThrowErr(env, PARAM_ERROR, "Failed to get mode");
268         return result;
269     }
270     int32_t type = ConvertTypeToInt(mode);
271     if ((type < Type::TYPE_ABSOLUTE_STILL) || (type > Type::TYPE_LID_OPEN)) {
272         ThrowErr(env, PARAM_ERROR, "Type is illegal");
273         return result;
274     }
275     return std::make_tuple(true, args[ARG_1], type);
276 }
277 
GetParameters(napi_env env, size_t argc, const napi_value* args)278 napi_value DeviceStatusNapi::GetParameters(napi_env env, size_t argc, const napi_value* args)
279 {
280     CALL_DEBUG_ENTER;
281     size_t modLen = 0;
282     napi_status status = napi_get_value_string_utf8(env, args[0], nullptr, 0, &modLen);
283     if (status != napi_ok) {
284         ThrowErr(env, PARAM_ERROR, "Failed to get string item");
285         return nullptr;
286     }
287     char mode[NAPI_BUF_LENGTH] = { 0 };
288     status = napi_get_value_string_utf8(env, args[0], mode, modLen + 1, &modLen);
289     if (status != napi_ok) {
290         ThrowErr(env, PARAM_ERROR, "Failed to get mode");
291         return nullptr;
292     }
293     int32_t type = DeviceStatusNapi::ConvertTypeToInt(mode);
294     if ((type < Type::TYPE_ABSOLUTE_STILL) || (type > Type::TYPE_LID_OPEN)) {
295         ThrowErr(env, PARAM_ERROR, "Type is illegal");
296         return nullptr;
297     }
298     int32_t event = 0;
299     status = napi_get_value_int32(env, args[1], &event);
300     if (status != napi_ok) {
301         ThrowErr(env, PARAM_ERROR, "Failed to get int32 item");
302         return nullptr;
303     }
304     if ((event < ActivityEvent::ENTER) || (event > ActivityEvent::ENTER_EXIT)) {
305         ThrowErr(env, PARAM_ERROR, "Event is illegal");
306         return nullptr;
307     }
308     if ((argc < 3) || IsMatchType(env, args[2], napi_undefined) || IsMatchType(env, args[2], napi_null)) {
309         if (!g_obj->RemoveAllCallback(type)) {
310             FI_HILOGE("Callback type is not exist");
311             return nullptr;
312         }
313         UnsubscribeCallback(env, type, event);
314         return nullptr;
315     }
316     FI_HILOGD("type:%{public}d, event:%{public}d", type, event);
317     if (!IsMatchType(env, args[2], napi_function)) {
318         ThrowErr(env, PARAM_ERROR, "get error callback type");
319         return nullptr;
320     }
321     if (!g_obj->Off(type, args[2])) {
322         FI_HILOGE("Not ready to unsubscribe for type:%{public}d", type);
323         return nullptr;
324     }
325     UnsubscribeCallback(env, type, event);
326     return nullptr;
327 }
328 
SubscribeDeviceStatusCallback(napi_env env, napi_callback_info info, napi_value handler, int32_t type, int32_t event, int32_t latency)329 napi_value DeviceStatusNapi::SubscribeDeviceStatusCallback(napi_env env, napi_callback_info info, napi_value handler,
330     int32_t type, int32_t event, int32_t latency)
331 {
332     CALL_DEBUG_ENTER;
333     if (g_obj == nullptr) {
334         g_obj = new (std::nothrow) DeviceStatusNapi(env);
335         CHKPP(g_obj);
336         FI_HILOGD("Didn't find object, so created it");
337     }
338     napi_value thisArg = nullptr;
339     void *data = nullptr;
340     napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
341     if (status != napi_ok) {
342         FI_HILOGE("Failed to get_cb_info item");
343         delete g_obj;
344         g_obj = nullptr;
345         return nullptr;
346     }
347     status = napi_wrap(env, thisArg, reinterpret_cast<void *>(g_obj),
348         [](napi_env env, void *data, void *hint) {
349             (void)env;
350             (void)hint;
351             CHKPV(data);
352             DeviceStatusNapi *devicestatus = static_cast<DeviceStatusNapi *>(data);
353             delete devicestatus;
354             g_obj = nullptr;
355         },
356         nullptr, nullptr);
357     if (status != napi_ok) {
358         FI_HILOGE("napi_wrap failed");
359         delete g_obj;
360         g_obj = nullptr;
361         return nullptr;
362     }
363     if (!g_obj->On(type, handler, false)) {
364         FI_HILOGE("type:%{public}d already exists", type);
365         return nullptr;
366     }
367     std::lock_guard<std::mutex> guard(g_obj->mutex_);
368     auto callbackIter = callbacks_.find(type);
369     if (callbackIter != callbacks_.end()) {
370         FI_HILOGD("Callback exists");
371         return nullptr;
372     }
373     sptr<IRemoteDevStaCallback> callback = new (std::nothrow) DeviceStatusCallback(env);
374     CHKPP(callback);
375     int32_t subscribeRet = StationaryManager::GetInstance()->SubscribeCallback(static_cast<Type>(type),
376         static_cast<ActivityEvent>(event), static_cast<ReportLatencyNs>(latency), callback);
377     if (subscribeRet != RET_OK) {
378         ThrowErr(env, SERVICE_EXCEPTION, "On:Failed to SubscribeCallback");
379         return nullptr;
380     }
381     auto ret = callbacks_.insert(std::pair<int32_t, sptr<IRemoteDevStaCallback>>(type, callback));
382     if (!ret.second) {
383         FI_HILOGE("Failed to insert");
384     }
385     return nullptr;
386 }
387 
SubscribeDeviceStatus(napi_env env, napi_callback_info info)388 napi_value DeviceStatusNapi::SubscribeDeviceStatus(napi_env env, napi_callback_info info)
389 {
390     CALL_DEBUG_ENTER;
391     const auto [ret, handler, typeMode, event, latency] = CheckSubscribeParam(env, info);
392     if (!ret) {
393         FI_HILOGE("On:Failed to SubscribeDeviceStatus");
394         return nullptr;
395     }
396     int32_t type = ConvertTypeToInt(typeMode);
397     FI_HILOGD("type:%{public}d, event:%{public}d, latency:%{public}d", type, event, latency);
398     if ((type < Type::TYPE_ABSOLUTE_STILL) || (type > Type::TYPE_LID_OPEN)) {
399         ThrowErr(env, PARAM_ERROR, "Type is illegal");
400         return nullptr;
401     }
402     if ((event < ActivityEvent::ENTER) || (event > ActivityEvent::ENTER_EXIT)) {
403         ThrowErr(env, PARAM_ERROR, "Event is illegal");
404         return nullptr;
405     }
406     if ((latency < ReportLatencyNs::SHORT) || (latency > ReportLatencyNs::LONG)) {
407         ThrowErr(env, PARAM_ERROR, "Latency is illegal");
408         return nullptr;
409     }
410     return SubscribeDeviceStatusCallback(env, info, handler, type, event, latency);
411 }
412 
UnsubscribeDeviceStatus(napi_env env, napi_callback_info info)413 napi_value DeviceStatusNapi::UnsubscribeDeviceStatus(napi_env env, napi_callback_info info)
414 {
415     CALL_DEBUG_ENTER;
416     CHKPP(g_obj);
417     size_t argc = 3;
418     napi_value args[3] = { nullptr };
419     napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
420     if (status != napi_ok) {
421         ThrowErr(env, PARAM_ERROR, "Bad parameters");
422         return nullptr;
423     }
424     if (argc < 2) {
425         ThrowErr(env, PARAM_ERROR, "Param number is invalid");
426         return nullptr;
427     }
428     return GetParameters(env, argc, args);
429 }
430 
UnsubscribeCallback(napi_env env, int32_t type, int32_t event)431 napi_value DeviceStatusNapi::UnsubscribeCallback(napi_env env, int32_t type, int32_t event)
432 {
433     CALL_DEBUG_ENTER;
434     std::lock_guard<std::mutex> guard(g_obj->mutex_);
435     auto callbackIter = callbacks_.find(type);
436     if (callbackIter == callbacks_.end()) {
437         NAPI_ASSERT(env, false, "No existed callback");
438         return nullptr;
439     }
440     int32_t unsubscribeRet = StationaryManager::GetInstance()->UnsubscribeCallback(static_cast<Type>(type),
441         static_cast<ActivityEvent>(event), callbackIter->second);
442     if (unsubscribeRet != RET_OK) {
443         ThrowErr(env, SERVICE_EXCEPTION, "Off:Failed to UnsubscribeCallback");
444     }
445     callbacks_.erase(type);
446     return nullptr;
447 }
448 
GetDeviceStatus(napi_env env, napi_callback_info info)449 napi_value DeviceStatusNapi::GetDeviceStatus(napi_env env, napi_callback_info info)
450 {
451     CALL_DEBUG_ENTER;
452     const auto [ret, handler, type] = CheckGetParam(env, info);
453     if (!ret) {
454         FI_HILOGE("Once:Failed to GetDeviceStatus");
455         return nullptr;
456     }
457     napi_value thisArg = nullptr;
458     void *data = nullptr;
459     napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
460     if (status != napi_ok) {
461         FI_HILOGE("Failed to get_cb_info item");
462         delete g_obj;
463         g_obj = nullptr;
464         return nullptr;
465     }
466     if (g_obj == nullptr) {
467         g_obj = new (std::nothrow) DeviceStatusNapi(env);
468         CHKPP(g_obj);
469         status = napi_wrap(env, thisArg, reinterpret_cast<void *>(g_obj),
470             [](napi_env env, void *data, void *hint) {
471                 (void)env;
472                 (void)hint;
473                 CHKPV(data);
474                 DeviceStatusNapi *devicestatus = static_cast<DeviceStatusNapi *>(data);
475                 delete devicestatus;
476                 g_obj = nullptr;
477             },
478             nullptr, nullptr);
479         if (status != napi_ok) {
480             FI_HILOGE("napi_wrap failed");
481             delete g_obj;
482             g_obj = nullptr;
483             return nullptr;
484         }
485     }
486     if (!g_obj->On(type, handler, true)) {
487         FI_HILOGE("type:%{public}d already exists", type);
488         return nullptr;
489     }
490     Data devicestatusData = StationaryManager::GetInstance()->GetDeviceStatusData(static_cast<Type>(type));
491     if (devicestatusData.type == Type::TYPE_INVALID) {
492         ThrowErr(env, SERVICE_EXCEPTION, "Once:Failed to get device status data");
493     }
494     g_obj->OnDeviceStatusChangedDone(devicestatusData.type, devicestatusData.value, true);
495     g_obj->OffOnce(devicestatusData.type, handler);
496     return nullptr;
497 }
498 
EnumActivityEventConstructor(napi_env env, napi_callback_info info)499 napi_value DeviceStatusNapi::EnumActivityEventConstructor(napi_env env, napi_callback_info info)
500 {
501     CALL_DEBUG_ENTER;
502     napi_value thisArg = nullptr;
503     void *data = nullptr;
504     napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
505     if (status != napi_ok) {
506         FI_HILOGE("Failed to get_cb_info item");
507         return nullptr;
508     }
509     napi_value global = nullptr;
510     status = napi_get_global(env, &global);
511     if (status != napi_ok) {
512         FI_HILOGE("Failed to get_global item");
513         return nullptr;
514     }
515     return thisArg;
516 }
517 
DeclareEventTypeInterface(napi_env env, napi_value exports)518 napi_value DeviceStatusNapi::DeclareEventTypeInterface(napi_env env, napi_value exports)
519 {
520     CALL_DEBUG_ENTER;
521     napi_value enter = nullptr;
522     napi_status status = napi_create_int32(env, static_cast<int32_t>(ActivityEvent::ENTER), &enter);
523     if (status != napi_ok) {
524         FI_HILOGE("Failed to create ENTER item");
525         return nullptr;
526     }
527     napi_value exit = nullptr;
528     status = napi_create_int32(env, static_cast<int32_t>(ActivityEvent::EXIT), &exit);
529     if (status != napi_ok) {
530         FI_HILOGE("Failed to create EXIT item");
531         return nullptr;
532     }
533     napi_value enter_exit = nullptr;
534     status = napi_create_int32(env, static_cast<int32_t>(ActivityEvent::ENTER_EXIT), &enter_exit);
535     if (status != napi_ok) {
536         FI_HILOGE("Failed to create ENTER_EXIT item");
537         return nullptr;
538     }
539     napi_property_descriptor desc[] = {
540         DECLARE_NAPI_STATIC_PROPERTY("ENTER", enter),
541         DECLARE_NAPI_STATIC_PROPERTY("EXIT", exit),
542         DECLARE_NAPI_STATIC_PROPERTY("ENTER_EXIT", enter_exit)
543     };
544     napi_value result = nullptr;
545     status = napi_define_class(env, "ActivityEvent", NAPI_AUTO_LENGTH,
546         EnumActivityEventConstructor, nullptr, sizeof(desc) / sizeof(*desc), desc, &result);
547     if (status != napi_ok) {
548         FI_HILOGE("Failed to define_class item");
549         return nullptr;
550     }
551     status = napi_set_named_property(env, exports, "ActivityEvent", result);
552     if (status != napi_ok) {
553         FI_HILOGE("Failed to set_named_property item");
554         return nullptr;
555     }
556     return exports;
557 }
558 
Init(napi_env env, napi_value exports)559 napi_value DeviceStatusNapi::Init(napi_env env, napi_value exports)
560 {
561     CALL_DEBUG_ENTER;
562     napi_property_descriptor desc[] = {
563         DECLARE_NAPI_FUNCTION("on", SubscribeDeviceStatus),
564         DECLARE_NAPI_FUNCTION("off", UnsubscribeDeviceStatus),
565         DECLARE_NAPI_FUNCTION("once", GetDeviceStatus)
566     };
567     DeclareEventTypeInterface(env, exports);
568     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
569     return exports;
570 }
571 
572 EXTERN_C_START
573 /*
574  * function for module exports
575  */
DeviceStatusInit(napi_env env, napi_value exports)576 static napi_value DeviceStatusInit(napi_env env, napi_value exports)
577 {
578     CALL_DEBUG_ENTER;
579     napi_value ret = DeviceStatusNapi::Init(env, exports);
580     return ret;
581 }
582 EXTERN_C_END
583 
584 /*
585  * Module definition
586  */
587 static napi_module g_module = {
588     .nm_version = 1,
589     .nm_flags = 0,
590     .nm_filename = "stationary",
591     .nm_register_func = DeviceStatusInit,
592     .nm_modname = "stationary",
593     .nm_priv = (static_cast<void *>(0)),
594     .reserved = {0}
595 };
596 
597 /*
598  * Module registration
599  */
RegisterModule(void)600 extern "C" __attribute__((constructor)) void RegisterModule(void)
601 {
602     napi_module_register(&g_module);
603 }
604 } // namespace DeviceStatus
605 } // namespace Msdp
606 } // namespace OHOS
607