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