287a9fe4dbe94af4545d43d4917e48993a79b2fd
[platform/framework/native/bluetooth.git] / src / FNetBt_BluetoothHdpSystemAdapter.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
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
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17 // @file        FNetBt_BluetoothHdpSystemAdapter.cpp
18 // @brief       This is the implementation file for the _BluetoothHdpSystemAdapter class.
19 //
20
21 #include <pthread.h>
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"
36
37 using namespace std;
38 using namespace Tizen::Base;
39 using namespace Tizen::Base::Collection;
40 using namespace Tizen::Base::Utility;
41
42 namespace Tizen { namespace Net { namespace Bluetooth
43 {
44
45 /*
46  * @class               _BluetoothAddressComparer
47  * @brief               The _BluetoothAddressComparer class provides the comparer about two specified String
48  *              which consists of Bluetooth address and service UUID.
49  */
50 class _BluetoothAddressComparer
51         : public Tizen::Base::Collection::IComparerT <Tizen::Base::String>
52         , public Tizen::Base::Object
53 {
54 public:
55         _BluetoothAddressComparer(void) {}
56         virtual ~_BluetoothAddressComparer(void) {}
57
58         virtual result Compare(const Tizen::Base::String& obj1, const Tizen::Base::String& obj2, int& cmp) const
59         {
60                 cmp = obj1.CompareTo(obj2);
61                 return E_SUCCESS;
62         }
63
64 private:
65         _BluetoothAddressComparer(const _BluetoothAddressComparer& value);
66         _BluetoothAddressComparer& operator =(const _BluetoothAddressComparer& value);
67
68 };      //_BluetoothAddressComparer
69
70 /*
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.
74  */
75 class _BluetoothAddressHashCodeProvider
76         : public Tizen::Base::Collection::IHashCodeProviderT <Tizen::Base::String>
77 {
78 public:
79         _BluetoothAddressHashCodeProvider(void) {}
80         virtual ~_BluetoothAddressHashCodeProvider(void) {}
81         virtual int GetHashCode(const Tizen::Base::String& obj) const
82         {
83                 return obj.GetHashCode();
84         }
85
86 private:
87         _BluetoothAddressHashCodeProvider(const _BluetoothAddressHashCodeProvider& value);
88         _BluetoothAddressHashCodeProvider& operator =(const _BluetoothAddressHashCodeProvider& value);
89
90 };      //_BluetoothAddressHashCodeProvider
91
92
93 static _BluetoothAddressComparer _btAddressComparer;
94 static _BluetoothAddressHashCodeProvider _btAddressHashCodeProvider;
95
96 _BluetoothHdpSystemAdapter* _BluetoothHdpSystemAdapter::__pInstance = null;
97
98 _BluetoothHdpSystemAdapter::_BluetoothHdpSystemAdapter(void)
99         : __pAppHealthMap(null)
100         , __pChannelHealthMap(null)
101         , __pChannelAddressMap(null)
102 {
103 }
104
105 _BluetoothHdpSystemAdapter::~_BluetoothHdpSystemAdapter(void)
106 {
107 }
108
109 void
110 _BluetoothHdpSystemAdapter::InitSingleton(void)
111 {
112         bool r = false;
113         std::unique_ptr<_BluetoothHdpSystemAdapter> pInst;
114
115         pInst.reset(new (std::nothrow) _BluetoothHdpSystemAdapter());
116         r = pInst->Construct();
117         SysTryReturnVoidResult(NID_NET_BT, r == true, E_SYSTEM, "[E_SYSTEM] Propagating.");
118
119         __pInstance = pInst.release();
120
121         std::atexit(DeinitializeSingleton);
122 }
123
124 void
125 _BluetoothHdpSystemAdapter::DeinitializeSingleton(void)
126 {
127         // unregister the callback methods from the underlying layer
128         int err = bt_hdp_unset_connection_state_changed_cb();
129         SysLog(NID_NET_BT, "[0x%x] error in unregistering the connection state change callback method", err);
130
131         err = bt_hdp_unset_data_received_cb();
132         SysLog(NID_NET_BT, "[0x%x] error in unregistering the data received state change callback method", err);
133 }
134
135 _BluetoothHdpSystemAdapter*
136 _BluetoothHdpSystemAdapter::GetInstance(void)
137 {
138         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
139
140         if (__pInstance == null)
141         {
142                 ClearLastResult();
143                 pthread_once(&onceBlock, InitSingleton);
144                 result r = GetLastResult();
145                 if (IsFailed(r))
146                 {
147                         onceBlock = PTHREAD_ONCE_INIT;
148                 }
149         }
150
151         return __pInstance;
152 }
153
154 bool
155 _BluetoothHdpSystemAdapter::Construct(void)
156 {
157         int err = BT_ERROR_NONE;
158         result r = E_SUCCESS;
159         unique_ptr<Tizen::Base::Collection::HashMapT< Tizen::Base::String, _BluetoothHealthImpl*> > pAppHealthMap;
160         unique_ptr<Tizen::Base::Collection::HashMapT< int, _BluetoothHealthImpl*> > pChannelHealthMap;
161         unique_ptr<Tizen::Base::Collection::HashMapT< int, Tizen::Base::String> > pChannelAddressMap;
162
163         pAppHealthMap.reset(new (std::nothrow) HashMapT<String, _BluetoothHealthImpl*>);
164         SysTryReturn(NID_NET_BT, pAppHealthMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
165
166         //Constructing the hashmap template with the default capacity(16) and loadFactor(0.75f)
167         r = pAppHealthMap->Construct(16, 0.75f, _btAddressHashCodeProvider, _btAddressComparer);
168         SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
169
170         pChannelHealthMap.reset(new (std::nothrow) HashMapT<int, _BluetoothHealthImpl*>);
171         SysTryReturn(NID_NET_BT, pChannelHealthMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
172
173         r = pChannelHealthMap->Construct();
174         SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
175
176         pChannelAddressMap.reset(new (std::nothrow) HashMapT<int, String>);
177         SysTryReturn(NID_NET_BT, pChannelAddressMap != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
178
179         r = pChannelAddressMap->Construct();
180         SysTryReturn(NID_NET_BT, r == E_SUCCESS, false, r, "[%s] Propagating.", GetErrorMessage(r));
181
182         //register a call back to be invoked when connection state of the Sink device changes
183         err = bt_hdp_set_connection_state_changed_cb(&OnHdpConnected, &OnHdpDisconnected, null);
184         SysTryReturn(NID_NET_BT, err == BT_ERROR_NONE, false, E_SYSTEM, "[E_SYSTEM] Registering the callback method has failed.");
185
186         //register a callback to be invoked when any health data is received by the Sink device
187         err = bt_hdp_set_data_received_cb(&OnHdpDataReceived, null);
188         if (err != BT_ERROR_NONE)
189         {
190                 int errUnset = bt_hdp_unset_connection_state_changed_cb();
191                 SysLog(NID_NET_BT, "[0x%x] error in unregistering the connection state change callback method", errUnset);
192         }
193         SysTryReturn(NID_NET_BT, err == BT_ERROR_NONE, false, E_SYSTEM, "[E_SYSTEM] Registering the callback method has failed.");
194
195         __pAppHealthMap = move(pAppHealthMap);
196         __pChannelHealthMap = move(pChannelHealthMap);
197         __pChannelAddressMap = move(pChannelAddressMap);
198
199         return true;
200 }
201
202 result
203 _BluetoothHdpSystemAdapter::StartSinkService(int dataType, _BluetoothHealthImpl& implListener, char** pAppId)
204 {
205         result r = E_OPERATION_FAILED;
206         int err = BT_ERROR_NONE;
207
208         char* pUuidStr;
209         bool isUsed = false;
210
211         // check HDP service availability
212         pUuidStr = _StringConverter::CopyToCharArrayN(UuId(BT_SVC_UUID_HDP).ToString());
213         err = bt_adapter_is_service_used(pUuidStr, &isUsed);
214         delete[] pUuidStr;
215         SysTryReturnResult(NID_NET_BT, (err == BT_ERROR_NONE) && !isUsed, E_SERVICE_UNAVAILABLE,
216                         "[E_SERVICE_UNAVAILABLE] HDP sink service for the specified UUID is not available.");
217
218         err = bt_hdp_register_sink_app(dataType, pAppId);
219         SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_OPERATION_FAILED,
220                         "[E_OPERATION_FAILED] Registering Sink role application for specified HDP data type is failed");
221         SysLog(NID_NET_BT, "Registering the HDP Sink role is successful [%d].", err);
222
223         String appIdString(*pAppId);
224
225         // Add the _BluetoothHealthImpl pointer to the event map using appIdString as the key.
226         r = __pAppHealthMap->Add(appIdString, &implListener);
227         SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
228                         "[E_OPERATION_FAILED] Failed to add the _BluetoothHealthImpl instance to the map");
229         return E_SUCCESS;
230 }
231
232 result
233 _BluetoothHdpSystemAdapter::StopService(const char* pAppId)
234 {
235         int err = BT_ERROR_NONE;
236         result r = E_OPERATION_FAILED;
237
238         String appIdString(pAppId);
239
240         err = bt_hdp_unregister_sink_app(pAppId);
241         SysTryReturnResult(NID_NET_BT, err == BT_ERROR_NONE, E_OPERATION_FAILED,
242                         "[E_OPERATION_FAILED] Failed to unregister the given Sink Role HDP application");
243         SysLog(NID_NET_BT, "The Sink role HDP app is successfully unregistered");
244
245         // remove the specified appIdString from the application event map.
246         r = __pAppHealthMap->Remove(appIdString);
247         SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
248                         "[E_OPERATION_FAILED] failed to remove the appId from the event map.");
249
250         return E_SUCCESS;
251 }
252
253 result
254 _BluetoothHdpSystemAdapter::ConnectToSource(const Tizen::Base::ByteBuffer& sourceAddress, const char* pAppId)
255 {
256         int err = BT_ERROR_NONE;
257         result r = E_OPERATION_FAILED;
258
259         char* pSourceAddress = null;
260
261         SysTryReturnResult(NID_NET_BT, sourceAddress.GetRemaining() == _BT_ADDRESS_LENGTH, E_OPERATION_FAILED,
262                                                 "The address of the remote Source device is incorrect.");
263
264         pSourceAddress = _StringConverter::CopyToCharArrayN(_BluetoothDeviceImpl::GetAddressString(sourceAddress));
265         SysTryReturnResult(NID_NET_BT, pSourceAddress != null, E_OPERATION_FAILED, "Converting address to char* fails.");
266
267         err = bt_hdp_connect_to_source(pSourceAddress, pAppId);
268         SysSecureLog(NID_NET_BT, "Connecting to the remote source device  [%s] %s.", pSourceAddress,
269                                                 err == BT_ERROR_NONE ? "is successful" : "fails");
270         if (err == BT_ERROR_NONE)
271         {
272                 r = E_SUCCESS;
273         }
274
275         delete[] pSourceAddress;
276         return r;
277 }
278
279 result
280 _BluetoothHdpSystemAdapter::Disconnect(int channelId)
281 {
282         int err = BT_ERROR_NONE;
283         result r = E_OPERATION_FAILED;
284
285         String connectedAddress;
286         char* pSourceAddress = null;
287
288         r = __pChannelAddressMap->GetValue(channelId, connectedAddress);
289         SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "The channel ID is invalid.");
290
291         pSourceAddress = _StringConverter::CopyToCharArrayN(connectedAddress);
292         SysTryReturnResult(NID_NET_BT, pSourceAddress != null, E_OPERATION_FAILED, "Address converting fails.");
293
294         err = bt_hdp_disconnect(pSourceAddress, channelId);
295         SysSecureLog(NID_NET_BT, "Disconnecting from the remote source device [%s] with channel id [%d] %s.", pSourceAddress, channelId,
296                                                 err == BT_ERROR_NONE ? "is successful" : "fails");
297         if (err == BT_ERROR_NONE)
298         {
299                 r = E_SUCCESS;
300         }
301
302         delete[] pSourceAddress;
303         return r;
304 }
305
306 result
307 _BluetoothHdpSystemAdapter::SendData(int channelId, const Tizen::Base::ByteBuffer& data)
308 {
309         int err = BT_ERROR_NONE;
310         result r = E_OPERATION_FAILED;
311
312         const byte* pHealthData = null;
313         int healthDataLength = 0;
314
315         pHealthData = data.GetPointer();
316         pHealthData += data.GetPosition();
317         healthDataLength = data.GetRemaining();
318
319         err = bt_hdp_send_data(channelId, (char*)pHealthData, healthDataLength);
320         SysSecureLog(NID_NET_BT, "Sending data to the remote source with channel id [%d] of length [%d] %s.", channelId, healthDataLength,
321                                                 err == BT_ERROR_NONE ? "is successful" : "fails");
322         if (err == BT_ERROR_NONE)
323         {
324                 r = E_SUCCESS;
325         }
326
327         return r;
328 }
329
330 void
331 _BluetoothHdpSystemAdapter::OnHdpConnected(int status, const char* pRemoteAddress, const char* pAppId,
332                 bt_hdp_channel_type_e channelType, unsigned int channelId, void* pUserData)
333 {
334         result r = E_OPERATION_FAILED;
335
336         BluetoothDevice btDevice;
337         ByteBuffer deviceAddress;
338         String remoteDeviceAddrStr(pRemoteAddress);
339         BluetoothHealthDataChannelType hdpchannelType = BT_HEALTH_DATA_CHANNEL_NONE;
340
341         _BluetoothHealthImpl* pHealthImpl = null;
342         String appIdString(pAppId);
343
344         _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
345
346         // retrieve the _BluetoothHealthImpl instance from the __pAppHealthMap by using appIdString as key
347         r = pHdpAdapter->__pAppHealthMap->GetValue(appIdString, pHealthImpl);
348         SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
349                         "[E_OPERATION_FAILED] The application Id is unknown.");
350
351         r = deviceAddress.Construct(_BT_ADDRESS_LENGTH);
352         SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
353                         "[E_OPERATION_FAILED] Failed to construct the address buffer");
354
355         (void) _BluetoothDeviceImpl::GetAddressByteBuffer(remoteDeviceAddrStr, L":", deviceAddress);
356
357         r = _BluetoothGapSystemAdapter::GetPairedDevice(deviceAddress, btDevice);
358         SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED,
359                         "[E_OPERATION_FAILED] Getting information of the source health device has failed.");
360
361         if (status == BT_ERROR_NONE)
362         {
363                 // insert the pHealthImpl into __pChannelHealthMap by using the specified channelId as key
364                 r = pHdpAdapter->__pChannelHealthMap->Add(channelId, pHealthImpl);
365                 if (r != E_SUCCESS)
366                 {
367                         SysLogException(NID_NET_BT, E_OPERATION_FAILED, "[%s] Propagating.", GetErrorMessage(r));
368                         r = E_OPERATION_FAILED;
369                 }
370
371                 // insert the pRemoteAddress into __pChannelAddressMap by using the specified channelId as key
372                 r = pHdpAdapter->__pChannelAddressMap->Add(channelId, remoteDeviceAddrStr);
373                 if (r != E_SUCCESS)
374                 {
375                         SysLogException(NID_NET_BT, E_OPERATION_FAILED, "[%s] Propagating.", GetErrorMessage(r));
376                         r = E_OPERATION_FAILED;
377                 }
378         }
379         else
380         {
381                 SysLog(NID_NET_BT, "[E_OPERATION_FAILED] Connection request failure is reported by the underlying system.");
382                 r = E_OPERATION_FAILED;
383         }
384
385         hdpchannelType = ((channelType == BT_HDP_CHANNEL_TYPE_RELIABLE)?
386                         BT_HEALTH_DATA_CHANNEL_RELIABLE : BT_HEALTH_DATA_CHANNEL_STREAMING);
387
388         // Fire the connect event using the _BluetoothHealthImpl handle
389         pHealthImpl->OnBluetoothHealthConnected(channelId, hdpchannelType, &btDevice, r);
390 }
391
392 void
393 _BluetoothHdpSystemAdapter::OnHdpDisconnected(int status, const char* pRemoteAddress, unsigned int channelId, void* pUserData)
394 {
395         result r = E_SYSTEM;
396
397         BluetoothDevice btDevice;
398         ByteBuffer deviceAddress;
399         String remoteDeviceAddrStr(pRemoteAddress);
400
401         _BluetoothHealthImpl* pHealthImpl = null;
402
403         _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
404
405          // get the pointer of the _BluetoothHealthImpl from __pChannelHealthMap by using the specified channelId as a key
406         r = pHdpAdapter->__pChannelHealthMap->GetValue(channelId, pHealthImpl);
407         SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "[E_OPERATION_FAILED] The channel Id is unknown.");
408
409         if (status == BT_ERROR_NONE)
410         {
411                 (void) pHdpAdapter->__pChannelHealthMap->Remove(channelId);
412                 pHdpAdapter->__pChannelAddressMap->Remove(channelId);
413         }
414         else
415         {
416                 SysLog(NID_NET_BT, "[E_OPERATION_FAILED] Disconnection request failure is reported by the underlying system [%d].", status);
417                 r = E_OPERATION_FAILED;
418         }
419
420         // Fire the Disconnect event using the _BluetoothHealthImpl handle
421         pHealthImpl->OnBluetoothHealthDisconnected(channelId, r);
422 }
423
424 void
425 _BluetoothHdpSystemAdapter::OnHdpDataReceived(unsigned int channelId, const char* pData, unsigned int dataSize, void* pUserData)
426 {
427         result r = E_SUCCESS;
428         ByteBuffer dataBuffer;
429
430         _BluetoothHealthImpl* pHealthImpl = null;
431
432         _BluetoothHdpSystemAdapter* pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance();
433
434         // find the appropriate _BluetoothHealthImpl handle with the given channelId
435         r = pHdpAdapter->__pChannelHealthMap->GetValue(channelId, pHealthImpl);
436         SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "[E_OPERATION_FAILED] unknown channelId.");
437
438         dataBuffer.Construct(dataSize);
439         dataBuffer.SetArray((byte*) pData, 0, dataSize);
440         dataBuffer.SetPosition(0);
441
442         // Fire the data received event using the _BluetoothHealthImpl handle
443         pHealthImpl->OnBluetoothHealthDataReceived(channelId, dataBuffer);
444         SysSecureLog(NID_NET_BT, " Received Health data of (%d bytes) through the channel (ID: %d) is received.",       dataSize, channelId);
445 }
446
447 } } }  // Tizen::Net::Bluetooth