1 /*
2 * Copyright (C) 2024-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_communication_manager.h"
17 #include <dlfcn.h>
18 #include "cJSON.h"
19 #include "telephony_errors.h"
20 #include "telephony_log_wrapper.h"
21 #include "distributed_data_sink_controller.h"
22 #include "distributed_data_source_controller.h"
23 #include "distributed_sink_switch_controller.h"
24 #include "distributed_source_switch_controller.h"
25
26 namespace OHOS {
27 namespace Telephony {
DistributedCommunicationManager()28 DistributedCommunicationManager::DistributedCommunicationManager()
29 {
30 }
31
~DistributedCommunicationManager()32 DistributedCommunicationManager::~DistributedCommunicationManager()
33 {
34 }
35
Init()36 void DistributedCommunicationManager::Init()
37 {
38 devObserver_ = std::make_shared<DistributedDeviceObserver>();
39 if (devObserver_ != nullptr) {
40 devObserver_->Init();
41 }
42 }
43
InitExtWrapper()44 void DistributedCommunicationManager::InitExtWrapper()
45 {
46 std::lock_guard<ffrt::mutex> lock(mutexFunc_);
47 if (extWrapperHandler_ != nullptr) {
48 return;
49 }
50 extWrapperHandler_ = dlopen("libtelephony_ext_innerkits.z.so", RTLD_NOW);
51 if (extWrapperHandler_ == nullptr) {
52 TELEPHONY_LOGE("open ext so failed");
53 return;
54 }
55 regDevCallbackFunc_ = (REGISTER_DEVICE_CALLBACK)dlsym(extWrapperHandler_, "RegisterDistributedDevState");
56 unRegDevCallbackFunc_ = (UN_REGISTER_DEVICE_CALLBACK)dlsym(extWrapperHandler_, "UnRegisterDistributedDevState");
57 switchDevFunc_ = (SWITCH_DEVICE)dlsym(extWrapperHandler_, "SwitchDistributedDevice");
58 TELEPHONY_LOGI("init ext wrapper finish");
59 }
60
DeInitExtWrapper()61 void DistributedCommunicationManager::DeInitExtWrapper()
62 {
63 std::lock_guard<ffrt::mutex> lock(mutexFunc_);
64 if (extWrapperHandler_ != nullptr) {
65 dlclose(extWrapperHandler_);
66 extWrapperHandler_ = nullptr;
67 regDevCallbackFunc_ = nullptr;
68 unRegDevCallbackFunc_ = nullptr;
69 switchDevFunc_ = nullptr;
70 }
71 TELEPHONY_LOGI("de-init ext wrapper finish");
72 }
73
RegDevCallbackWrapper(const std::shared_ptr<IDistributedDeviceCallback> & callback)74 int32_t DistributedCommunicationManager::RegDevCallbackWrapper(
75 const std::shared_ptr<IDistributedDeviceCallback> &callback)
76 {
77 std::lock_guard<ffrt::mutex> lock(mutexFunc_);
78 if (regDevCallbackFunc_ == nullptr) {
79 TELEPHONY_LOGE("reg dev callback func is null");
80 return TELEPHONY_ERROR;
81 }
82 return regDevCallbackFunc_(callback);
83 }
84
UnRegDevCallbackWrapper()85 int32_t DistributedCommunicationManager::UnRegDevCallbackWrapper()
86 {
87 std::lock_guard<ffrt::mutex> lock(mutexFunc_);
88 if (unRegDevCallbackFunc_ == nullptr) {
89 TELEPHONY_LOGE("un-reg dev callback func is null");
90 return TELEPHONY_ERROR;
91 }
92 return unRegDevCallbackFunc_();
93 }
94
SwitchDevWrapper(const std::string & devId,int32_t direction)95 int32_t DistributedCommunicationManager::SwitchDevWrapper(const std::string &devId, int32_t direction)
96 {
97 std::lock_guard<ffrt::mutex> lock(mutexFunc_);
98 if (switchDevFunc_ == nullptr) {
99 TELEPHONY_LOGE("switch dev func is null");
100 return TELEPHONY_ERROR;
101 }
102 return switchDevFunc_(devId, direction);
103 }
104
OnDeviceOnline(const std::string & devId,const std::string & devName,AudioDeviceType deviceType,int32_t devRole)105 void DistributedCommunicationManager::OnDeviceOnline(const std::string &devId, const std::string &devName,
106 AudioDeviceType deviceType, int32_t devRole)
107 {
108 if (devObserver_ == nullptr) {
109 return;
110 }
111 {
112 std::lock_guard<ffrt::mutex> lock(mutex_);
113 status_ = DistributedStatus::CONNECT;
114 role_ = (devRole == 0 ? DistributedRole::SINK : DistributedRole::SOURCE); // peer role 0 means local role sink
115 auto iter = std::find(peerDevices_.begin(), peerDevices_.end(), devId);
116 if (iter == peerDevices_.end()) {
117 peerDevices_.emplace_back(devId);
118 }
119 if (dataController_ == nullptr) {
120 if (role_ == DistributedRole::SINK) {
121 dataController_ = std::make_shared<DistributedDataSinkController>();
122 } else {
123 dataController_ = std::make_shared<DistributedDataSourceController>();
124 }
125 }
126 if (devSwitchController_ == nullptr) {
127 if (role_ == DistributedRole::SINK) {
128 devSwitchController_ = std::make_shared<DistributedSinkSwitchController>();
129 } else {
130 devSwitchController_ = std::make_shared<DistributedSourceSwitchController>();
131 }
132 }
133 }
134 devObserver_->RegisterDevStatusCallback(dataController_);
135 devObserver_->RegisterDevStatusCallback(devSwitchController_);
136 devObserver_->OnDeviceOnline(devId, devName, deviceType);
137 TELEPHONY_LOGI("distributed device online");
138 }
139
OnDeviceOffline(const std::string & devId,const std::string & devName,AudioDeviceType deviceType,int32_t devRole)140 void DistributedCommunicationManager::OnDeviceOffline(const std::string &devId, const std::string &devName,
141 AudioDeviceType deviceType, int32_t devRole)
142 {
143 if (devObserver_ == nullptr) {
144 return;
145 }
146 devObserver_->OnDeviceOffline(devId, devName, deviceType);
147 devObserver_->UnRegisterDevStatusCallback(dataController_);
148 devObserver_->UnRegisterDevStatusCallback(devSwitchController_);
149
150 std::lock_guard<ffrt::mutex> lock(mutex_);
151 auto iter = std::find(peerDevices_.begin(), peerDevices_.end(), devId);
152 if (iter != peerDevices_.end()) {
153 peerDevices_.erase(iter);
154 }
155 if (!peerDevices_.empty()) {
156 TELEPHONY_LOGI("device list not empty");
157 return;
158 }
159
160 status_ = DistributedStatus::DISCONNECT;
161 role_ = DistributedRole::UNKNOWN;
162 if (dataController_ != nullptr) {
163 dataController_.reset();
164 dataController_ = nullptr;
165 }
166 if (devSwitchController_ != nullptr) {
167 devSwitchController_.reset();
168 devSwitchController_ = nullptr;
169 }
170 TELEPHONY_LOGI("distributed device offline");
171 }
172
OnRemoveSystemAbility()173 void DistributedCommunicationManager::OnRemoveSystemAbility()
174 {
175 std::lock_guard<ffrt::mutex> lock(mutex_);
176 peerDevices_.clear();
177 status_ = DistributedStatus::DISCONNECT;
178 role_ = DistributedRole::UNKNOWN;
179 dataController_ = nullptr;
180 devSwitchController_ = nullptr;
181 TELEPHONY_LOGI("distributed system ability remove");
182 }
183
IsSinkRole()184 bool DistributedCommunicationManager::IsSinkRole()
185 {
186 std::lock_guard<ffrt::mutex> lock(mutex_);
187 return role_ == DistributedRole::SINK;
188 }
189
IsConnected()190 bool DistributedCommunicationManager::IsConnected()
191 {
192 std::lock_guard<ffrt::mutex> lock(mutex_);
193 return status_ == DistributedStatus::CONNECT;
194 }
195
IsDistributedDev(const AudioDevice & device)196 bool DistributedCommunicationManager::IsDistributedDev(const AudioDevice& device)
197 {
198 std::string devId = ParseDevIdFromAudioDevice(device);
199 return IsDistributedDev(devId);
200 }
201
GetDistributedDeviceObserver()202 const std::shared_ptr<DistributedDeviceObserver>& DistributedCommunicationManager::GetDistributedDeviceObserver()
203 {
204 return devObserver_;
205 }
206
SwitchToSinkDevice(const AudioDevice & device)207 bool DistributedCommunicationManager::SwitchToSinkDevice(const AudioDevice& device)
208 {
209 std::string devId = ParseDevIdFromAudioDevice(device);
210 if (devId.empty()) {
211 TELEPHONY_LOGE("parse dev id fail");
212 return false;
213 }
214 if (!IsDistributedDev(devId)) {
215 TELEPHONY_LOGE("not distributed dev");
216 return false;
217 }
218
219 TELEPHONY_LOGI("switch to remote.");
220 std::lock_guard<ffrt::mutex> lock(mutex_);
221 if (devSwitchController_ == nullptr) {
222 return false;
223 }
224 if (devSwitchController_->IsAudioOnSink()) {
225 TELEPHONY_LOGE("call is already on sink, no need to switch");
226 return true;
227 }
228
229 return devSwitchController_->SwitchDevice(devId, static_cast<int32_t>(DistributedRole::SINK));
230 }
231
SwitchToSourceDevice()232 bool DistributedCommunicationManager::SwitchToSourceDevice()
233 {
234 TELEPHONY_LOGI("switch to local.");
235 std::lock_guard<ffrt::mutex> lock(mutex_);
236 if (devSwitchController_ == nullptr) {
237 return false;
238 }
239 if (!devSwitchController_->IsAudioOnSink()) {
240 return true;
241 }
242 return devSwitchController_->SwitchDevice("", static_cast<int32_t>(DistributedRole::SOURCE));
243 }
244
IsAudioOnSink()245 bool DistributedCommunicationManager::IsAudioOnSink()
246 {
247 std::lock_guard<ffrt::mutex> lock(mutex_);
248 if (devSwitchController_ == nullptr) {
249 return false;
250 }
251 return devSwitchController_->IsAudioOnSink();
252 }
253
SetMuted(bool isMute)254 void DistributedCommunicationManager::SetMuted(bool isMute)
255 {
256 std::lock_guard<ffrt::mutex> lock(mutex_);
257 if (dataController_ != nullptr) {
258 dataController_->SetMuted(isMute);
259 }
260 TELEPHONY_LOGI("set muted %{public}d", isMute);
261 }
262
MuteRinger()263 void DistributedCommunicationManager::MuteRinger()
264 {
265 std::lock_guard<ffrt::mutex> lock(mutex_);
266 if (dataController_ != nullptr) {
267 dataController_->MuteRinger();
268 }
269 }
270
ProcessCallInfo(const sptr<CallBase> & call,DistributedDataType type)271 void DistributedCommunicationManager::ProcessCallInfo(const sptr<CallBase> &call, DistributedDataType type)
272 {
273 std::lock_guard<ffrt::mutex> lock(mutex_);
274 if (dataController_ != nullptr) {
275 dataController_->ProcessCallInfo(call, type);
276 }
277 }
278
NewCallCreated(sptr<CallBase> & call)279 void DistributedCommunicationManager::NewCallCreated(sptr<CallBase> &call)
280 {
281 if (call == nullptr) {
282 return;
283 }
284 auto callType = call->GetCallType();
285 if (callType != CallType::TYPE_IMS && callType != CallType::TYPE_CS) {
286 return;
287 }
288
289 if (role_ == DistributedRole::SINK) {
290 DistributedSinkSwitchController::TrySwitchToBtHeadset();
291 }
292
293 std::lock_guard<ffrt::mutex> lock(mutex_);
294 if (dataController_ != nullptr) {
295 if (peerDevices_.empty()) {
296 TELEPHONY_LOGI("call created but no peer device");
297 return;
298 }
299 TELEPHONY_LOGI("call %{public}d created, role %{public}hhd", call->GetCallID(), role_);
300 dataController_->OnCallCreated(call, peerDevices_.front());
301 }
302 }
303
CallDestroyed(const DisconnectedDetails & details)304 void DistributedCommunicationManager::CallDestroyed(const DisconnectedDetails &details)
305 {
306 std::lock_guard<ffrt::mutex> lock(mutex_);
307 if (dataController_ != nullptr) {
308 TELEPHONY_LOGI("call destroyed, role %{public}hhd", role_);
309 dataController_->OnCallDestroyed();
310 }
311 }
312
IsDistributedDev(const std::string & devId)313 bool DistributedCommunicationManager::IsDistributedDev(const std::string &devId)
314 {
315 std::lock_guard<ffrt::mutex> lock(mutex_);
316 auto iter = std::find(peerDevices_.begin(), peerDevices_.end(), devId);
317 return iter != peerDevices_.end();
318 }
319
ParseDevIdFromAudioDevice(const AudioDevice & device)320 std::string DistributedCommunicationManager::ParseDevIdFromAudioDevice(const AudioDevice& device)
321 {
322 std::string devId = "";
323 std::string address = device.address;
324 if (address.empty()) {
325 TELEPHONY_LOGI("address invalid, not distributed device");
326 return devId;
327 }
328 cJSON *root = cJSON_Parse(address.c_str());
329 if (root == nullptr) {
330 TELEPHONY_LOGE("json string invalid");
331 return devId;
332 }
333 cJSON *devIdJson = cJSON_GetObjectItem(root, "devId");
334 if (devIdJson != nullptr) {
335 if (cJSON_IsString(devIdJson)) {
336 char *value = cJSON_GetStringValue(devIdJson);
337 devId = value;
338 }
339 }
340 cJSON_Delete(root);
341 return devId;
342 }
343
344 } // namespace Telephony
345 } // namespace OHOS
346