1 /*
2  * Copyright (C) 2021 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 "hfp_ag_sdp_client.h"
17 
18 #include <cstring>
19 
20 #include "adapter_config.h"
21 #include "hfp_ag_profile_event_sender.h"
22 #include "raw_address.h"
23 
24 #include "hfp_ag_service.h"
25 
26 namespace OHOS {
27 namespace bluetooth {
28 std::map<std::string, HfpAgRemoteSdpServiceArray> HfpAgSdpClient::g_remoteSdpServiceArrays;
29 std::recursive_mutex HfpAgSdpClient::g_hfpSdpMutex;
30 int hfProfileState_ = -1;
31 
~HfpAgSdpClient()32 HfpAgSdpClient::~HfpAgSdpClient()
33 {
34     std::lock_guard<std::recursive_mutex> lk(g_hfpSdpMutex);
35     auto it = g_remoteSdpServiceArrays.find(currentAddr_);
36     if (it != g_remoteSdpServiceArrays.end()) {
37         DeleteSdpServiceArray(it->second);
38         g_remoteSdpServiceArrays.erase(it);
39     }
40 }
41 
SdpCallback(const BtAddr * addr,const SdpService * serviceAry,uint16_t serviceNum,void * context)42 void HfpAgSdpClient::SdpCallback(const BtAddr *addr, const SdpService *serviceAry, uint16_t serviceNum, void *context)
43 {
44     int msgWhat = HFP_AG_SDP_DISCOVERY_RESULT_FAIL;
45     std::string address = RawAddress::ConvertToString(addr->addr).GetAddress();
46     if (serviceNum > 0) {
47         CopySdpServiceArray(address, serviceAry, serviceNum);
48         msgWhat = HFP_AG_SDP_DISCOVERY_RESULT_SUCCESS;
49         hfProfileState_ = HFP_AG_HF_FOUND;
50     }
51     int hspState = 1;
52     AdapterConfig::GetInstance()->GetValue(HSP_AG_STATE_SECTION_NAME, HSP_AG_STATE_PROPERY_NAME, hspState);
53     if (hspState == HSP_AG_STATE_BOTH) {
54         HfpAgSdpClient *sdpClient = static_cast<HfpAgSdpClient *>(context);
55         HfpAgService::GetService()->GetDispatcher()->PostTask(
56             std::bind(&HfpAgSdpClient::DoHspHsDiscovery, sdpClient, address));
57         return;
58     }
59     HfpAgProfileEventSender::GetInstance().ProcessSdpDiscoveryResult(address, msgWhat);
60 }
61 
DoDiscovery(const std::string & remoteAddr,int role)62 int HfpAgSdpClient::DoDiscovery(const std::string &remoteAddr, int role)
63 {
64     hfProfileState_ = -1;
65     AdapterConfig::GetInstance()->GetValue(HSP_AG_STATE_SECTION_NAME, HSP_AG_STATE_PROPERY_NAME, hspState_);
66     if (hspState_ == HSP_AG_STATE_HSP) {
67         LOG_INFO("[HFP AG] start hsp hs dicovery");
68         return DoHspHsDiscovery(remoteAddr);
69     }
70     BtAddr address;
71     address.type = BT_PUBLIC_DEVICE_ADDRESS;
72     RawAddress rawAddr(remoteAddr);
73     rawAddr.ConvertToUint8(address.addr);
74 
75     BtUuid classid[HFP_AG_CLIENT_CLASSID_NUM];
76     classid[0].type = BT_UUID_16;
77     classid[0].uuid16 = HFP_AG_UUID_SERVCLASS_HFP_HF;
78     SdpUuid sdpUUid;
79     sdpUUid.uuidNum = HFP_AG_CLIENT_CLASSID_NUM;
80     sdpUUid.uuid = &classid[0];
81 
82     SdpAttributeIdList attributeIdList;
83     attributeIdList.type = SDP_TYPE_LIST;
84     if (HFP_AG_INITIATOR == role) {
85         attributeIdList.attributeIdList.attributeIdNumber = HFP_AG_CLIENT_INITIATOR_ATTR_NUM;
86         attributeIdList.attributeIdList.attributeId[SERVICE_CLASS_ID_LIST_INDEX] =
87             SDP_ATTRIBUTE_SERVICE_CLASS_ID_LIST;
88         attributeIdList.attributeIdList.attributeId[PROTOCOL_DESCRIPTOR_LIST_INDEX] =
89             SDP_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST;
90         attributeIdList.attributeIdList.attributeId[INITIATOR_PROFILE_DESCRIPTOR_LIST_INDEX] =
91             SDP_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST;
92         attributeIdList.attributeIdList.attributeId[INITIATOR_SUPPORTED_FEATURES_INDEX] =
93             HFP_AG_SDP_ATTRIBUTE_SUPPORTED_FEATURES;
94     } else {
95         attributeIdList.attributeIdList.attributeIdNumber = HFP_AG_CLIENT_ACCEPTOR_ATTR_NUM;
96         attributeIdList.attributeIdList.attributeId[SERVICE_CLASS_ID_LIST_INDEX] =
97             SDP_ATTRIBUTE_SERVICE_CLASS_ID_LIST;
98         attributeIdList.attributeIdList.attributeId[ACCEPTER_PROFILE_DESCRIPTOR_LIST_INDEX] =
99             SDP_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST;
100         attributeIdList.attributeIdList.attributeId[ACCEPTER_SUPPORTED_FEATURES_INDEX] =
101             HFP_AG_SDP_ATTRIBUTE_SUPPORTED_FEATURES;
102     }
103 
104     int ret = SDP_ServiceSearchAttribute(&address, &sdpUUid, attributeIdList, this, &HfpAgSdpClient::SdpCallback);
105     HFP_AG_RETURN_IF_FAIL(ret);
106     currentAddr_ = remoteAddr;
107     return ret;
108 }
109 
SdpHspHsCallback(const BtAddr * addr,const SdpService * serviceAry,uint16_t serviceNum,void * context)110 void HfpAgSdpClient::SdpHspHsCallback(const BtAddr *addr, const SdpService *serviceAry,
111     uint16_t serviceNum, void *context)
112 {
113     int msgWhat = HFP_AG_SDP_DISCOVERY_RESULT_FAIL;
114     std::string address = RawAddress::ConvertToString(addr->addr).GetAddress();
115     if (serviceNum > 0) {
116         CopySdpServiceArray(address, serviceAry, serviceNum);
117         msgWhat = HFP_AG_SDP_DISCOVERY_RESULT_SUCCESS;
118         if (hfProfileState_ == HFP_AG_HF_FOUND) {
119             hfProfileState_ = HFP_AG_HF_HS_FOUND;
120         } else {
121             hfProfileState_ = HFP_AG_HS_FOUND;
122         }
123     }
124     if (hfProfileState_ != -1) {
125         msgWhat = HFP_AG_SDP_DISCOVERY_RESULT_SUCCESS;
126         HfpAgProfileEventSender::GetInstance().ProcessSdpDiscoveryResult(address, msgWhat);
127     }
128 }
129 
DoHspHsDiscovery(const std::string & remoteAddr)130 int HfpAgSdpClient::DoHspHsDiscovery(const std::string &remoteAddr)
131 {
132     BtAddr address;
133     address.type = BT_PUBLIC_DEVICE_ADDRESS;
134     RawAddress rawAddr(remoteAddr);
135     rawAddr.ConvertToUint8(address.addr);
136 
137     BtUuid classid[HFP_AG_CLIENT_CLASSID_NUM];
138     classid[0].type = BT_UUID_16;
139     classid[0].uuid16 = HSP_HS_UUID_SERVCLASS;
140     SdpUuid sdpUUid;
141     sdpUUid.uuidNum = HFP_AG_CLIENT_CLASSID_NUM;
142     sdpUUid.uuid = &classid[0];
143 
144     SdpAttributeIdList attributeIdList;
145     attributeIdList.type = SDP_TYPE_LIST;
146     attributeIdList.attributeIdList.attributeIdNumber = HFP_AG_CLIENT_INITIATOR_ATTR_NUM;
147     attributeIdList.attributeIdList.attributeId[SERVICE_CLASS_ID_LIST_INDEX] =
148         SDP_ATTRIBUTE_SERVICE_CLASS_ID_LIST;
149     attributeIdList.attributeIdList.attributeId[PROTOCOL_DESCRIPTOR_LIST_INDEX] =
150         SDP_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST;
151     attributeIdList.attributeIdList.attributeId[INITIATOR_PROFILE_DESCRIPTOR_LIST_INDEX] =
152         SDP_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST;
153     attributeIdList.attributeIdList.attributeId[INITIATOR_SUPPORTED_FEATURES_INDEX] =
154         HSP_AG_SDP_ATTRIBUTE_REMOTE_AUDIO_VOLUME_CONTROL;
155 
156     int ret = SDP_ServiceSearchAttribute(&address, &sdpUUid, attributeIdList, this, &HfpAgSdpClient::SdpHspHsCallback);
157     currentAddr_ = remoteAddr;
158     return ret;
159 }
160 
FindAttributes(const std::string & remoteAddr,int role)161 bool HfpAgSdpClient::FindAttributes(const std::string &remoteAddr, int role)
162 {
163     std::lock_guard<std::recursive_mutex> lk(g_hfpSdpMutex);
164     auto it = g_remoteSdpServiceArrays.find(remoteAddr);
165     if (it == g_remoteSdpServiceArrays.end()) {
166         LOG_ERROR("[HFP AG]%{public}s():Not found the attributes", __FUNCTION__);
167         return false;
168     }
169 
170     HfpAgRemoteSdpInfo info;
171     uint16_t num = 0;
172     if (HFP_AG_INITIATOR == role) {
173         if (!LoopAllProtocolRfcomm(num, it->second, info.remoteServerChannelNumber)) {
174             LOG_ERROR("[HFP AG]%{public}s():Not found peer rfcomm scn", __FUNCTION__);
175             return false;
176         }
177     }
178 
179     if (!FindProfileVersion(it->second.services[num].profileDescriptors, info.remoteVersion)) {
180         info.remoteVersion = HFP_AG_HFP_VERSION_1_1;
181         LOG_INFO("[HFP AG]%{public}s():Not found peer HFP version, using default version[1.1]", __FUNCTION__);
182     }
183 
184     if (!FindProfileFeatures(it->second.services[num].attributes, info.remoteFeatures)) {
185         info.remoteFeatures = HFP_AG_HF_FEATURES_NONE;
186         LOG_INFO("[HFP AG]%{public}s():Not found peer HFP features, using default features", __FUNCTION__);
187     }
188     if (info.remoteFeatures & HFP_AG_HF_FEATURES_SUPPORT_WBS) {
189         info.remoteCodec = HFP_AG_CODEC_MSBC;
190     } else {
191         info.remoteCodec = HFP_AG_CODEC_CVSD;
192     }
193 
194     remoteSdpInfo_ = info;
195     DeleteSdpServiceArray(it->second);
196     g_remoteSdpServiceArrays.erase(it);
197     return true;
198 }
199 
GetRemoteSdpInfo() const200 HfpAgRemoteSdpInfo HfpAgSdpClient::GetRemoteSdpInfo() const
201 {
202     return remoteSdpInfo_;
203 }
204 
CopySdpServiceArray(const std::string & remoteAddr,const SdpService * serviceAry,uint16_t serviceNum)205 void HfpAgSdpClient::CopySdpServiceArray(
206     const std::string &remoteAddr, const SdpService *serviceAry, uint16_t serviceNum)
207 {
208     std::lock_guard<std::recursive_mutex> lk(g_hfpSdpMutex);
209     HfpAgRemoteSdpServiceArray array;
210     for (uint16_t n = 0; n < serviceNum; n++) {
211         HfpAgRemoteSdpService service;
212         for (uint16_t i = 0; i < serviceAry[n].descriptorNumber; i++) {
213             SdpProtocolDescriptor descriptor = serviceAry[n].descriptor[i];
214             service.descriptors.push_back(descriptor);
215         }
216         for (uint16_t j = 0; j < serviceAry[n].profileDescriptorNumber; j++) {
217             SdpProfileDescriptor profileDescriptor = serviceAry[n].profileDescriptor[j];
218             service.profileDescriptors.push_back(profileDescriptor);
219         }
220         for (uint16_t k = 0; k < serviceAry[n].attributeNumber; k++) {
221             HfpAgSdpAttribute attribute;
222             attribute.attributeId = serviceAry[n].attribute[k].attributeId;
223             attribute.type = serviceAry[n].attribute[k].type;
224             uint16_t length = serviceAry[n].attribute[k].attributeValueLength;
225             if (length == ATTRIBUTE_LENGTH_UINT16) {
226                 attribute.attributeValue = *static_cast<uint16_t*>(serviceAry[n].attribute[k].attributeValue);
227             } else if (length == ATTRIBUTE_LENGTH_UINT8) {
228                 attribute.attributeValue = *static_cast<uint8_t*>(serviceAry[n].attribute[k].attributeValue);
229             } else {
230                 LOG_ERROR("[HFP AG]%{public}s():Error attribute(n[%hu] k[%hu]) length[%hu]",
231                     __FUNCTION__, n, k, length);
232             }
233             service.attributes.push_back(attribute);
234         }
235         array.services.push_back(service);
236     }
237     g_remoteSdpServiceArrays.insert_or_assign(remoteAddr, array);
238 }
239 
DeleteSdpServiceArray(HfpAgRemoteSdpServiceArray & array)240 void HfpAgSdpClient::DeleteSdpServiceArray(HfpAgRemoteSdpServiceArray &array)
241 {
242     if (array.services.capacity() == 0) {
243         return;
244     }
245 
246     for (uint16_t n = 0; n < array.services.size(); n++) {
247         if (array.services[n].descriptors.capacity() != 0) {
248             std::vector<SdpProtocolDescriptor>().swap(array.services[n].descriptors);
249         }
250         if (array.services[n].profileDescriptors.capacity() != 0) {
251             std::vector<SdpProfileDescriptor>().swap(array.services[n].profileDescriptors);
252         }
253         if (array.services[n].attributes.capacity() != 0) {
254             std::vector<HfpAgSdpAttribute>().swap(array.services[n].attributes);
255         }
256     }
257     std::vector<HfpAgRemoteSdpService>().swap(array.services);
258 }
259 
LoopAllProtocolRfcomm(uint16_t & loopNum,const HfpAgRemoteSdpServiceArray & array,uint8_t & scn) const260 bool HfpAgSdpClient::LoopAllProtocolRfcomm(uint16_t &loopNum,
261                                            const HfpAgRemoteSdpServiceArray &array,
262                                            uint8_t &scn) const
263 {
264     uint16_t serviceNum = array.services.size();
265     for (uint16_t num = 0; num < serviceNum; num++) {
266         loopNum = num;
267         if (FindProtocolRfcomm(array.services[loopNum].descriptors, scn)) {
268             break;
269         }
270     }
271 
272     bool ret = false;
273     if (loopNum < serviceNum) {
274         ret = true;
275     }
276     return ret;
277 }
278 
FindProtocolRfcomm(const std::vector<SdpProtocolDescriptor> & protocols,uint8_t & scn)279 bool HfpAgSdpClient::FindProtocolRfcomm(const std::vector<SdpProtocolDescriptor> &protocols, uint8_t &scn)
280 {
281     uint16_t num = 0;
282     while (num < protocols.size()) {
283         if ((protocols[num].protocolUuid.uuid16 == UUID_PROTOCOL_RFCOMM) &&
284             (protocols[num].parameter[0].type == SDP_TYPE_UINT_8)) {
285             scn = static_cast<uint8_t>(protocols[num].parameter[0].value);
286             LOG_INFO("[HFP AG]%{public}s():Found rfcomm scn is [%hhu]", __FUNCTION__, scn);
287             return true;
288         }
289         num++;
290     }
291     return false;
292 }
293 
FindProfileVersion(const std::vector<SdpProfileDescriptor> & profiles,uint16_t & version)294 bool HfpAgSdpClient::FindProfileVersion(const std::vector<SdpProfileDescriptor> &profiles, uint16_t &version)
295 {
296     uint16_t num = 0;
297     while (num < profiles.size()) {
298         if (profiles[num].profileUuid.uuid16 == HFP_AG_UUID_SERVCLASS_HFP_HF) {
299             version = profiles[num].versionNumber;
300             LOG_DEBUG("[HFP AG]%{public}s():Found profile version is [%hu]", __FUNCTION__, version);
301             return true;
302         } else if (profiles[num].profileUuid.uuid16 == HSP_HS_UUID_SERVCLASS) {
303             version = profiles[num].versionNumber;
304             LOG_DEBUG("[HSP AG]%{public}s():Found profile version is [%hu]", __FUNCTION__, version);
305             return true;
306         }
307         num++;
308     }
309     return false;
310 }
311 
FindProfileFeatures(const std::vector<HfpAgSdpAttribute> & attributes,uint16_t & features)312 bool HfpAgSdpClient::FindProfileFeatures(const std::vector<HfpAgSdpAttribute> &attributes, uint16_t &features)
313 {
314     uint16_t num = 0;
315     while (num < attributes.size()) {
316         if (attributes[num].attributeId == HFP_AG_SDP_ATTRIBUTE_SUPPORTED_FEATURES) {
317             features = HFP_AG_HF_FEATURES_BRSF_MASK & attributes[num].attributeValue;
318             LOG_INFO("[HFP AG]%{public}s():Found profile features are [%hu]", __FUNCTION__, features);
319             return true;
320         }
321         num++;
322     }
323     return false;
324 }
325 }  // namespace bluetooth
326 }  // namespace OHOS