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