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