• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "napi_state_registry.h"
17 #include <map>
18 #include <utility>
19 #include "event_listener_manager.h"
20 #include "napi_parameter_util.h"
21 #include "napi_telephony_observer.h"
22 #include "napi_util.h"
23 #include "telephony_errors.h"
24 #include "telephony_log_wrapper.h"
25 #include "telephony_state_manager.h"
26 
27 namespace OHOS {
28 namespace Telephony {
29 namespace {
30 constexpr int32_t ARRAY_SIZE = 64;
31 const std::map<std::string_view, TelephonyUpdateEventType> eventMap {
32     {"networkStateChange", TelephonyUpdateEventType::EVENT_NETWORK_STATE_UPDATE},
33     {"callStateChange", TelephonyUpdateEventType::EVENT_CALL_STATE_UPDATE},
34     {"signalInfoChange", TelephonyUpdateEventType::EVENT_SIGNAL_STRENGTHS_UPDATE},
35     {"simStateChange", TelephonyUpdateEventType::EVENT_SIM_STATE_UPDATE},
36     {"cellInfoChange", TelephonyUpdateEventType::EVENT_CELL_INFO_UPDATE},
37     {"cellularDataConnectionStateChange", TelephonyUpdateEventType::EVENT_DATA_CONNECTION_UPDATE},
38     {"cellularDataFlowChange", TelephonyUpdateEventType::EVENT_CELLULAR_DATA_FLOW_UPDATE},
39 };
40 
GetEventType(std::string_view event)41 TelephonyUpdateEventType GetEventType(std::string_view event)
42 {
43     auto serched = eventMap.find(event);
44     return (serched != eventMap.end() ? serched->second : TelephonyUpdateEventType::NONE_EVENT_TYPE);
45 }
46 } // namespace
47 
NativeOn(napi_env env,void * data)48 static void NativeOn(napi_env env, void *data)
49 {
50     if (data == nullptr) {
51         TELEPHONY_LOGE("NativeOn data is nullptr");
52         return;
53     }
54     ObserverContext *asyncContext = static_cast<ObserverContext *>(data);
55     TELEPHONY_LOGI("NativeOn eventType = %{public}d", asyncContext->eventType);
56     EventListener listener {
57         env,
58         asyncContext->eventType,
59         asyncContext->slotId,
60         asyncContext->callbackRef,
61     };
62     std::optional<int32_t> result = EventListenerManager::RegisterEventListener(listener);
63     asyncContext->resolved = !result.has_value();
64     asyncContext->errorCode = result.value_or(ERROR_NONE);
65 }
66 
OnCallback(napi_env env,napi_status status,void * data)67 static void OnCallback(napi_env env, napi_status status, void *data)
68 {
69     if (data == nullptr) {
70         TELEPHONY_LOGE("OnCallback data is nullptr");
71         return;
72     }
73     ObserverContext *asyncContext = static_cast<ObserverContext *>(data);
74     if (!asyncContext->resolved) {
75         TELEPHONY_LOGE("OnCallback error by add observer failed");
76     }
77     napi_delete_async_work(env, asyncContext->work);
78     delete asyncContext;
79 }
80 
On(napi_env env,napi_callback_info info)81 static napi_value On(napi_env env, napi_callback_info info)
82 {
83     size_t parameterCount = 3;
84     napi_value parameters[] = {nullptr, nullptr, nullptr};
85     napi_get_cb_info(env, info, &parameterCount, parameters, nullptr, nullptr);
86 
87     std::unique_ptr<ObserverContext> asyncContext = std::make_unique<ObserverContext>();
88     if (asyncContext == nullptr) {
89         napi_throw_error(env, nullptr, "ObserverContext is nullptr!");
90         return nullptr;
91     }
92     std::array<char, ARRAY_SIZE> eventType {};
93     napi_value object = NapiUtil::CreateUndefined(env);
94     std::optional<NapiError> errCode;
95     if (parameterCount == std::size(parameters)) {
96         auto paraTuple = std::make_tuple(std::data(eventType), &object, &asyncContext->callbackRef);
97         errCode = MatchParameters(env, parameters, parameterCount, paraTuple);
98         if (!errCode.has_value()) {
99             napi_value slotId = NapiUtil::GetNamedProperty(env, object, "slotId");
100             if (slotId) {
101                 NapiValueToCppValue(env, slotId, napi_number, &asyncContext->slotId);
102                 TELEPHONY_LOGI("sate registry on  slotId = %{public}d", asyncContext->slotId);
103             }
104         }
105     } else {
106         auto paraTuple = std::make_tuple(std::data(eventType), &asyncContext->callbackRef);
107         errCode = MatchParameters(env, parameters, parameterCount, paraTuple);
108     }
109 
110     if (errCode.has_value()) {
111         const std::string errMsg = "type of input parameters error : " + std::to_string(errCode.value());
112         napi_throw_error(env, nullptr, errMsg.c_str());
113         return nullptr;
114     }
115 
116     asyncContext->eventType = GetEventType(eventType.data());
117     if (asyncContext->eventType != TelephonyUpdateEventType::NONE_EVENT_TYPE) {
118         return NapiUtil::HandleAsyncWork(env, asyncContext.release(), "On", NativeOn, OnCallback);
119     } else {
120         napi_throw_error(env, "1", "first parameter \"type\" mismatch with the observer.d.ts");
121     }
122     return NapiUtil::CreateUndefined(env);
123 }
124 
NativeOff(napi_env env,void * data)125 static void NativeOff(napi_env env, void *data)
126 {
127     if (data == nullptr) {
128         TELEPHONY_LOGE("NativeOff data is nullptr");
129         return;
130     }
131     ObserverContext *asyncContext = static_cast<ObserverContext *>(data);
132     std::optional<int32_t> result =
133         EventListenerManager::UnregisterEventListener(asyncContext->slotId, asyncContext->eventType);
134     asyncContext->resolved = !result.has_value();
135     asyncContext->errorCode = result.value_or(ERROR_NONE);
136 }
137 
OffCallback(napi_env env,napi_status status,void * data)138 static void OffCallback(napi_env env, napi_status status, void *data)
139 {
140     if (data == nullptr) {
141         TELEPHONY_LOGE("OffCallback data is nullptr");
142         return;
143     }
144     ObserverContext *asyncContext = static_cast<ObserverContext *>(data);
145     EventListenerManager::RemoveListener(asyncContext->eventType);
146     if (!asyncContext->resolved) {
147         TELEPHONY_LOGE("OffCallback error by remove observer failed");
148     }
149     napi_delete_async_work(env, asyncContext->work);
150     delete asyncContext;
151 }
152 
Off(napi_env env,napi_callback_info info)153 static napi_value Off(napi_env env, napi_callback_info info)
154 {
155     size_t parameterCount = 2;
156     napi_value parameters[] = {nullptr, nullptr};
157     napi_get_cb_info(env, info, &parameterCount, parameters, nullptr, nullptr);
158 
159     std::array<char, ARRAY_SIZE> eventType {};
160     std::unique_ptr<ObserverContext> asyncContext = std::make_unique<ObserverContext>();
161     if (asyncContext == nullptr) {
162         napi_throw_error(env, nullptr, "ObserverContext is nullptr!");
163         return nullptr;
164     }
165     auto paraTuple = std::make_tuple(std::data(eventType), &asyncContext->callbackRef);
166     std::optional<NapiError> errCode = MatchParameters(env, parameters, parameterCount, paraTuple);
167     if (errCode.has_value()) {
168         const std::string errMsg = "type of input parameters error : " + std::to_string(errCode.value());
169         napi_throw_error(env, nullptr, errMsg.c_str());
170         return nullptr;
171     }
172 
173     asyncContext->eventType = GetEventType(eventType.data());
174     if (asyncContext->eventType != TelephonyUpdateEventType::NONE_EVENT_TYPE) {
175         return NapiUtil::HandleAsyncWork(env, asyncContext.release(), "Off", NativeOff, OffCallback);
176     } else {
177         napi_throw_error(env, "1", "first parameter \"type\" mismatch with the @ohos.telephony.observer.d.ts");
178         return NapiUtil::CreateUndefined(env);
179     }
180 }
181 
182 EXTERN_C_START
InitNapiStateRegistry(napi_env env,napi_value exports)183 napi_value InitNapiStateRegistry(napi_env env, napi_value exports)
184 {
185     napi_property_descriptor desc[] = {
186         DECLARE_NAPI_FUNCTION("on", On),
187         DECLARE_NAPI_FUNCTION("off", Off),
188     };
189     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
190     return exports;
191 }
192 EXTERN_C_END
193 
194 static napi_module _stateRegistryModule = {
195     .nm_version = 1,
196     .nm_flags = 0,
197     .nm_filename = nullptr,
198     .nm_register_func = InitNapiStateRegistry,
199     .nm_modname = "telephony.observer",
200     .nm_priv = ((void *)0),
201     .reserved = {(void *)0},
202 };
203 
RegisterTelephonyObserverModule(void)204 extern "C" __attribute__((constructor)) void RegisterTelephonyObserverModule(void)
205 {
206     napi_module_register(&_stateRegistryModule);
207 }
208 } // namespace Telephony
209 } // namespace OHOS
210