• 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_sink_switch_controller.h"
17 
18 #include <chrono>
19 #include "distributed_communication_manager.h"
20 #include "audio_device_manager.h"
21 #include "audio_control_manager.h"
22 #include "bluetooth_connection.h"
23 #ifdef ABILITY_BLUETOOTH_SUPPORT
24 #include "bluetooth_device.h"
25 #endif
26 
27 namespace OHOS {
28 namespace Telephony {
29 using namespace std::chrono;
OnDeviceOnline(const std::string & devId,const std::string & devName,AudioDeviceType devType)30 void DistributedSinkSwitchController::OnDeviceOnline(const std::string &devId, const std::string &devName,
31     AudioDeviceType devType)
32 {
33 #ifdef ABILITY_BLUETOOTH_SUPPORT
34     std::lock_guard<ffrt::mutex> lock(mutex_);
35     if (hfpListener_ == nullptr) {
36         hfpListener_ = std::make_shared<DcCallHfpListener>();
37         Bluetooth::HandsFreeAudioGateway::GetProfile()->RegisterObserver(hfpListener_);
38     }
39 #endif
40 }
41 
OnDeviceOffline(const std::string & devId,const std::string & devName,AudioDeviceType devType)42 void DistributedSinkSwitchController::OnDeviceOffline(const std::string &devId, const std::string &devName,
43     AudioDeviceType devType)
44 {
45 #ifdef ABILITY_BLUETOOTH_SUPPORT
46     std::lock_guard<ffrt::mutex> lock(mutex_);
47     if (hfpListener_ != nullptr) {
48         Bluetooth::HandsFreeAudioGateway::GetProfile()->DeregisterObserver(hfpListener_);
49         hfpListener_ = nullptr;
50     }
51 #endif
52 }
53 
OnDistributedAudioDeviceChange(const std::string & devId,const std::string & devName,AudioDeviceType devType,int32_t devRole)54 void DistributedSinkSwitchController::OnDistributedAudioDeviceChange(const std::string &devId,
55     const std::string &devName, AudioDeviceType devType, int32_t devRole)
56 {
57     {
58         std::lock_guard<ffrt::mutex> lock(mutex_);
59         isAudioOnSink_ = (devRole == static_cast<int32_t>(DistributedRole::SINK));
60         TELEPHONY_LOGI("OnDistributedAudioDeviceChange isAudioOnSink[%{public}d]", isAudioOnSink_);
61     }
62     if (devRole == static_cast<int32_t>(DistributedRole::SINK)) {
63         TrySwitchToBtHeadset();
64 #ifdef ABILITY_BLUETOOTH_SUPPORT
65         if (hfpListener_ != nullptr &&
66             !DelayedSingleton<BluetoothConnection>::GetInstance()->GetWearBtHeadsetAddress().empty()) {
67             hfpListener_->SetPreAction(WEAR_ACTION);
68         }
69 #endif
70     }
71 }
72 
OnRemoveSystemAbility()73 void DistributedSinkSwitchController::OnRemoveSystemAbility()
74 {
75     std::lock_guard<ffrt::mutex> lock(mutex_);
76     isAudioOnSink_ = false;
77 #ifdef ABILITY_BLUETOOTH_SUPPORT
78     if (hfpListener_ != nullptr) {
79         Bluetooth::HandsFreeAudioGateway::GetProfile()->DeregisterObserver(hfpListener_);
80         hfpListener_ = nullptr;
81     }
82 #endif
83 }
84 
TrySwitchToBtHeadset()85 void DistributedSinkSwitchController::TrySwitchToBtHeadset()
86 {
87 #ifdef ABILITY_BLUETOOTH_SUPPORT
88     auto address = DelayedSingleton<BluetoothConnection>::GetInstance()->GetWearBtHeadsetAddress();
89     if (address.empty()) {
90         return;
91     }
92 
93     AudioDevice audioDevice;
94     audioDevice.deviceType = AudioDeviceType::DEVICE_BLUETOOTH_SCO;
95     if (memcpy_s(audioDevice.address, kMaxAddressLen, address.c_str(), address.length()) != EOK) {
96         TELEPHONY_LOGE("memcpy_s fail");
97         return;
98     }
99     auto ret = DelayedSingleton<AudioControlManager>::GetInstance()->SetAudioDevice(audioDevice);
100     TELEPHONY_LOGI("set bt headset ret[%{public}d]", ret);
101 #endif
102 }
103 
104 #ifdef ABILITY_BLUETOOTH_SUPPORT
OnHfpStackChanged(const Bluetooth::BluetoothRemoteDevice & device,int32_t action)105 void DcCallHfpListener::OnHfpStackChanged(const Bluetooth::BluetoothRemoteDevice &device, int32_t action)
106 {
107     TELEPHONY_LOGI("dc call hfp stack changed, action[%{public}d], preAction_[%{public}d]", action, preAction_);
108     int32_t cod = DEFAULT_HFP_FLAG_VALUE;
109     int32_t majorClass = DEFAULT_HFP_FLAG_VALUE;
110     int32_t majorMinorClass = DEFAULT_HFP_FLAG_VALUE;
111     device.GetDeviceProductType(cod, majorClass, majorMinorClass);
112     bool isBtHeadset = (majorClass == Bluetooth::BluetoothDevice::MAJOR_AUDIO_VIDEO &&
113                         (majorMinorClass == Bluetooth::BluetoothDevice::AUDIO_VIDEO_HEADPHONES ||
114                          majorMinorClass == Bluetooth::BluetoothDevice::AUDIO_VIDEO_WEARABLE_HEADSET));
115     if (!isBtHeadset) {
116         return;
117     }
118     if (!DelayedSingleton<DistributedCommunicationManager>::GetInstance()->IsConnected() ||
119         !DelayedSingleton<DistributedCommunicationManager>::GetInstance()->IsAudioOnSink()) {
120         TELEPHONY_LOGI("dc not connected or audio not on sink");
121         preAction_ = action;
122         return;
123     }
124     if ((action == WEAR_ACTION) || (action == DISABLE_FROM_REMOTE_ACTION && preAction_ == WEAR_ACTION)) {
125         // Forcibly switch to the bt headset in either of the following situations:
126         // case 1: At the moment, the user wears the headset
127         // case 2: The headset is preempted by the peer device when the user wears the headset
128         SwitchToBtHeadset(device);
129     }
130     preAction_ = action;
131 }
132 
SetPreAction(int32_t action)133 void DcCallHfpListener::SetPreAction(int32_t action)
134 {
135     preAction_ = action;
136 }
137 
SwitchToBtHeadset(const Bluetooth::BluetoothRemoteDevice & device)138 void DcCallHfpListener::SwitchToBtHeadset(const Bluetooth::BluetoothRemoteDevice &device)
139 {
140     AudioDevice audioDevice;
141     audioDevice.deviceType = AudioDeviceType::DEVICE_BLUETOOTH_SCO;
142     if (memcpy_s(audioDevice.address, kMaxAddressLen, device.GetDeviceAddr().c_str(),
143         device.GetDeviceAddr().length()) != EOK) {
144         TELEPHONY_LOGE("memcpy_s address fail");
145         return;
146     }
147     auto ret = DelayedSingleton<AudioControlManager>::GetInstance()->SetAudioDevice(audioDevice);
148     TELEPHONY_LOGI("switch to bt headset, ret[%{public}d]", ret);
149 }
150 #endif
151 
152 } // namespace Telephony
153 } // namespace OHOS
154