1 /*
2 * Copyright (C) 2025-2025 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 "interoperable_data_controller.h"
17 #include "telephony_log_wrapper.h"
18 #include "call_control_manager.h"
19 #include "call_object_manager.h"
20 #include "call_ability_report_proxy.h"
21 #include "report_call_info_handler.h"
22
23 namespace OHOS {
24 namespace Telephony {
25 constexpr int32_t BT_CALL_WAIT_SLOT_TIME = 2;
OnReceiveMsg(const char * data,uint32_t dataLen)26 void InteroperableDataController::OnReceiveMsg(const char* data, uint32_t dataLen)
27 {
28 if (dataLen > INTEROPERABLE_MAX_RECV_DATA_LEN) {
29 TELEPHONY_LOGE("recv invalid data len %{public}d", dataLen);
30 return;
31 }
32 std::string recvData(data, dataLen);
33 cJSON *msg = cJSON_Parse(recvData.c_str());
34 if (msg == nullptr) {
35 TELEPHONY_LOGE("json string invalid");
36 return;
37 }
38 int32_t msgType = static_cast<int32_t>(InteroperableMsgType::DATA_TYPE_UNKNOWN);
39 if (!GetInt32Value(msg, DATA_TYPE, msgType)) {
40 cJSON_Delete(msg);
41 return;
42 }
43 TELEPHONY_LOGI("recv data, msg type %{public}d", msgType);
44 if (msgType == static_cast<int32_t>(InteroperableMsgType::DATA_TYPE_MUTE)) {
45 HandleMuted(msg);
46 } else if (msgType == static_cast<int32_t>(InteroperableMsgType::DATA_TYPE_MUTE_RINGER)) {
47 HandleMuteRinger();
48 } else if (msgType == static_cast<int32_t>(InteroperableMsgType::DATA_TYPE_REQUISITES)) {
49 HandleRequisitesData(msg);
50 } else {
51 HandleSpecificMsg(msgType, msg);
52 }
53 cJSON_Delete(msg);
54 }
55
SetMuted(bool isMute)56 void InteroperableDataController::SetMuted(bool isMute)
57 {
58 if (session_ == nullptr) {
59 TELEPHONY_LOGE("session is null");
60 return;
61 }
62 TELEPHONY_LOGI("send mute %{public}d msg", isMute);
63 auto data = CreateMuteMsg(InteroperableMsgType::DATA_TYPE_MUTE, isMute);
64 if (data.empty()) {
65 return;
66 }
67 session_->SendMsg(data.c_str(), static_cast<uint32_t>(data.length()));
68 }
69
MuteRinger()70 void InteroperableDataController::MuteRinger()
71 {
72 if (session_ == nullptr) {
73 TELEPHONY_LOGE("session is null");
74 return;
75 }
76 TELEPHONY_LOGI("send mute ringer msg");
77 auto data = CreateMuteRingerMsg(InteroperableMsgType::DATA_TYPE_MUTE_RINGER);
78 if (data.empty()) {
79 return;
80 }
81 session_->SendMsg(data.c_str(), static_cast<uint32_t>(data.length()));
82 }
83
HandleMuted(const cJSON * msg)84 void InteroperableDataController::HandleMuted(const cJSON *msg)
85 {
86 bool isMute = false;
87 if (!GetBoolValue(msg, INTEROPERABLE_ITEM_MUTE, isMute)) {
88 return;
89 }
90 TELEPHONY_LOGI("set muted %{public}d", isMute);
91 DelayedSingleton<CallControlManager>::GetInstance()->SetMuted(isMute);
92 }
93
HandleMuteRinger()94 void InteroperableDataController::HandleMuteRinger()
95 {
96 TELEPHONY_LOGI("set mute ringer");
97 auto controlManager = DelayedSingleton<CallControlManager>::GetInstance()->MuteRinger();
98 }
99
CreateMuteMsg(InteroperableMsgType msgType,bool isMute)100 std::string InteroperableDataController::CreateMuteMsg(InteroperableMsgType msgType, bool isMute)
101 {
102 std::string data = "";
103 cJSON *muteMsg = cJSON_CreateObject();
104 if (muteMsg == nullptr) {
105 TELEPHONY_LOGE("create json msg fail");
106 return data;
107 }
108
109 cJSON_AddNumberToObject(muteMsg, DATA_TYPE, static_cast<int32_t>(msgType));
110 cJSON_AddBoolToObject(muteMsg, INTEROPERABLE_ITEM_MUTE, isMute);
111 char *jsonData = cJSON_PrintUnformatted(muteMsg);
112 if (jsonData != nullptr) {
113 data = jsonData;
114 free(jsonData);
115 jsonData = nullptr;
116 }
117 cJSON_Delete(muteMsg);
118 return data;
119 }
120
CreateMuteRingerMsg(InteroperableMsgType msgType)121 std::string InteroperableDataController::CreateMuteRingerMsg(InteroperableMsgType msgType)
122 {
123 std::string data = "";
124 cJSON *muteRingerMsg = cJSON_CreateObject();
125 if (muteRingerMsg == nullptr) {
126 TELEPHONY_LOGE("create json msg fail");
127 return data;
128 }
129
130 cJSON_AddNumberToObject(muteRingerMsg, DATA_TYPE, static_cast<int32_t>(msgType));
131 char *jsonData = cJSON_PrintUnformatted(muteRingerMsg);
132 if (jsonData != nullptr) {
133 data = jsonData;
134 free(jsonData);
135 jsonData = nullptr;
136 }
137 cJSON_Delete(muteRingerMsg);
138 return data;
139 }
140
GetInt32Value(const cJSON * msg,const std::string & name,int32_t & value)141 bool InteroperableDataController::GetInt32Value(const cJSON *msg, const std::string &name, int32_t &value)
142 {
143 cJSON *dataJson = cJSON_GetObjectItem(msg, name.c_str());
144 if (dataJson == nullptr || !cJSON_IsNumber(dataJson)) {
145 TELEPHONY_LOGE("%{public}s not contain or not number", name.c_str());
146 return false;
147 }
148 value = static_cast<int32_t>(dataJson->valueint);
149 return true;
150 }
151
GetBoolValue(const cJSON * msg,const std::string & name,bool & value)152 bool InteroperableDataController::GetBoolValue(const cJSON *msg, const std::string &name, bool &value)
153 {
154 cJSON *dataJson = cJSON_GetObjectItem(msg, name.c_str());
155 if (dataJson == nullptr || !cJSON_IsBool(dataJson)) {
156 TELEPHONY_LOGE("%{public}s not contain or not bool", name.c_str());
157 return false;
158 }
159 value = cJSON_IsTrue(dataJson);
160 return true;
161 }
162
SendRequisiteDataToPeer(int32_t slotId,const std::string & phoneNum)163 void InteroperableDataController::SendRequisiteDataToPeer(int32_t slotId, const std::string &phoneNum)
164 {
165 if (session_ == nullptr) {
166 TELEPHONY_LOGE("session is null");
167 return;
168 }
169
170 auto data = CreateRequisitesDataMsg(InteroperableMsgType::DATA_TYPE_REQUISITES, slotId, phoneNum);
171 if (data.empty()) {
172 return;
173 }
174 session_->SendMsg(data.c_str(), static_cast<uint32_t>(data.length()));
175 }
176
CreateRequisitesDataMsg(InteroperableMsgType msgType,int32_t slotId,const std::string & phoneNum)177 std::string InteroperableDataController::CreateRequisitesDataMsg(InteroperableMsgType msgType,
178 int32_t slotId, const std::string &phoneNum)
179 {
180 std::string data = "";
181 cJSON *slotIdMsg = cJSON_CreateObject();
182 if (slotIdMsg == nullptr) {
183 TELEPHONY_LOGE("create json msg fail");
184 return data;
185 }
186
187 cJSON_AddNumberToObject(slotIdMsg, DATA_TYPE, static_cast<int32_t>(msgType));
188 cJSON_AddStringToObject(slotIdMsg, INTEROPERABLE_ITEM_PHONE_NUMBER, phoneNum.c_str());
189 cJSON_AddNumberToObject(slotIdMsg, INTEROPERABLE_ITEM_SLOT, slotId);
190 cJSON_AddBoolToObject(slotIdMsg, INTEROPERABLE_ITEM_CALL_TYPE, false); // is caas call
191 char *jsonData = cJSON_PrintUnformatted(slotIdMsg);
192 if (jsonData != nullptr) {
193 data = jsonData;
194 free(jsonData);
195 jsonData = nullptr;
196 }
197 cJSON_Delete(slotIdMsg);
198 return data;
199 }
200
HandleRequisitesData(const cJSON * msg)201 void InteroperableDataController::HandleRequisitesData(const cJSON *msg)
202 {
203 int32_t slotId = DEFAULT_SIM_SLOT_ID;
204 std::string phoneNum = "";
205 bool isCaasVoip = false;
206 if (!GetStringValue(msg, INTEROPERABLE_ITEM_PHONE_NUMBER, phoneNum)) {
207 TELEPHONY_LOGE("OnRequisitesDataReceived get phone num failed");
208 return;
209 }
210 if (!GetInt32Value(msg, INTEROPERABLE_ITEM_SLOT, slotId)) {
211 TELEPHONY_LOGE("OnRequisitesDataReceived get slotId failed");
212 return;
213 }
214 if (!GetBoolValue(msg, INTEROPERABLE_ITEM_CALL_TYPE, isCaasVoip)) {
215 TELEPHONY_LOGE("OnRequisitesDataReceived get isCaasVoip failed");
216 return;
217 }
218
219 TELEPHONY_LOGI("parse data success, slot id[%{public}d]", slotId);
220 sptr<CallBase> callPtr = CallObjectManager::GetOneCallObject(phoneNum);
221 if (callPtr == nullptr) {
222 TELEPHONY_LOGI("OnRequisitesDataReceived, query call failed, save slotId");
223 SaveBtSlotId(phoneNum, slotId);
224 std::lock_guard<ffrt::mutex> lock(slotIdMutex_);
225 slotIdCv_.notify_all();
226 return;
227 }
228 CallAttributeInfo info;
229 callPtr->SetAccountId(slotId);
230 callPtr->GetCallAttributeBaseInfo(info);
231 auto abilityProxy = DelayedSingleton<CallAbilityReportProxy>::GetInstance();
232 if (abilityProxy != nullptr) {
233 abilityProxy->ReportCallStateInfo(info);
234 }
235 }
236
GetStringValue(const cJSON * msg,const std::string & name,std::string & value)237 bool InteroperableDataController::GetStringValue(const cJSON *msg, const std::string &name,
238 std::string &value)
239 {
240 cJSON *dataJson = cJSON_GetObjectItem(msg, name.c_str());
241 if (dataJson == nullptr || !cJSON_IsString(dataJson)) {
242 TELEPHONY_LOGE("%{public}s is not string", name.c_str());
243 return false;
244 }
245 char *data = cJSON_GetStringValue(dataJson);
246 if (data == nullptr) {
247 TELEPHONY_LOGE("get null %{public}s", name.c_str());
248 return false;
249 }
250 value = data;
251 return true;
252 }
253
CreateQueryRequisitesDataMsg(InteroperableMsgType msgType,const std::string & phoneNum)254 std::string InteroperableDataController::CreateQueryRequisitesDataMsg(InteroperableMsgType msgType,
255 const std::string &phoneNum)
256 {
257 std::string data = "";
258 cJSON *querySlotMsg = cJSON_CreateObject();
259 if (querySlotMsg == nullptr) {
260 TELEPHONY_LOGE("create json msg fail");
261 return data;
262 }
263
264 cJSON_AddNumberToObject(querySlotMsg, DATA_TYPE, static_cast<int32_t>(msgType));
265 cJSON_AddStringToObject(querySlotMsg, INTEROPERABLE_ITEM_PHONE_NUMBER, phoneNum.c_str());
266 char *jsonData = cJSON_PrintUnformatted(querySlotMsg);
267 if (jsonData != nullptr) {
268 data = jsonData;
269 free(jsonData);
270 jsonData = nullptr;
271 }
272 cJSON_Delete(querySlotMsg);
273 return data;
274 }
275
SendRequisiteDataQueryToPeer(const std::string & phoneNum)276 void InteroperableDataController::SendRequisiteDataQueryToPeer(const std::string &phoneNum)
277 {
278 TELEPHONY_LOGI("SendQueryRequisitesDataMsgWithPhoneNum enter");
279 if (session_ == nullptr || !session_->IsReady()) {
280 TELEPHONY_LOGE("session invalid");
281 return;
282 }
283
284 auto data = CreateQueryRequisitesDataMsg(InteroperableMsgType::DATA_TYPE_QUERY_REQUISITES_DATA, phoneNum);
285 if (data.empty()) {
286 return;
287 }
288 session_->SendMsg(data.c_str(), static_cast<uint32_t>(data.length()));
289 }
290
WaitForBtSlotId(const std::string & phoneNum)291 void InteroperableDataController::WaitForBtSlotId(const std::string &phoneNum)
292 {
293 TELEPHONY_LOGI("wait slot id 2s");
294 std::unique_lock<ffrt::mutex> lock(slotIdMutex_);
295 auto status = slotIdCv_.wait_for(lock, std::chrono::seconds(BT_CALL_WAIT_SLOT_TIME), [&] {
296 return slotIdMap_.find(phoneNum) != slotIdMap_.end();
297 });
298 if (!status) {
299 TELEPHONY_LOGE("wait slot id timeout");
300 }
301 }
302
SaveBtSlotId(const std::string & phoneNum,int32_t slotId)303 void InteroperableDataController::SaveBtSlotId(const std::string &phoneNum, int32_t slotId)
304 {
305 std::lock_guard<ffrt::mutex> lock(slotIdMutex_);
306 slotIdMap_[phoneNum] = slotId;
307 }
308
DeleteBtSlotIdByPhoneNumber(const std::string & phoneNum)309 void InteroperableDataController::DeleteBtSlotIdByPhoneNumber(const std::string &phoneNum)
310 {
311 std::lock_guard<ffrt::mutex> lock(slotIdMutex_);
312 if (!slotIdMap_.erase(phoneNum)) {
313 TELEPHONY_LOGE("delete slot failed!");
314 }
315 }
316
ClearBtSlotId()317 void InteroperableDataController::ClearBtSlotId()
318 {
319 TELEPHONY_LOGI("clear slot id map");
320 std::lock_guard<ffrt::mutex> lock(slotIdMutex_);
321 slotIdMap_.clear();
322 }
323
GetBtSlotIdByPhoneNumber(const std::string & phoneNum)324 int32_t InteroperableDataController::GetBtSlotIdByPhoneNumber(const std::string &phoneNum)
325 {
326 std::lock_guard<ffrt::mutex> lock(slotIdMutex_);
327 if (slotIdMap_.find(phoneNum) != slotIdMap_.end()) {
328 return slotIdMap_[phoneNum];
329 }
330 return BT_CALL_INVALID_SLOT;
331 }
332 }
333 }