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