• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }