1 /*
2 * Copyright (C) 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
16 #include "distributed_data_sink_controller.h"
17 #include "call_ability_report_proxy.h"
18 #include "common_type.h"
19 #include "telephony_log_wrapper.h"
20 #include "call_object_manager.h"
21 #include "transmission_manager.h"
22
23 namespace OHOS {
24 namespace Telephony {
25 constexpr size_t SINGLE_CALL_COUNT = 1;
OnCallCreated(const sptr<CallBase> & call,const std::string & devId)26 void DistributedDataSinkController::OnCallCreated(const sptr<CallBase> &call, const std::string &devId)
27 {
28 ConnectRemote(devId);
29 CheckLocalData(call, DistributedDataType::NAME);
30 CheckLocalData(call, DistributedDataType::LOCATION);
31 SendDataQueryReq();
32 }
33
OnCallDestroyed()34 void DistributedDataSinkController::OnCallDestroyed()
35 {
36 std::list<int32_t> carrierCallList;
37 CallObjectManager::GetCarrierCallList(carrierCallList);
38 // The call is deleted only after the OnCallDestroyed() method is invoked.
39 if (carrierCallList.size() > SINGLE_CALL_COUNT) {
40 return;
41 }
42 if (session_ != nullptr) {
43 session_->Disconnect();
44 session_.reset();
45 session_ = nullptr;
46 }
47
48 std::lock_guard<ffrt::mutex> lock(mutex_);
49 queryInfo_.clear();
50 }
51
ProcessCallInfo(const sptr<CallBase> & call,DistributedDataType type)52 void DistributedDataSinkController::ProcessCallInfo(const sptr<CallBase> &call, DistributedDataType type)
53 {
54 CheckLocalData(call, type);
55 SendDataQueryReq();
56 }
57
OnConnected()58 void DistributedDataSinkController::OnConnected()
59 {
60 SendDataQueryReq();
61 SendCurrentDataQueryReq();
62 }
63
HandleRecvMsg(int32_t msgType,const cJSON * msg)64 void DistributedDataSinkController::HandleRecvMsg(int32_t msgType, const cJSON *msg)
65 {
66 if (msg == nullptr) {
67 return;
68 }
69 switch (msgType) {
70 case static_cast<int32_t>(DistributedMsgType::DATA_RSP):
71 HandleDataQueryRsp(msg);
72 break;
73 case static_cast<int32_t>(DistributedMsgType::CURRENT_DATA_RSP):
74 HandleCurrentDataQueryRsp(msg);
75 break;
76 default:
77 break;
78 }
79 }
80
ConnectRemote(const std::string & devId)81 void DistributedDataSinkController::ConnectRemote(const std::string &devId)
82 {
83 if (session_ != nullptr) {
84 return;
85 }
86 auto transMgr = DelayedSingleton<TransmissionManager>::GetInstance();
87 if (transMgr == nullptr) {
88 TELEPHONY_LOGE("get transmission manager fail");
89 return;
90 }
91 session_ = transMgr->CreateClientSession(shared_from_this());
92 if (session_ != nullptr) {
93 session_->Connect(devId, SESSION_NAME, SESSION_NAME, QOS_MIN_BW);
94 }
95 }
96
CheckLocalData(const sptr<CallBase> & call,DistributedDataType type)97 void DistributedDataSinkController::CheckLocalData(const sptr<CallBase> &call, DistributedDataType type)
98 {
99 if (call == nullptr) {
100 return;
101 }
102 std::string num = call->GetAccountNumber();
103 std::string location = call->GetNumberLocation();
104 std::string name(call->GetCallerInfo().name);
105 if (num.empty()) {
106 TELEPHONY_LOGE("invalid phone num");
107 return;
108 }
109 uint32_t queryInfo = 0;
110 if (type == DistributedDataType::NAME && name.empty()) {
111 queryInfo |= DISTRIBUTED_DATA_TYPE_OFFSET_BASE << static_cast<uint32_t>(DistributedDataType::NAME);
112 }
113 if (type == DistributedDataType::LOCATION && (location.empty() || location == "default")) {
114 queryInfo |= DISTRIBUTED_DATA_TYPE_OFFSET_BASE << static_cast<uint32_t>(DistributedDataType::LOCATION);
115 }
116 TELEPHONY_LOGI("query distributed data info %{public}d", queryInfo);
117
118 std::lock_guard<ffrt::mutex> lock(mutex_);
119 if (queryInfo_.find(num) == queryInfo_.end()) {
120 queryInfo_[num] = queryInfo;
121 } else {
122 queryInfo_[num] |= queryInfo;
123 }
124 }
125
CreateDataReqMsg(DistributedMsgType msgType,uint32_t itemType,const std::string & num)126 std::string DistributedDataSinkController::CreateDataReqMsg(DistributedMsgType msgType, uint32_t itemType,
127 const std::string &num)
128 {
129 std::string data = "";
130 cJSON *reqMsg = cJSON_CreateObject();
131 if (reqMsg == nullptr) {
132 TELEPHONY_LOGE("create json msg fail");
133 return data;
134 }
135 do {
136 if (cJSON_AddNumberToObject(reqMsg, DISTRIBUTED_MSG_TYPE, static_cast<int32_t>(msgType)) == nullptr) {
137 TELEPHONY_LOGE("add msg type fail");
138 break;
139 }
140 if (cJSON_AddNumberToObject(reqMsg, DISTRIBUTED_ITEM_TYPE, static_cast<int32_t>(itemType)) == nullptr) {
141 TELEPHONY_LOGE("add item type fail");
142 break;
143 }
144 if (cJSON_AddStringToObject(reqMsg, DISTRIBUTED_ITEM_NUM, num.c_str()) == nullptr) {
145 TELEPHONY_LOGE("add num fail");
146 break;
147 }
148 char *jsonData = cJSON_PrintUnformatted(reqMsg);
149 if (jsonData != nullptr) {
150 data = jsonData;
151 free(jsonData);
152 jsonData = nullptr;
153 }
154 } while (false);
155 cJSON_Delete(reqMsg);
156 return data;
157 }
158
SendDataQueryReq()159 void DistributedDataSinkController::SendDataQueryReq()
160 {
161 if (session_ == nullptr || !session_->IsReady()) {
162 TELEPHONY_LOGI("session not ready");
163 return;
164 }
165 std::lock_guard<ffrt::mutex> lock(mutex_);
166 for (auto iter = queryInfo_.begin(); iter != queryInfo_.end(); iter++) {
167 uint32_t queryInfo = iter->second;
168 for (auto type = static_cast<uint32_t>(DistributedDataType::NAME);
169 type < static_cast<uint32_t>(DistributedDataType::MAX); type++) {
170 if (((queryInfo >> type) & DISTRIBUTED_DATA_TYPE_OFFSET_BASE) != DISTRIBUTED_DATA_TYPE_OFFSET_BASE) {
171 continue;
172 }
173 TELEPHONY_LOGI("send request data, type %{public}d", type);
174 auto data = CreateDataReqMsg(DistributedMsgType::DATA_REQ, type, iter->first);
175 if (data.empty()) {
176 continue;
177 }
178 session_->SendMsg(data.c_str(), static_cast<uint32_t>(data.length()));
179 iter->second &= ~(DISTRIBUTED_DATA_TYPE_OFFSET_BASE << type);
180 }
181 }
182 }
183
HandleDataQueryRsp(const cJSON * msg)184 void DistributedDataSinkController::HandleDataQueryRsp(const cJSON *msg)
185 {
186 int32_t type = static_cast<int32_t>(DistributedDataType::MAX);
187 if (!GetInt32Value(msg, DISTRIBUTED_ITEM_TYPE, type)) {
188 return;
189 }
190 std::string num = "";
191 if (!GetStringValue(msg, DISTRIBUTED_ITEM_NUM, num)) {
192 return;
193 }
194 auto call = CallObjectManager::GetOneCallObject(num);
195 if (call == nullptr) {
196 TELEPHONY_LOGE("not find distributed call");
197 return;
198 }
199 if (type == static_cast<int32_t>(DistributedDataType::NAME)) {
200 UpdateCallName(call, msg);
201 } else if (type == static_cast<int32_t>(DistributedDataType::LOCATION)) {
202 UpdateCallLocation(call, msg);
203 }
204 }
205
UpdateCallName(sptr<CallBase> & call,const cJSON * msg)206 void DistributedDataSinkController::UpdateCallName(sptr<CallBase> &call, const cJSON *msg)
207 {
208 std::string name = "";
209 if (!GetStringValue(msg, DISTRIBUTED_ITEM_NAME, name)) {
210 return;
211 }
212 if (name.empty()) {
213 return;
214 }
215 auto callerInfo = call->GetCallerInfo();
216 callerInfo.name = name;
217 call->SetCallerInfo(callerInfo);
218 ReportCallInfo(call);
219 }
220
UpdateCallLocation(sptr<CallBase> & call,const cJSON * msg)221 void DistributedDataSinkController::UpdateCallLocation(sptr<CallBase> &call, const cJSON *msg)
222 {
223 std::string location = "";
224 if (!GetStringValue(msg, DISTRIBUTED_ITEM_LOCATION, location)) {
225 return;
226 }
227 if (!location.empty()) {
228 call->SetNumberLocation(location);
229 ReportCallInfo(call);
230 }
231 }
232
ReportCallInfo(const sptr<CallBase> & call)233 void DistributedDataSinkController::ReportCallInfo(const sptr<CallBase> &call)
234 {
235 CallAttributeInfo info;
236 call->GetCallAttributeBaseInfo(info);
237 auto abilityProxy = DelayedSingleton<CallAbilityReportProxy>::GetInstance();
238 if (abilityProxy != nullptr) {
239 abilityProxy->ReportCallStateInfo(info);
240 }
241 }
242
CreateCurrentDataReqMsg(const std::string & num)243 std::string DistributedDataSinkController::CreateCurrentDataReqMsg(const std::string &num)
244 {
245 std::string data = "";
246 cJSON *currentReqMsg = cJSON_CreateObject();
247 if (currentReqMsg == nullptr) {
248 TELEPHONY_LOGE("create json msg fail");
249 return data;
250 }
251 do {
252 if (cJSON_AddNumberToObject(currentReqMsg, DISTRIBUTED_MSG_TYPE,
253 static_cast<int32_t>(DistributedMsgType::CURRENT_DATA_REQ)) == nullptr) {
254 TELEPHONY_LOGE("add msg type fail");
255 break;
256 }
257 if (cJSON_AddStringToObject(currentReqMsg, DISTRIBUTED_ITEM_NUM, num.c_str()) == nullptr) {
258 TELEPHONY_LOGE("add num fail");
259 break;
260 }
261 char *jsonData = cJSON_PrintUnformatted(currentReqMsg);
262 if (jsonData != nullptr) {
263 data = jsonData;
264 free(jsonData);
265 jsonData = nullptr;
266 }
267 } while (false);
268 cJSON_Delete(currentReqMsg);
269 return data;
270 }
271
SendCurrentDataQueryReq()272 void DistributedDataSinkController::SendCurrentDataQueryReq()
273 {
274 if (session_ == nullptr) {
275 return;
276 }
277 auto calls = CallObjectManager::GetAllCallList();
278 for (auto &call : calls) {
279 if (call == nullptr) {
280 continue;
281 }
282 auto callType = call->GetCallType();
283 if (callType != CallType::TYPE_IMS && callType != CallType::TYPE_CS) {
284 continue;
285 }
286 TELEPHONY_LOGI("send current data request");
287 auto data = CreateCurrentDataReqMsg(call->GetAccountNumber());
288 if (data.empty()) {
289 continue;
290 }
291 session_->SendMsg(data.c_str(), static_cast<uint32_t>(data.length()));
292 }
293 }
294
HandleCurrentDataQueryRsp(const cJSON * msg)295 void DistributedDataSinkController::HandleCurrentDataQueryRsp(const cJSON *msg)
296 {
297 HandleMuted(msg);
298 std::string num = "";
299 if (!GetStringValue(msg, DISTRIBUTED_ITEM_NUM, num)) {
300 return;
301 }
302 int32_t direction = static_cast<int32_t>(CallDirection::CALL_DIRECTION_UNKNOW);
303 if (!GetInt32Value(msg, DISTRIBUTED_ITEM_DIRECTION, direction)) {
304 return;
305 }
306 TELEPHONY_LOGI("get distributed call direction %{public}d", direction);
307 if (direction < static_cast<int32_t>(CallDirection::CALL_DIRECTION_IN) ||
308 direction > static_cast<int32_t>(CallDirection::CALL_DIRECTION_OUT)) {
309 return;
310 }
311 auto call = CallObjectManager::GetOneCallObject(num);
312 if (call != nullptr) {
313 call->SetCallDirection(static_cast<CallDirection>(direction));
314 }
315 }
316
317 } // namespace Telephony
318 } // namespace OHOS
319