2 // Tizen Web Device API
3 // Copyright (c) 2012 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.
20 #include <JSWebAPIErrorFactory.h>
22 #include <TimeTracer.h>
24 #include "BluetoothHealthProfileHandler.h"
25 #include "BluetoothHealthProfileHandlerCallback.h"
26 #include "JSBluetoothHealthApplication.h"
27 #include "JSBluetoothDevice.h"
28 #include "JSBluetoothHealthChannel.h"
29 #include "BluetoothHealthChannel.h"
31 using namespace DeviceAPI::Common;
36 void BluetoothHealthProfileHandler::onConnected(int result, const char *remote_address, const char *app_id,
37 bt_hdp_channel_type_e type, unsigned int channel, void *userData)
40 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
42 HealthProfileHandlerPtr object = static_cast<HealthProfileHandlerPtr>(userData);
44 LoggerW("userData is NULL");
48 if(result != BT_ERROR_NONE) {
49 LoggerD("Not BT_ERROR_NONE");
52 LoggerD("Connected app: " << app_id);
53 LoggerD("Connected channel: " << channel);
55 std::string appID(app_id);
56 RegisteredHealthAppMapT::iterator iter = object->mRegisteredHealthAppMap.find(appID);
57 if(iter == object->mRegisteredHealthAppMap.end()) {
58 LoggerW("This app is not registered");
61 BluetoothHealthApplicationSharedPtr application = iter->second;
63 bool isChannelInserted = false;
64 BluetoothHealthChannelPtr healthChannel = NULL;
66 // call BluetoothHealthApplication.onconnect
67 if(result == BT_ERROR_NONE) {
68 Common::MultiCallbackUserDataPtr callback = application->getOnConnect();
70 bt_device_info_s *deviceInfo = NULL;
71 if(bt_adapter_get_bonded_device_info(remote_address, &deviceInfo) == BT_ERROR_NONE &&
73 BluetoothDeviceSharedPtr device(new BluetoothDevice(deviceInfo));
75 device->copyAceCheckAccessFunction(getInstance());
76 bt_adapter_free_device_info(deviceInfo);
78 LoggerD("invoke BluetoothHealthApplication.onconnect");
79 healthChannel = new BluetoothHealthChannel(channel, device, type, application);
80 healthChannel->copyAceCheckAccessFunction(getInstance());
81 object->mConnectedSocketMap.insert(std::pair<unsigned int, BluetoothHealthChannelPtr>(channel, healthChannel));
82 isChannelInserted = true;
83 callback->invokeCallback("onconnect", JSBluetoothHealthChannel::createJSObject(callback->getContext(), healthChannel));
86 LoggerE("Can't call BluetoothHealthApplication.onconnect because failed to get device info");
90 LoggerD("BluetoothHealthApplication.onconnect is not set");
94 // in case of connectToSource()
95 HealthConnReqMapT::iterator i = object->mHealthConnReqMap.find(application);
96 if(i != object->mHealthConnReqMap.end()) {
97 LoggerD("Requested connection");
98 Common::MultiCallbackUserDataPtr callback = i->second->mUserData;
100 if(result == BT_ERROR_NONE) {
101 if(isChannelInserted == false) {
102 healthChannel = new BluetoothHealthChannel(channel, i->second->mRemoteDevice, type, application);
103 healthChannel->copyAceCheckAccessFunction(getInstance());
104 object->mConnectedSocketMap.insert(std::pair<unsigned int, BluetoothHealthChannelPtr>(channel, healthChannel));
106 callback->invokeCallback("success", JSBluetoothHealthChannel::createJSObject(callback->getContext(), healthChannel));
109 LoggerE("Failed to establish a connection with health profile");
110 callback->invokeCallback("error",
111 JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), UnknownException("Failed to establish a connection with health profile")));
115 // Update mHealthConnReqMap
116 object->mHealthConnReqMap.erase(i);
119 LoggerD("There is no connection request");
122 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
125 void BluetoothHealthProfileHandler::onDisconnected(int result, const char *remote_address, unsigned int channel, void *userData)
128 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
130 HealthProfileHandlerPtr object = static_cast<HealthProfileHandlerPtr>(userData);
132 LoggerW("userData is NULL");
136 LoggerD("Disconnected channel: " << channel);
137 HealthConnectedSocketMapT::iterator iter = object->mConnectedSocketMap.find(channel);
138 if(iter == object->mConnectedSocketMap.end()) {
139 LoggerW("Unexpected health disconnection event");
143 if(result == BT_ERROR_NONE) {
144 BluetoothHealthChannelPtr healthChannel = iter->second;
145 object->mConnectedSocketMap.erase(iter);
147 healthChannel->setConnectionState(false);
148 MultiCallbackUserDataPtr callback = healthChannel->getListener();
150 callback->invokeCallback("onclose");
153 LoggerW("Failed to disconnect a connection");
156 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
160 void BluetoothHealthProfileHandler::onDataReceivedCB(unsigned int channel, const char *data, unsigned int size, void *userData)
164 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
166 HealthProfileHandlerPtr object = static_cast<HealthProfileHandlerPtr>(userData);
168 LoggerW("userData is NULL");
172 LoggerD("data channel: " << channel);
173 LoggerD("sent data size: " << size);
174 HealthConnectedSocketMapT::iterator iter = object->mConnectedSocketMap.find(channel);
175 if(iter == object->mConnectedSocketMap.end()) {
176 LoggerW("Unexpected health data received event");
180 BluetoothHealthChannelPtr healthChannel = iter->second;
181 MultiCallbackUserDataPtr callback = healthChannel->getListener();
183 std::vector<signed char> receivedData;
184 for(unsigned int i = 0; i < size; i++) {
185 receivedData.push_back(static_cast<signed char>(data[i]));
187 callback->invokeCallback("onmessage", JSUtil::toJSValueRef_(callback->getContext(), receivedData));
190 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
193 BluetoothHealthProfileHandler* BluetoothHealthProfileHandler::getInstance()
195 static BluetoothHealthProfileHandler instance;
199 BluetoothHealthProfileHandler::BluetoothHealthProfileHandler()
201 Common::SecurityAccessor();
203 if(bt_hdp_set_connection_state_changed_cb(onConnected, onDisconnected, this) != BT_ERROR_NONE) {
204 LoggerE("bt_hdp_set_connection_state_changed_cb() failed");
207 if(bt_hdp_set_data_received_cb(onDataReceivedCB, this) != BT_ERROR_NONE) {
208 LoggerE("bt_hdp_set_data_received_cb() failed");
213 BluetoothHealthProfileHandler::~BluetoothHealthProfileHandler()
215 // unset platform callback
216 bt_hdp_unset_connection_state_changed_cb();
217 bt_hdp_unset_data_received_cb();
219 mHealthConnReqMap.clear();
220 mConnectedSocketMap.clear();
221 mRegisteredHealthAppMap.clear();
224 void BluetoothHealthProfileHandler::registerSinkApp(unsigned short dataType, std::string name, Common::MultiCallbackUserDataPtr callback)
226 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
227 BluetoothHealthProfileHandlerCallback::syncToAsyncRegisterCB(callback, dataType, name);
228 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
231 void BluetoothHealthProfileHandler::returnRegisteringSinkAppResult(unsigned short dataType, std::string name, Common::MultiCallbackUserDataPtr callback)
234 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
237 int ret = bt_hdp_register_sink_app(dataType, &app_id);
241 LoggerD("Registered app: " << app_id);
242 std::string appID(app_id);
244 BluetoothHealthApplicationSharedPtr application(new BluetoothHealthApplication(appID, name, dataType));
245 application->copyAceCheckAccessFunction(getInstance());
247 mRegisteredHealthAppMap.insert(std::pair<std::string, BluetoothHealthApplicationSharedPtr>(appID, application));
249 callback->invokeCallback("success", JSBluetoothHealthApplication::createJSObject(callback->getContext(), application));
252 case BT_ERROR_NOT_ENABLED:
255 callback->invokeCallback("error",
256 JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), ServiceNotAvailableException("Bluetooth device is turned off")));
263 callback->invokeCallback("error",
264 JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), UnknownException("Unknown error")));
269 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
273 void BluetoothHealthProfileHandler::unregisterSinkApplication(JSObjectRef appObj, Common::MultiCallbackUserDataPtr callback)
275 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
276 BluetoothHealthProfileHandlerCallback::syncToAsyncUnregisterCB(callback, appObj);
277 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
280 void BluetoothHealthProfileHandler::returnUnregisteringResult(JSObjectRef appObj, Common::MultiCallbackUserDataPtr callback)
282 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
284 BluetoothHealthApplicationSharedPtr app = JSBluetoothHealthApplication::toBluetoothHealthApplication(appObj);
285 int ret = bt_hdp_unregister_sink_app(app->getAppID().c_str());
289 //app->setRegistrationState(false);
290 BluetoothHealthProfileHandlerCallback::syncToAsyncSuccessCB(callback);
293 case BT_ERROR_NOT_ENABLED:
295 ServiceNotAvailableException *error = new ServiceNotAvailableException("Bluetooth device is turned off");
296 BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
301 UnknownException *error = new UnknownException("Unknown error");
302 BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
306 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
310 void BluetoothHealthProfileHandler::unregisterApp(std::string appID, Common::MultiCallbackUserDataPtr callback)
312 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
313 BluetoothHealthProfileHandlerCallback::syncToAsyncUnregisterCB(callback, appID);
314 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
317 void BluetoothHealthProfileHandler::returnUnregisteringAppResult(std::string appID, Common::MultiCallbackUserDataPtr callback)
319 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
321 RegisteredHealthAppMapT::iterator iter = mRegisteredHealthAppMap.find(appID);
322 BluetoothHealthApplicationSharedPtr application;
323 if(iter != mRegisteredHealthAppMap.end()) {
324 LoggerE("registered Health Application is found");
325 application = iter->second;
328 LoggerD("Already unregistered");
330 callback->invokeCallback("success");
334 int ret = bt_hdp_unregister_sink_app(appID.c_str());
338 mRegisteredHealthAppMap.erase(iter);
339 application->setRegistrationState(false);
341 callback->invokeCallback("success");
344 case BT_ERROR_NOT_ENABLED:
347 callback->invokeCallback("error",
348 JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), ServiceNotAvailableException("Bluetooth device is turned off")));
355 callback->invokeCallback("error",
356 JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), UnknownException("Unknown error")));
361 TIME_TRACER_ITEM_END(__FUNCTION__, 1);
364 void BluetoothHealthProfileHandler::connectToSource(JSObjectRef remoteDeviceObj, JSObjectRef appObj, Common::MultiCallbackUserDataPtr callback)
368 TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
370 BluetoothDeviceSharedPtr device = JSBluetoothDevice::toBluetoothDevice(remoteDeviceObj);
371 BluetoothHealthApplicationSharedPtr app = JSBluetoothHealthApplication::toBluetoothHealthApplication(appObj);
372 LoggerD("address: " << device->getAddress().c_str());
373 LoggerD("app ID: " << app->getAppID().c_str());
374 int ret = bt_hdp_connect_to_source(device->getAddress().c_str(), app->getAppID().c_str());
379 HealthConnReqPtr connReq = new HealthConnReq(device, callback);
380 mHealthConnReqMap.insert(std::pair<BluetoothHealthApplicationSharedPtr, HealthConnReqPtr>(app, connReq));
383 case BT_ERROR_NOT_ENABLED:
385 LoggerD("Not Enabled");
386 ServiceNotAvailableException *error = new ServiceNotAvailableException("Bluetooth device is turned off");
387 BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
390 case BT_ERROR_INVALID_PARAMETER:
391 case BT_ERROR_REMOTE_DEVICE_NOT_BONDED:
393 LoggerD("invalid value");
394 InvalidValuesException *error = new InvalidValuesException("Invalid value");
395 BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
400 LoggerD("Unknown error");
401 UnknownException *error = new UnknownException("Unknown error");
402 BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, error);
406 TIME_TRACER_ITEM_END(__FUNCTION__, 1);