2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
17 // @file FNetBt_BluetoothHdpSystemAdapter.cpp
18 // @brief This is the implementation file for the _BluetoothHdpSystemAdapter class.
22 #include <FBaseByteBuffer.h>
23 #include <FBaseString.h>
24 #include <FBaseColHashMapT.h>
25 #include <FBaseColIComparerT.h>
26 #include <FBaseColIHashCodeProviderT.h>
27 #include <FBaseUtilStringUtil.h>
28 #include <FNetBtBluetoothDevice.h>
29 #include <FNetBtBluetoothTypes.h>
30 #include <FBaseSysLog.h>
31 #include <FBase_StringConverter.h>
32 #include "FNetBt_BluetoothHealthImpl.h"
33 #include "FNetBt_BluetoothHdpSystemAdapter.h"
34 #include "FNetBt_BluetoothGapSystemAdapter.h"
35 #include "FNetBt_BluetoothDeviceImpl.h"
38 using namespace Tizen::Base;
39 using namespace Tizen::Base::Collection;
40 using namespace Tizen::Base::Utility;
42 namespace Tizen { namespace Net { namespace Bluetooth
46 * @class _BluetoothAddressComparer
47 * @brief The _BluetoothAddressComparer class provides the comparer about two specified String
48 * which consists of Bluetooth address and service UUID.
50 class _BluetoothAddressComparer
51 : public Tizen::Base::Collection::IComparerT <Tizen::Base::String>
52 , public Tizen::Base::Object
55 _BluetoothAddressComparer(void) {}
56 virtual ~_BluetoothAddressComparer(void) {}
58 virtual result Compare(const Tizen::Base::String& obj1, const Tizen::Base::String& obj2, int& cmp) const
60 cmp = obj1.CompareTo(obj2);
65 _BluetoothAddressComparer(const _BluetoothAddressComparer& value);
66 _BluetoothAddressComparer& operator =(const _BluetoothAddressComparer& value);
68 }; //_BluetoothAddressComparer
71 * @class _BluetoothAddressHashCodeProviderT
72 * @brief The _BluetoothAddressHashCodeProviderT class provides the hash code of a specified String
73 * which consists of Bluetooth address and service UUID.
75 class _BluetoothAddressHashCodeProvider
76 : public Tizen::Base::Collection::IHashCodeProviderT <Tizen::Base::String>
79 _BluetoothAddressHashCodeProvider(void) {}
80 virtual ~_BluetoothAddressHashCodeProvider(void) {}
81 virtual int GetHashCode(const Tizen::Base::String& obj) const
83 return obj.GetHashCode();
87 _BluetoothAddressHashCodeProvider(const _BluetoothAddressHashCodeProvider& value);
88 _BluetoothAddressHashCodeProvider& operator =(const _BluetoothAddressHashCodeProvider& value);
90 }; //_BluetoothAddressHashCodeProvider
93 static _BluetoothAddressComparer _btAddressComparer;
94 static _BluetoothAddressHashCodeProvider _btAddressHashCodeProvider;
96 _BluetoothHdpSystemAdapter* _BluetoothHdpSystemAdapter::__pInstance = null;
98 _BluetoothHdpSystemAdapter::_BluetoothHdpSystemAdapter(void)
99 : __pAppHealthMap(null)
100 , __pChannelHealthMap(null)
101 , __pChannelAddressMap(null)
105 _BluetoothHdpSystemAdapter::~_BluetoothHdpSystemAdapter(void)
107 // unregister the callback methods from the underlying layer
108 int err = bt_hdp_unset_connection_state_changed_cb();
109 SysLog(NID_NET_BT, "[0x%x] error in unregistering the connection state change callback method", err);
111 err = bt_hdp_unset_data_received_cb();
112 SysLog(NID_NET_BT, "[0x%x] error in unregistering the data received state change callback method", err);
116 _BluetoothHdpSystemAdapter::InitSingleton(void)
119 static _BluetoothHdpSystemAdapter inst;
121 r = inst.Construct();
122 SysTryReturnVoidResult(NID_NET_BT, r == true, E_SYSTEM, "[E_SYSTEM] Propagating.");
127 _BluetoothHdpSystemAdapter*
128 _BluetoothHdpSystemAdapter::GetInstance(void)
130 static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
132 if (__pInstance == null)
135 pthread_once(&onceBlock, InitSingleton);
136 result r = GetLastResult();
139 onceBlock = PTHREAD_ONCE_INIT;
147 _BluetoothHdpSystemAdapter::Construct(void)
149 int err = BT_ERROR_NONE;
150 result r = E_SUCCESS;
151 unique_ptr<Tizen::Base::Collection::HashMapT< Tizen::Base::String, _BluetoothHealthImpl*> > pAppHealthMap;
152 unique_ptr<Tizen::Base::Collection::HashMapT< int, _BluetoothHealthImpl*> > pChannelHealthMap;
153 unique_ptr<Tizen::Base::Collection::HashMapT< int, Tizen::Base::String> > pChannelAddressMap;
155 pAppHealthMap.reset(new (std::nothrow) HashMapT<String, _BluetoothHealthImpl*>);
156 SysTryReturn(NID_NET_BT, pAppHealthMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
158 //Constructing the hashmap template with the default capacity(16) and loadFactor(0.75f)
159 r = pAppHealthMap->Construct(16, 0.75f, _btAddressHashCodeProvider, _btAddressComparer);
160 SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
162 pChannelHealthMap.reset(new (std::nothrow) HashMapT<int, _BluetoothHealthImpl*>);
163 SysTryReturn(NID_NET_BT, pChannelHealthMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
165 r = pChannelHealthMap->Construct();
166 SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
168 pChannelAddressMap.reset(new (std::nothrow) HashMapT<int, String>);
169 SysTryReturn(NID_NET_BT, pChannelAddressMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
171 r = pChannelAddressMap->Construct();
172 SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
174 //register a call back to be invoked when connection state of the Sink device changes
175 err = bt_hdp_set_connection_state_changed_cb(&OnHdpConnected, &OnHdpDisconnected, null);
176 SysTryReturn(NID_NET_BT, err == BT_ERROR_NONE, false, E_SYSTEM, "[E_SYSTEM] Registering the callback method has failed.");
178 //register a callback to be invoked when any health data is received by the Sink device
179 err = bt_hdp_set_data_received_cb(&OnHdpDataReceived, null);
180 if (err != BT_ERROR_NONE)
182 int errUnset = bt_hdp_unset_connection_state_changed_cb();
183 SysLog(NID_NET_BT, "[0x%x] error in unregistering the connection state change callback method", errUnset);
185 SysTryReturn(NID_NET_BT, err == BT_ERROR_NONE, false, E_SYSTEM, "[E_SYSTEM] Registering the callback method has failed.");
187 __pAppHealthMap = move(pAppHealthMap);
188 __pChannelHealthMap = move(pChannelHealthMap);
189 __pChannelAddressMap = move(pChannelAddressMap);
195 _BluetoothHdpSystemAdapter::StartSinkService(int dataType, _BluetoothHealthImpl& implListener, char** pAppId)
197 result r = E_OPERATION_FAILED;
198 int err = BT_ERROR_NONE;
203 // check HDP service availability
204 pUuidStr = _StringConverter::CopyToCharArrayN(UuId(BT_SVC_UUID_HDP).ToString());
205 err = bt_adapter_is_service_used(pUuidStr, &isUsed);
207 SysTryReturnResult(NID_NET_BT, (err == BT_ERROR_NONE) && !isUsed, E_SERVICE_UNAVAILABLE,
208 "[E_SERVICE_UNAVAILABLE] HDP sink service for the specified UUID is not available.");
210 err = bt_hdp_register_sink_app(dataType, pAppId);
211 SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_OPERATION_FAILED,
212 "[E_OPERATION_FAILED] Registering Sink role application for specified HDP data type is failed");
213 SysLog(NID_NET_BT, "Registering the HDP Sink role is successful [%d].", err);
215 String appIdString(*pAppId);
217 // Add the _BluetoothHealthImpl pointer to the event map using appIdString as the key.
218 r = __pAppHealthMap->Add(appIdString, &implListener);
219 SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
220 "[E_OPERATION_FAILED] Failed to add the _BluetoothHealthImpl instance to the map");
225 _BluetoothHdpSystemAdapter::StopService(const char* pAppId)
227 int err = BT_ERROR_NONE;
228 result r = E_OPERATION_FAILED;
230 String appIdString(pAppId);
232 err = bt_hdp_unregister_sink_app(pAppId);
233 SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_OPERATION_FAILED,
234 "[E_OPERATION_FAILED] Failed to unregister the given Sink Role HDP application");
235 SysLog(NID_NET_BT, "The Sink role HDP app is successfully unregistered");
237 // remove the specified appIdString from the application event map.
238 r = __pAppHealthMap->Remove(appIdString);
239 SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
240 "[E_OPERATION_FAILED] failed to remove the appId from the event map.");
246 _BluetoothHdpSystemAdapter::ConnectToSource(const Tizen::Base::ByteBuffer& sourceAddress, const char* pAppId)
248 int err = BT_ERROR_NONE;
249 result r = E_OPERATION_FAILED;
251 char* pSourceAddress = null;
253 SysTryReturnResult(NID_NET_BT, sourceAddress.GetRemaining() == _BT_ADDRESS_LENGTH, E_OPERATION_FAILED,
254 "The address of the remote Source device is incorrect.");
256 pSourceAddress = _StringConverter::CopyToCharArrayN(_BluetoothDeviceImpl::GetAddressString(sourceAddress));
257 SysTryReturnResult(NID_NET_BT, pSourceAddress != null, E_OPERATION_FAILED, "Converting address to char* fails.");
259 err = bt_hdp_connect_to_source(pSourceAddress, pAppId);
260 SysSecureLog(NID_NET_BT, "Connecting to the remote source device [%s] %s.", pSourceAddress,
261 err == BT_ERROR_NONE ? "is successful" : "fails");
262 if (err == BT_ERROR_NONE)
267 delete[] pSourceAddress;
272 _BluetoothHdpSystemAdapter::Disconnect(int channelId)
274 int err = BT_ERROR_NONE;
275 result r = E_OPERATION_FAILED;
277 String connectedAddress;
278 char* pSourceAddress = null;
280 r = __pChannelAddressMap->GetValue(channelId, connectedAddress);
281 SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "The channel ID is invalid.");
283 pSourceAddress = _StringConverter::CopyToCharArrayN(connectedAddress);
284 SysTryReturnResult(NID_NET_BT, pSourceAddress != null, E_OPERATION_FAILED, "Address converting fails.");
286 err = bt_hdp_disconnect(pSourceAddress, channelId);
287 SysSecureLog(NID_NET_BT, "Disconnecting from the remote source device [%s] with channel id [%d] %s.", pSourceAddress, channelId,
288 err == BT_ERROR_NONE ? "is successful" : "fails");
289 if (err == BT_ERROR_NONE)
294 delete[] pSourceAddress;
299 _BluetoothHdpSystemAdapter::SendData(int channelId, const Tizen::Base::ByteBuffer& data)
301 int err = BT_ERROR_NONE;
302 result r = E_OPERATION_FAILED;
304 const byte* pHealthData = null;
305 int healthDataLength = 0;
307 pHealthData = data.GetPointer();
308 pHealthData += data.GetPosition();
309 healthDataLength = data.GetRemaining();
311 err = bt_hdp_send_data(channelId, (char*)pHealthData, healthDataLength);
312 SysSecureLog(NID_NET_BT, "Sending data to the remote source with channel id [%d] of length [%d] %s.", channelId, healthDataLength,
313 err == BT_ERROR_NONE ? "is successful" : "fails");
314 if (err == BT_ERROR_NONE)
323 _BluetoothHdpSystemAdapter::OnHdpConnected(int status, const char* pRemoteAddress, const char* pAppId,
324 bt_hdp_channel_type_e channelType, unsigned int channelId, void* pUserData)
326 result r = E_OPERATION_FAILED;
328 BluetoothDevice btDevice;
329 ByteBuffer deviceAddress;
330 String remoteDeviceAddrStr(pRemoteAddress);
331 BluetoothHealthDataChannelType hdpchannelType = BT_HEALTH_DATA_CHANNEL_NONE;
333 _BluetoothHealthImpl* pHealthImpl = null;
334 String appIdString(pAppId);
336 _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
338 // retrieve the _BluetoothHealthImpl instance from the __pAppHealthMap by using appIdString as key
339 r = pHdpAdapter->__pAppHealthMap->GetValue(appIdString, pHealthImpl);
340 SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
341 "[E_OPERATION_FAILED] The application Id is unknown.");
343 r = deviceAddress.Construct(_BT_ADDRESS_LENGTH);
344 SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
345 "[E_OPERATION_FAILED] Failed to construct the address buffer");
347 (void) _BluetoothDeviceImpl::GetAddressByteBuffer(remoteDeviceAddrStr, L":", deviceAddress);
349 r = _BluetoothGapSystemAdapter::GetPairedDevice(deviceAddress, btDevice);
350 SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
351 "[E_OPERATION_FAILED] Getting information of the source health device has failed.");
353 if (status == BT_ERROR_NONE)
355 // insert the pHealthImpl into __pChannelHealthMap by using the specified channelId as key
356 r = pHdpAdapter->__pChannelHealthMap->Add(channelId, pHealthImpl);
359 SysLogException(NID_NET_BT, E_OPERATION_FAILED, "[%s] Propagating.", GetErrorMessage(r));
360 r = E_OPERATION_FAILED;
363 // insert the pRemoteAddress into __pChannelAddressMap by using the specified channelId as key
364 r = pHdpAdapter->__pChannelAddressMap->Add(channelId, remoteDeviceAddrStr);
367 SysLogException(NID_NET_BT, E_OPERATION_FAILED, "[%s] Propagating.", GetErrorMessage(r));
368 r = E_OPERATION_FAILED;
373 SysLog(NID_NET_BT, "[E_OPERATION_FAILED] Connection request failure is reported by the underlying system.");
374 r = E_OPERATION_FAILED;
377 hdpchannelType = ((channelType == BT_HDP_CHANNEL_TYPE_RELIABLE)?
378 BT_HEALTH_DATA_CHANNEL_RELIABLE : BT_HEALTH_DATA_CHANNEL_STREAMING);
380 // Fire the connect event using the _BluetoothHealthImpl handle
381 pHealthImpl->OnBluetoothHealthConnected(channelId, hdpchannelType, &btDevice, r);
385 _BluetoothHdpSystemAdapter::OnHdpDisconnected(int status, const char* pRemoteAddress, unsigned int channelId, void* pUserData)
389 BluetoothDevice btDevice;
390 ByteBuffer deviceAddress;
391 String remoteDeviceAddrStr(pRemoteAddress);
393 _BluetoothHealthImpl* pHealthImpl = null;
395 _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
397 // get the pointer of the _BluetoothHealthImpl from __pChannelHealthMap by using the specified channelId as a key
398 r = pHdpAdapter->__pChannelHealthMap->GetValue(channelId, pHealthImpl);
399 SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "[E_OPERATION_FAILED] The channel Id is unknown.");
401 if (status == BT_ERROR_NONE)
403 (void) pHdpAdapter->__pChannelHealthMap->Remove(channelId);
404 pHdpAdapter->__pChannelAddressMap->Remove(channelId);
408 SysLog(NID_NET_BT, "[E_OPERATION_FAILED] Disconnection request failure is reported by the underlying system [%d].", status);
409 r = E_OPERATION_FAILED;
412 // Fire the Disconnect event using the _BluetoothHealthImpl handle
413 pHealthImpl->OnBluetoothHealthDisconnected(channelId, r);
417 _BluetoothHdpSystemAdapter::OnHdpDataReceived(unsigned int channelId, const char* pData, unsigned int dataSize, void* pUserData)
419 result r = E_SUCCESS;
420 ByteBuffer dataBuffer;
422 _BluetoothHealthImpl* pHealthImpl = null;
424 _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
426 // find the appropriate _BluetoothHealthImpl handle with the given channelId
427 r = pHdpAdapter->__pChannelHealthMap->GetValue(channelId, pHealthImpl);
428 SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "[E_OPERATION_FAILED] unknown channelId.");
430 dataBuffer.Construct(dataSize);
431 dataBuffer.SetArray((byte*) pData, 0, dataSize);
432 dataBuffer.SetPosition(0);
434 // Fire the data received event using the _BluetoothHealthImpl handle
435 pHealthImpl->OnBluetoothHealthDataReceived(channelId, dataBuffer);
436 SysSecureLog(NID_NET_BT, " Received Health data of (%d bytes) through the channel (ID: %d) is received.", dataSize, channelId);
439 } } } // Tizen::Net::Bluetooth