1 /*
2 * Copyright (C) 2022-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 #include "napi_ims_reg_info_callback_manager.h"
16
17 #include "core_service_client.h"
18 #include "napi_util.h"
19 #include "singleton.h"
20 #include "telephony_errors.h"
21 #include "telephony_log_wrapper.h"
22
23 namespace OHOS {
24 namespace Telephony {
RegisterImsRegStateCallback(ImsRegStateCallback & stateCallback)25 int32_t NapiImsRegInfoCallbackManager::RegisterImsRegStateCallback(ImsRegStateCallback &stateCallback)
26 {
27 int32_t slotId = stateCallback.slotId;
28 ImsServiceType imsSrvType = stateCallback.imsSrvType;
29 stateCallback.imsCallback = new NapiImsRegInfoCallback();
30 if (stateCallback.imsCallback == nullptr) {
31 TELEPHONY_LOGE("[slot%{public}d] Creat ImsRegInfoCallback failed, type %{public}d,", slotId, imsSrvType);
32 return TELEPHONY_ERR_REGISTER_CALLBACK_FAIL;
33 }
34 if (InsertImsRegCallback(slotId, imsSrvType, stateCallback) != TELEPHONY_SUCCESS) {
35 TELEPHONY_LOGI("[slot%{public}d] Ignore register action, since callback is existent, type %{public}d", slotId,
36 imsSrvType);
37 return TELEPHONY_SUCCESS;
38 }
39 int32_t ret = DelayedRefSingleton<CoreServiceClient>::GetInstance().RegisterImsRegInfoCallback(
40 slotId, imsSrvType, stateCallback.imsCallback);
41 if (ret == TELEPHONY_SUCCESS) {
42 TELEPHONY_LOGI(
43 "[slot%{public}d] Register imsRegState callback successfully, type %{public}d", slotId, imsSrvType);
44 } else {
45 if (stateCallback.imsCallback != nullptr) {
46 stateCallback.imsCallback = nullptr;
47 }
48 RemoveImsRegCallback(slotId, imsSrvType);
49 TELEPHONY_LOGE("[slot%{public}d] Register imsRegState callback failed, type %{public}d, ret %{public}d", slotId,
50 imsSrvType, ret);
51 }
52 return ret;
53 }
54
UnregisterImsRegStateCallback(napi_env env,int32_t slotId,ImsServiceType imsSrvType)55 int32_t NapiImsRegInfoCallbackManager::UnregisterImsRegStateCallback(
56 napi_env env, int32_t slotId, ImsServiceType imsSrvType)
57 {
58 int32_t ret = TELEPHONY_SUCCESS;
59 RemoveImsRegCallback(slotId, imsSrvType);
60 ret = DelayedRefSingleton<CoreServiceClient>::GetInstance().UnregisterImsRegInfoCallback(slotId, imsSrvType);
61 TELEPHONY_LOGI(
62 "[slot%{public}d] Unregister imsRegState callback successfully, type %{public}d", slotId, imsSrvType);
63 return ret;
64 }
65
InsertImsRegCallback(int32_t slotId,ImsServiceType imsSrvType,ImsRegStateCallback & stateCallback)66 int32_t NapiImsRegInfoCallbackManager::InsertImsRegCallback(
67 int32_t slotId, ImsServiceType imsSrvType, ImsRegStateCallback &stateCallback)
68 {
69 std::lock_guard<std::mutex> lock(mutex_);
70 for (auto iter : listImsRegStateCallback_) {
71 if ((iter.slotId == slotId) && (iter.imsSrvType == imsSrvType)) {
72 TELEPHONY_LOGD("[slot%{public}d] callback is existent", slotId);
73 return TELEPHONY_ERROR;
74 }
75 }
76 listImsRegStateCallback_.push_back(stateCallback);
77 return TELEPHONY_SUCCESS;
78 }
79
RemoveImsRegCallback(int32_t slotId,ImsServiceType imsSrvType)80 void NapiImsRegInfoCallbackManager::RemoveImsRegCallback(int32_t slotId, ImsServiceType imsSrvType)
81 {
82 std::lock_guard<std::mutex> lock(mutex_);
83 auto iter = listImsRegStateCallback_.begin();
84 for (; iter != listImsRegStateCallback_.end(); ++iter) {
85 if ((iter->slotId == slotId) && (iter->imsSrvType == imsSrvType)) {
86 if (iter->imsCallback != nullptr) {
87 iter->imsCallback = nullptr;
88 }
89 listImsRegStateCallback_.erase(iter);
90 break;
91 }
92 }
93 }
94
ReportImsRegInfo(int32_t slotId,ImsServiceType imsSrvType,const ImsRegInfo & info)95 int32_t NapiImsRegInfoCallbackManager::ReportImsRegInfo(
96 int32_t slotId, ImsServiceType imsSrvType, const ImsRegInfo &info)
97 {
98 int32_t ret = TELEPHONY_ERROR;
99 std::lock_guard<std::mutex> lock(mutex_);
100 for (auto iter : listImsRegStateCallback_) {
101 if ((iter.slotId == slotId) && (iter.imsSrvType == imsSrvType)) {
102 ret = ReportImsRegInfoInner(iter, info);
103 break;
104 }
105 }
106 if (ret != TELEPHONY_SUCCESS) {
107 TELEPHONY_LOGE("[slot%{public}d] Report imsRegState callback failed, type %{public}d, ret %{public}d", slotId,
108 imsSrvType, ret);
109 return ret;
110 }
111 TELEPHONY_LOGI("[slot%{public}d] Report imsRegState callback successfully, type %{public}d", slotId, imsSrvType);
112 return ret;
113 }
114
ReportImsRegInfoInner(const ImsRegStateCallback & stateCallback,const ImsRegInfo & info)115 int32_t NapiImsRegInfoCallbackManager::ReportImsRegInfoInner(
116 const ImsRegStateCallback &stateCallback, const ImsRegInfo &info)
117 {
118 uv_loop_s *loop = nullptr;
119 #if NAPI_VERSION >= 2
120 napi_get_uv_event_loop(stateCallback.env, &loop);
121 #endif
122 ImsStateWorker *dataWorker = new ImsStateWorker();
123 dataWorker->info = info;
124 dataWorker->callback = stateCallback;
125 uv_work_t *work = new uv_work_t();
126 work->data = (void *)(dataWorker);
127 int32_t resultCode =
128 uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, ReportImsRegInfoWork, uv_qos_default);
129 if (resultCode != TELEPHONY_SUCCESS) {
130 delete dataWorker;
131 dataWorker = nullptr;
132 TELEPHONY_LOGE("ReportImsRegInfo failed, result: %{public}d", resultCode);
133 delete work;
134 work = nullptr;
135 return TELEPHONY_ERROR;
136 }
137 return TELEPHONY_SUCCESS;
138 }
139
ReportImsRegInfoWork(uv_work_t * work,int32_t status)140 void NapiImsRegInfoCallbackManager::ReportImsRegInfoWork(uv_work_t *work, int32_t status)
141 {
142 ImsStateWorker *dataWorkerData = (ImsStateWorker *)work->data;
143 int32_t ret = ReportImsRegInfo(dataWorkerData->info, dataWorkerData->callback);
144 delete dataWorkerData;
145 dataWorkerData = nullptr;
146 delete work;
147 work = nullptr;
148 if (ret != TELEPHONY_SUCCESS) {
149 TELEPHONY_LOGE("ReportImsRegInfo failed, result: %{public}d", ret);
150 return;
151 }
152 TELEPHONY_LOGI("ReportImsRegInfo successfully");
153 }
154
ReportImsRegInfo(const ImsRegInfo & info,const ImsRegStateCallback & stateCallback)155 int32_t NapiImsRegInfoCallbackManager::ReportImsRegInfo(
156 const ImsRegInfo &info, const ImsRegStateCallback &stateCallback)
157 {
158 napi_env env = stateCallback.env;
159 napi_handle_scope scope = nullptr;
160 napi_open_handle_scope(env, &scope);
161 if (scope == nullptr) {
162 TELEPHONY_LOGE("scope is nullptr");
163 napi_close_handle_scope(env, scope);
164 return TELEPHONY_ERROR;
165 }
166 napi_value callbackValues[CALLBACK_VALUES_SIZE] = { 0 };
167 napi_create_object(env, &callbackValues[0]);
168 NapiUtil::SetPropertyInt32(env, callbackValues[0], "imsRegState", static_cast<int32_t>(info.imsRegState));
169 NapiUtil::SetPropertyInt32(env, callbackValues[0], "imsRegTech", static_cast<int32_t>(info.imsRegTech));
170 napi_value thisVar = nullptr;
171 napi_get_reference_value(env, stateCallback.thisVar, &thisVar);
172 napi_value callbackFunc = nullptr;
173 napi_get_reference_value(env, stateCallback.callbackRef, &callbackFunc);
174 if (callbackFunc == nullptr) {
175 TELEPHONY_LOGE("callbackFunc is nullptr!");
176 napi_close_handle_scope(env, scope);
177 return TELEPHONY_ERROR;
178 }
179 napi_value callbackResult = nullptr;
180 napi_status ret =
181 napi_call_function(env, thisVar, callbackFunc, std::size(callbackValues), callbackValues, &callbackResult);
182 if (ret != napi_status::napi_ok) {
183 TELEPHONY_LOGE("napi_call_function failed!");
184 napi_close_handle_scope(env, scope);
185 return TELEPHONY_ERROR;
186 }
187 napi_close_handle_scope(env, scope);
188 return TELEPHONY_SUCCESS;
189 }
190 } // namespace Telephony
191 } // namespace OHOS