// // Open Service Platform // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. // // Licensed under the Apache License, Version 2.0 (the License); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // @file FNetBt_BluetoothHealthImpl.cpp // @brief This is the implementation file for the _BluetoothHealthImpl class. // #include #include #include #include #include "FNetBt_BluetoothHealthEvent.h" #include "FNetBt_BluetoothHealthEventArg.h" #include "FNetBt_BluetoothGapSystemAdapter.h" #include "FNetBt_BluetoothHdpSystemAdapter.h" #include "FNetBt_BluetoothHealthImpl.h" using namespace std; using namespace Tizen::Base; using namespace Tizen::Base::Runtime; namespace Tizen { namespace Net { namespace Bluetooth { _BluetoothHealthImpl::_BluetoothHealthImpl(void) : __pGapAdapter(null) , __pHdpAdapter(null) , __pEvent(null) , __stateMutex() , __currentState(_BT_HEALTH_STATE_DISABLED) , __channelIdList() , __pairingTargetAddress() , __pAppId(null) , __dataType(_BT_INVALID_DATA_TYPE) { } _BluetoothHealthImpl::~_BluetoothHealthImpl(void) { int count = 0; int channelId = 0; if (__pHdpAdapter != null) { count = __channelIdList.GetCount(); for (int i=0; iDisconnect(channelId); } } if (__pGapAdapter != null) { __pGapAdapter->UnregisterManagerEventListener(*this); __pGapAdapter->UnregisterDeviceEventListener(*this); } } result _BluetoothHealthImpl::Construct(IBluetoothHealthEventListener& listener) { result r = E_SUCCESS; unique_ptr<_BluetoothHealthEvent> pEvent; r = __stateMutex.Create(); SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "Failed to create the state mutex."); r = __pairingTargetAddress.Construct(_BT_ADDRESS_LENGTH); SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "Failed to construct the address for pairing."); __pGapAdapter = _BluetoothGapSystemAdapter::GetInstance(); SysTryReturnResult(NID_NET_BT, __pGapAdapter != null, E_OPERATION_FAILED, "Failed to invoke _BluetoothGapSystemAdapter::GetInstance()."); __pHdpAdapter = _BluetoothHdpSystemAdapter::GetInstance(); SysTryReturnResult(NID_NET_BT, __pHdpAdapter != null, E_OPERATION_FAILED, "Failed to invoke _BluetoothHdpSystemAdapter::GetInstance()."); pEvent.reset(new (std::nothrow) _BluetoothHealthEvent()); SysTryReturnResult(NID_NET_BT, pEvent != null, E_OUT_OF_MEMORY, "The memory is insufficient."); r = pEvent->Construct(); SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "Failed to construct the event."); // add IBluetoothHealthEventListener instance to the newly created _BluetoothHealthEvent. r = pEvent->AddListener(listener, true); SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "Propagating. Failed to add the application listener for health device"); // registers this callback listener to the system adapter for activation/deactivation event r = __pGapAdapter->RegisterManagerEventListener(*this, true); SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "Failed to register the callback listener to _BluetoothGapSystemAdapter."); // registers this callback listener to the system adapter for paired event r = __pGapAdapter->RegisterDeviceEventListener(*this); if (r != E_SUCCESS) { __pGapAdapter->UnregisterManagerEventListener(*this); } SysTryReturnResult(NID_NET_BT, r == E_SUCCESS, E_OPERATION_FAILED, "Failed to register the callback listener to _BluetoothGapSystemAdapter."); // checks whether the Bluetooth is available __stateMutex.Acquire(); if (__pGapAdapter->IsActivated() == true) { __currentState = _BT_HEALTH_STATE_IDLE; } __stateMutex.Release(); __pEvent = move(pEvent); return E_SUCCESS; } result _BluetoothHealthImpl::StartAsSink(int dataType) { SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState()); result r = E_SUCCESS; char* pAppId = null; __stateMutex.Acquire(); switch (__currentState) { case _BT_HEALTH_STATE_DISABLED: r = E_INVALID_STATE; break; case _BT_HEALTH_STATE_IDLE: r = __pHdpAdapter->StartSinkService(dataType, *this, &pAppId); if (r == E_SUCCESS) { __currentState = _BT_HEALTH_STATE_ON_SERVICE; __dataType = dataType; __pAppId.reset(pAppId); } break; case _BT_HEALTH_STATE_ON_SERVICE: case _BT_HEALTH_STATE_BONDING: case _BT_HEALTH_STATE_BOND_CANCELING: if (__dataType == dataType) { r = E_IN_PROGRESS; } else { r = E_INVALID_OPERATION; } break; default: r = E_OPERATION_FAILED; break; } __stateMutex.Release(); if (r != E_SUCCESS) { SysLogException(NID_NET_BT, r, "[%s] exception occurred on starting Health sink role.", GetErrorMessage(r)); } SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r)); return r; } result _BluetoothHealthImpl::Stop(void) { SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState()); result r = E_SUCCESS; __stateMutex.Acquire(); switch (__currentState) { case _BT_HEALTH_STATE_DISABLED: r = E_INVALID_STATE; break; case _BT_HEALTH_STATE_IDLE: case _BT_HEALTH_STATE_BOND_CANCELING: r = E_INVALID_OPERATION; break; case _BT_HEALTH_STATE_ON_SERVICE: r = __pHdpAdapter->StopService(__pAppId.get()); if (r == E_SUCCESS) { __currentState = _BT_HEALTH_STATE_IDLE; __pAppId.reset(null); __dataType = _BT_INVALID_DATA_TYPE; } break; case _BT_HEALTH_STATE_BONDING: if (__pGapAdapter->CancelPair() == E_SUCCESS) { r = E_SUCCESS; __currentState = _BT_HEALTH_STATE_BOND_CANCELING; } // It will be changed to IDLE after receiving the OnBluetoothPaired event. break; default: r = E_OPERATION_FAILED; break; } __stateMutex.Release(); if (r != E_SUCCESS) { SysLogException(NID_NET_BT, r, "[%s] exception occurred on stopping Health sink role.", GetErrorMessage(r)); } SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r)); return r; } result _BluetoothHealthImpl::ConnectToSource(const BluetoothDevice& remoteDevice) { SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState()); result r = E_OPERATION_FAILED; __stateMutex.Acquire(); switch (__currentState) { case _BT_HEALTH_STATE_DISABLED: r = E_INVALID_STATE; break; case _BT_HEALTH_STATE_IDLE: r = E_INVALID_OPERATION; break; case _BT_HEALTH_STATE_ON_SERVICE: if (__pGapAdapter->IsPaired(*(remoteDevice.GetAddress())) == true) { r = __pHdpAdapter->ConnectToSource(*(remoteDevice.GetAddress()), __pAppId.get()); } else { // start the pairing process if (__pGapAdapter->Pair(*(remoteDevice.GetAddress())) == E_SUCCESS) { // copy the address of the pairing device to the local variable __pairingTargetAddress.SetArray(remoteDevice.GetAddress()->GetPointer(), 0, _BT_ADDRESS_LENGTH); __pairingTargetAddress.SetPosition(0); r = E_SUCCESS; __currentState = _BT_HEALTH_STATE_BONDING; } else { r = E_OPERATION_FAILED; } } break; case _BT_HEALTH_STATE_BONDING: case _BT_HEALTH_STATE_BOND_CANCELING: r = E_DEVICE_BUSY; break; default: r = E_OPERATION_FAILED; break; } __stateMutex.Release(); if (r != E_SUCCESS) { SysLogException(NID_NET_BT, r, "[%s] exception occurred on requesting a connection to the source device.", GetErrorMessage(r)); } SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r)); return r; } result _BluetoothHealthImpl::Disconnect(int channelId) { SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState()); result r = E_OPERATION_FAILED; __stateMutex.Acquire(); switch (__currentState) { case _BT_HEALTH_STATE_DISABLED: r = E_INVALID_STATE; break; case _BT_HEALTH_STATE_IDLE: r = E_INVALID_OPERATION; break; case _BT_HEALTH_STATE_ON_SERVICE: case _BT_HEALTH_STATE_BONDING: case _BT_HEALTH_STATE_BOND_CANCELING: if (__channelIdList.Contains(channelId) == true) { if (__pHdpAdapter->Disconnect(channelId) == E_SUCCESS) { r = E_SUCCESS; } else { r = E_OPERATION_FAILED; } } else { r = E_INVALID_OPERATION; } break; default: r = E_OPERATION_FAILED; break; } __stateMutex.Release(); if (r != E_SUCCESS) { SysLogException(NID_NET_BT, r, "[%s] exception occurred on disconnecting the connection.", GetErrorMessage(r)); } SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r)); return r; } result _BluetoothHealthImpl::SendData(int channelId, const Tizen::Base::ByteBuffer& buffer) { SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState()); result r = E_OPERATION_FAILED; __stateMutex.Acquire(); switch (__currentState) { case _BT_HEALTH_STATE_DISABLED: r = E_INVALID_STATE; break; case _BT_HEALTH_STATE_IDLE: r = E_INVALID_OPERATION; break; case _BT_HEALTH_STATE_ON_SERVICE: case _BT_HEALTH_STATE_BONDING: case _BT_HEALTH_STATE_BOND_CANCELING: if (__channelIdList.Contains(channelId) == true) { if (buffer.GetRemaining() > 0) { r = __pHdpAdapter->SendData(channelId, buffer); } else { r = E_INVALID_ARG; } } else { r = E_INVALID_OPERATION; } break; default: r = E_OPERATION_FAILED; break; } __stateMutex.Release(); if (r != E_SUCCESS) { SysLogException(NID_NET_BT, r, "[%s] exception occurred on sending data.", GetErrorMessage(r)); } SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r)); return r; } void _BluetoothHealthImpl::OnBluetoothActivated(result r) { SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState()); __stateMutex.Acquire(); if ((__currentState == _BT_HEALTH_STATE_DISABLED) && (r == E_SUCCESS)) { __currentState = _BT_HEALTH_STATE_IDLE; } __stateMutex.Release(); SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r)); } void _BluetoothHealthImpl::OnBluetoothDeactivated(result r) { SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r)); __stateMutex.Acquire(); if (r == E_SUCCESS) { __currentState = _BT_HEALTH_STATE_DISABLED; } __stateMutex.Release(); SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s]", GetStringOfCurrentState()); } void _BluetoothHealthImpl::OnBluetoothPaired(const BluetoothDevice* pPairedDevice, result r) { SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r)); bool isFired = false; result responseResult = E_SYSTEM; __stateMutex.Acquire(); if (pPairedDevice->GetAddress()->Equals(__pairingTargetAddress)) { if (__currentState == _BT_HEALTH_STATE_BONDING) { if (r == E_SUCCESS) { if (__pHdpAdapter->ConnectToSource(__pairingTargetAddress, __pAppId.get()) != E_SUCCESS) { // callback responded with E_SYSTEM isFired = true; responseResult = E_SYSTEM; } } else { // callback responded with r isFired = true; responseResult = r; } __currentState = _BT_HEALTH_STATE_ON_SERVICE; __pairingTargetAddress.Clear(); } else if (__currentState == _BT_HEALTH_STATE_BOND_CANCELING) { // callback responded with E_SYSTEM or E_OPERATION_CANCELED isFired = true; __currentState = _BT_HEALTH_STATE_IDLE; responseResult = E_SYSTEM; } // ignore other cases } // ignored otherwise __stateMutex.Release(); if (isFired) { _BluetoothHealthEventArg* pArg = new (std::nothrow) _BluetoothHealthEventArg(-1, _BT_INVALID_DATA_TYPE, BT_HEALTH_DATA_CHANNEL_NONE, pPairedDevice, E_OPERATION_FAILED); if (pArg == null) { SysLogException(NID_NET_BT, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient."); isFired = false; } else // send the connected event in case of failure of pairing { __pEvent->FireAsync(*pArg); } } SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [CONNECTED_Event:%s]", GetStringOfCurrentState(), isFired ? "Fired" : "NotFired"); } void _BluetoothHealthImpl::OnBluetoothHealthConnected(int channelId, BluetoothHealthDataChannelType channelType, const BluetoothDevice* pRemoteDevice, result r) { SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [channelId:%d], [ActionResult:%s]", GetStringOfCurrentState(), channelId, GetErrorMessage(r)); bool isFired = false; __stateMutex.Acquire(); if ((__currentState == _BT_HEALTH_STATE_ON_SERVICE) || (__currentState == _BT_HEALTH_STATE_BONDING) || (__currentState == _BT_HEALTH_STATE_BOND_CANCELING)) { if (r == E_SUCCESS) { __channelIdList.Add(channelId); } else { SysLogException(NID_NET_BT, r, "[%s] exception occurred on the response of the Health connect request.", GetErrorMessage(r)); } isFired = true; } // ignore other cases __stateMutex.Release(); if (isFired) { _BluetoothHealthEventArg* pArg = new (std::nothrow) _BluetoothHealthEventArg(channelId, __dataType, channelType, pRemoteDevice, r); if (pArg == null) { SysLogException(NID_NET_BT, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient."); isFired = false; } else { __pEvent->FireAsync(*pArg); } } SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [CONNECTED_Event:%s]", GetStringOfCurrentState(), isFired ? "Fired" : "NotFired"); } void _BluetoothHealthImpl::OnBluetoothHealthDisconnected(int channelId, result r) { SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [channelId:%d], [ActionResult:%s]", GetStringOfCurrentState(), channelId, GetErrorMessage(r)); bool isFired = false; __stateMutex.Acquire(); if ((__currentState == _BT_HEALTH_STATE_ON_SERVICE) || (__currentState == _BT_HEALTH_STATE_BONDING) || (__currentState == _BT_HEALTH_STATE_BOND_CANCELING)) { if (r == E_SUCCESS) { if (__channelIdList.Contains(channelId) == true) { __channelIdList.Remove(channelId); isFired = true; } else { SysLog(NID_NET_BT, "channelId(%d) is NOT exist.", channelId); } } else { SysLogException(NID_NET_BT, r, "[%s] exception occurred on the response of the Health disconnect request.", GetErrorMessage(r)); } } // ignore other cases __stateMutex.Release(); if (isFired) { _BluetoothHealthEventArg* pArg = new (std::nothrow) _BluetoothHealthEventArg(channelId, r); if (pArg == null) { SysLogException(NID_NET_BT, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient."); isFired = false; } else { __pEvent->FireAsync(*pArg); } } SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [DISCONNECTED_Event:%s]", GetStringOfCurrentState(), isFired ? "Fired" : "NotFired"); } void _BluetoothHealthImpl::OnBluetoothHealthDataReceived(int channelId, Tizen::Base::ByteBuffer& buffer) { SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState()); bool isFired = false; __stateMutex.Acquire(); if ((__currentState == _BT_HEALTH_STATE_ON_SERVICE) || (__currentState == _BT_HEALTH_STATE_BONDING) || (__currentState == _BT_HEALTH_STATE_BOND_CANCELING)) { if (__channelIdList.Contains(channelId) == true) { isFired = true; } else { SysLog(NID_NET_BT, "channelId(%d) is NOT exist.", channelId); } } // ignore other cases __stateMutex.Release(); if (isFired) { _BluetoothHealthEventArg* pArg = new (std::nothrow) _BluetoothHealthEventArg(channelId, buffer); if (pArg == null) { SysLogException(NID_NET_BT, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient."); isFired = false; } else { // use Fire() instead of FireAsync() to improve the transfer rate. __pEvent->Fire(*pArg); } } SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [DATA_RECIEVED_Event:%s]", GetStringOfCurrentState(), isFired ? "Fired" : "NotFired"); } const char* _BluetoothHealthImpl::GetStringOfCurrentState(void) const { const char* pStateString = null; switch (__currentState) { case _BT_HEALTH_STATE_DISABLED: pStateString = "DISABLED"; break; case _BT_HEALTH_STATE_IDLE: pStateString = "IDLE"; break; case _BT_HEALTH_STATE_ON_SERVICE: pStateString = "ON_SERVICE"; break; case _BT_HEALTH_STATE_BONDING: pStateString = "BONDING"; break; case _BT_HEALTH_STATE_BOND_CANCELING: pStateString = "BOND_CANCELING"; break; default: pStateString = "Unknown"; break; } return pStateString; } } } } // Tizen::Net::Bluetooth