author | Matt Brubeck <mbrubeck@mozilla.com> |
Thu, 04 Apr 2013 17:45:06 -0700 | |
changeset 127734 | 03a6b2be2d610ff22b75194d0abe335507b716f2 |
parent 127733 | ca34eba9c8b630ede0c9eb62fa7717c3df7c06a8 |
child 127735 | 2418deea4b19e48fb1f5f5ef5402563c3d428501 |
push id | 24512 |
push user | ryanvm@gmail.com |
push date | Fri, 05 Apr 2013 20:13:49 +0000 |
treeherder | mozilla-central@139b6ba547fa [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 851046 |
milestone | 23.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/bluetooth/BluetoothCommon.h +++ b/dom/bluetooth/BluetoothCommon.h @@ -48,17 +48,16 @@ extern bool gBluetoothDebugFlag; #define KEY_LOCAL_AGENT "/B2G/bluetooth/agent" #define KEY_REMOTE_AGENT "/B2G/bluetooth/remote_device_agent" #define KEY_MANAGER "/B2G/bluetooth/manager" #define KEY_ADAPTER "/B2G/bluetooth/adapter" // Bluetooth address format: xx:xx:xx:xx:xx:xx (or xx_xx_xx_xx_xx_xx) #define BLUETOOTH_ADDRESS_LENGTH 17 -#define BLUETOOTH_ADDRESS_NONE "00:00:00:00:00:00" BEGIN_BLUETOOTH_NAMESPACE enum BluetoothSocketType { RFCOMM = 1, SCO = 2, L2CAP = 3 };
--- a/dom/bluetooth/BluetoothHfpManager.cpp +++ b/dom/bluetooth/BluetoothHfpManager.cpp @@ -6,17 +6,16 @@ #include "base/basictypes.h" #include "BluetoothHfpManager.h" #include "BluetoothReplyRunnable.h" #include "BluetoothScoManager.h" #include "BluetoothService.h" -#include "BluetoothSocket.h" #include "BluetoothUtils.h" #include "BluetoothUuid.h" #include "MobileConnection.h" #include "mozilla/dom/bluetooth/BluetoothTypes.h" #include "mozilla/Hal.h" #include "mozilla/Services.h" #include "mozilla/StaticPtr.h" @@ -35,29 +34,27 @@ /** * These constants are used in result code such as +CLIP and +CCWA. The value * of these constants is the same as TOA_INTERNATIONAL/TOA_UNKNOWN defined in * ril_consts.js */ #define TOA_UNKNOWN 0x81 #define TOA_INTERNATIONAL 0x91 -#define CR_LF "\xd\xa"; - using namespace mozilla; using namespace mozilla::ipc; USING_BLUETOOTH_NAMESPACE namespace { - StaticAutoPtr<BluetoothHfpManager> gBluetoothHfpManager; + StaticRefPtr<BluetoothHfpManager> gBluetoothHfpManager; StaticRefPtr<BluetoothHfpManagerObserver> sHfpObserver; bool gInShutdown = false; static bool sStopSendingRingFlag = true; + static int sRingInterval = 3000; //unit: ms - static const char kHfpCrlf[] = "\xd\xa"; } // anonymous namespace /* CallState for sCINDItems[CINDType::CALL].value * - NO_CALL: there are no calls in progress * - IN_PROGRESS: at least one call is in progress */ enum CallState { NO_CALL, @@ -258,17 +255,17 @@ BluetoothHfpManagerObserver::Observe(nsI } MOZ_ASSERT(false, "BluetoothHfpManager got unexpected topic!"); return NS_ERROR_UNEXPECTED; } NS_IMPL_ISUPPORTS1(BluetoothHfpManagerObserver, nsIObserver) -class BluetoothHfpManager::SendRingIndicatorTask : public Task +class SendRingIndicatorTask : public Task { public: SendRingIndicatorTask(const nsAString& aNumber, int aType) : mNumber(aNumber) , mType(aType) { MOZ_ASSERT(NS_IsMainThread()); } @@ -282,29 +279,30 @@ public: return; } if (!gBluetoothHfpManager) { NS_WARNING("BluetoothHfpManager no longer exists, cannot send ring!"); return; } + const char* kHfpCrlf = "\xd\xa"; nsAutoCString ringMsg(kHfpCrlf); - ringMsg.AppendLiteral("RING"); - ringMsg.AppendLiteral(kHfpCrlf); - gBluetoothHfpManager->SendLine(ringMsg.get()); + ringMsg += "RING"; + ringMsg += kHfpCrlf; + gBluetoothHfpManager->SendSocketData(ringMsg); if (!mNumber.IsEmpty()) { nsAutoCString clipMsg(kHfpCrlf); - clipMsg.AppendLiteral("+CLIP: \""); - clipMsg.Append(NS_ConvertUTF16toUTF8(mNumber).get()); - clipMsg.AppendLiteral("\","); + clipMsg += "+CLIP: \""; + clipMsg += NS_ConvertUTF16toUTF8(mNumber).get(); + clipMsg += "\","; clipMsg.AppendInt(mType); - clipMsg.AppendLiteral(kHfpCrlf); - gBluetoothHfpManager->SendLine(clipMsg.get()); + clipMsg += kHfpCrlf; + gBluetoothHfpManager->SendSocketData(clipMsg); } MessageLoop::current()-> PostDelayedTask(FROM_HERE, new SendRingIndicatorTask(mNumber, mType), sRingInterval); } @@ -388,21 +386,17 @@ BluetoothHfpManager::Reset() ResetCallArray(); } bool BluetoothHfpManager::Init() { MOZ_ASSERT(NS_IsMainThread()); - mSocket = new BluetoothSocket(this, - BluetoothSocketType::RFCOMM, - true, - true); - mPrevSocketStatus = mSocket->GetConnectionStatus(); + mSocketStatus = GetConnectionStatus(); sHfpObserver = new BluetoothHfpManagerObserver(); if (!sHfpObserver->Init()) { NS_WARNING("Cannot set up Hfp Observers!"); } mListener = new BluetoothTelephonyListener(); if (!mListener->StartListening()) { @@ -455,34 +449,38 @@ BluetoothHfpManager::Get() // If we're in shutdown, don't create a new instance if (gInShutdown) { NS_WARNING("BluetoothHfpManager can't be created during shutdown"); return nullptr; } // Create new instance, register, return - BluetoothHfpManager* manager = new BluetoothHfpManager(); - NS_ENSURE_TRUE(manager->Init(), nullptr); + nsRefPtr<BluetoothHfpManager> manager = new BluetoothHfpManager(); + NS_ENSURE_TRUE(manager, nullptr); + + if (!manager->Init()) { + return nullptr; + } gBluetoothHfpManager = manager; return gBluetoothHfpManager; } void BluetoothHfpManager::NotifySettings() { nsString type, name; BluetoothValue v; InfallibleTArray<BluetoothNamedValue> parameters; type.AssignLiteral("bluetooth-hfp-status-changed"); name.AssignLiteral("connected"); - v = (mSocket->GetConnectionStatus() == - SocketConnectionStatus::SOCKET_CONNECTED); + v = (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED) + ? true : false ; parameters.AppendElement(BluetoothNamedValue(name, v)); name.AssignLiteral("address"); v = mDevicePath; parameters.AppendElement(BluetoothNamedValue(name, v)); if (!BroadcastSystemMessage(type, parameters)) { NS_WARNING("Failed to broadcast system message to settings"); @@ -568,17 +566,17 @@ BluetoothHfpManager::HandleVolumeChanged // Adjust volume by headset and we don't have to send volume back to headset if (mReceiveVgsFlag) { mReceiveVgsFlag = false; return NS_OK; } // Only send volume back when there's a connected headset - if (mSocket->GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED) { + if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED) { SendCommand("+VGS: ", mCurrentVgs); } return NS_OK; } nsresult BluetoothHfpManager::HandleVoiceConnectionChanged() @@ -660,25 +658,24 @@ BluetoothHfpManager::HandleIccInfoChange return NS_OK; } nsresult BluetoothHfpManager::HandleShutdown() { MOZ_ASSERT(NS_IsMainThread()); gInShutdown = true; - Disconnect(); + CloseSocket(); gBluetoothHfpManager = nullptr; return NS_OK; } // Virtual function of class SocketConsumer void -BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket, - nsAutoPtr<UnixSocketRawData>& aMessage) +BluetoothHfpManager::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage) { MOZ_ASSERT(NS_IsMainThread()); nsAutoCString msg((const char*)aMessage->mData.get(), aMessage->mSize); msg.StripWhitespace(); nsTArray<nsCString> atCommandValues; @@ -740,19 +737,19 @@ BluetoothHfpManager::ReceiveSocketData(B } else { SendLine("ERROR"); } return; } } else if (msg.Find("AT+COPS?") != -1) { nsAutoCString message("+COPS: "); message.AppendInt(mNetworkSelectionMode); - message.AppendLiteral(",0,\""); - message.Append(NS_ConvertUTF16toUTF8(mOperatorName)); - message.AppendLiteral("\""); + message += ",0,\""; + message += NS_ConvertUTF16toUTF8(mOperatorName); + message += "\""; SendLine(message.get()); return; } else if (msg.Find("AT+VTS=") != -1) { ParseAtCommand(msg, 7, atCommandValues); if (atCommandValues.Length() != 1) { NS_WARNING("Couldn't get the value of command [AT+VTS=]"); goto respond_with_ok; @@ -906,20 +903,20 @@ BluetoothHfpManager::ReceiveSocketData(B break; default: NS_WARNING("Not handling state changed"); break; } } else if (msg.Find("AT+CNUM") != -1) { if (!mMsisdn.IsEmpty()) { nsAutoCString message("+CNUM: ,\""); - message.Append(NS_ConvertUTF16toUTF8(mMsisdn).get()); - message.AppendLiteral("\","); + message += NS_ConvertUTF16toUTF8(mMsisdn).get(); + message += "\","; message.AppendInt(TOA_UNKNOWN); - message.AppendLiteral(",,4"); + message += ",,4"; SendLine(message.get()); } } else { nsCString warningMsg; warningMsg.Append(NS_LITERAL_CSTRING("Unsupported AT command: ")); warningMsg.Append(msg); warningMsg.Append(NS_LITERAL_CSTRING(", reply with ERROR")); NS_WARNING(warningMsg.get()); @@ -940,25 +937,23 @@ BluetoothHfpManager::Connect(const nsASt { MOZ_ASSERT(NS_IsMainThread()); if (gInShutdown) { NS_WARNING("Connect called while in shutdown!"); return false; } - SocketConnectionStatus s = mSocket->GetConnectionStatus(); - - if (s == SocketConnectionStatus::SOCKET_CONNECTED || - s == SocketConnectionStatus::SOCKET_CONNECTING) { - NS_WARNING("BluetoothHfpManager has been already connected"); + if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED || + GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTING) { + NS_WARNING("BluetoothHfpManager has connected/is connecting to a headset!"); return false; } - mSocket->Disconnect(); + CloseSocket(); BluetoothService* bs = BluetoothService::Get(); NS_ENSURE_TRUE(bs, false); nsString uuid; if (aIsHandsfree) { BluetoothUuidHelper::GetString(BluetoothServiceClass::HANDSFREE, uuid); } else { @@ -967,71 +962,82 @@ BluetoothHfpManager::Connect(const nsASt mRunnable = aRunnable; nsresult rv = bs->GetSocketViaService(aDevicePath, uuid, BluetoothSocketType::RFCOMM, true, true, - mSocket, + this, mRunnable); return NS_FAILED(rv) ? false : true; } bool BluetoothHfpManager::Listen() { MOZ_ASSERT(NS_IsMainThread()); if (gInShutdown) { MOZ_ASSERT(false, "Listen called while in shutdown!"); return false; } - if (mSocket->GetConnectionStatus() == - SocketConnectionStatus::SOCKET_LISTENING) { + if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_LISTENING) { NS_WARNING("BluetoothHfpManager has been already listening"); return true; } - mSocket->Disconnect(); + CloseSocket(); + + BluetoothService* bs = BluetoothService::Get(); + NS_ENSURE_TRUE(bs, false); - if (!mSocket->Listen(BluetoothReservedChannels::CHANNEL_HANDSFREE_AG)) { - NS_WARNING("[HFP] Can't listen on socket!"); - return false; - } + nsresult rv = + bs->ListenSocketViaService(BluetoothReservedChannels::CHANNEL_HANDSFREE_AG, + BluetoothSocketType::RFCOMM, + true, + true, + this); - mPrevSocketStatus = mSocket->GetConnectionStatus(); - return true; + mSocketStatus = GetConnectionStatus(); + + return NS_FAILED(rv) ? false : true; } void BluetoothHfpManager::Disconnect() { - mSocket->Disconnect(); + if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_DISCONNECTED) { + NS_WARNING("BluetoothHfpManager has been disconnected!"); + return; + } + + CloseSocket(); } bool BluetoothHfpManager::SendLine(const char* aMessage) { + const char* kHfpCrlf = "\xd\xa"; nsAutoCString msg; - msg.AppendLiteral(kHfpCrlf); - msg.Append(aMessage); - msg.AppendLiteral(kHfpCrlf); + msg += kHfpCrlf; + msg += aMessage; + msg += kHfpCrlf; - return mSocket->SendSocketData(msg); + return SendSocketData(msg); } bool BluetoothHfpManager::SendCommand(const char* aCommand, uint8_t aValue) { - if (mPrevSocketStatus != SocketConnectionStatus::SOCKET_CONNECTED) { + if (mSocketStatus != SocketConnectionStatus::SOCKET_CONNECTED) { return false; } nsAutoCString message; int value = aValue; message += aCommand; if (!strcmp(aCommand, "+CIEV: ")) { @@ -1041,57 +1047,57 @@ BluetoothHfpManager::SendCommand(const c } if ((aValue < 1) || (aValue > ArrayLength(sCINDItems) - 1)) { NS_WARNING("unexpected CINDType for CIEV command"); return false; } message.AppendInt(aValue); - message.AppendLiteral(","); + message += ","; message.AppendInt(sCINDItems[aValue].value); } else if (!strcmp(aCommand, "+CIND: ")) { if (!aValue) { // Query for range for (uint8_t i = 1; i < ArrayLength(sCINDItems); i++) { - message.AppendLiteral("(\""); - message.Append(sCINDItems[i].name); - message.AppendLiteral("\",("); - message.Append(sCINDItems[i].range); - message.AppendLiteral(")"); + message += "(\""; + message += sCINDItems[i].name; + message += "\",("; + message += sCINDItems[i].range; + message += ")"; if (i == (ArrayLength(sCINDItems) - 1)) { - message.AppendLiteral(")"); + message +=")"; break; } - message.AppendLiteral("),"); + message += "),"; } } else { // Query for value for (uint8_t i = 1; i < ArrayLength(sCINDItems); i++) { message.AppendInt(sCINDItems[i].value); if (i == (ArrayLength(sCINDItems) - 1)) { break; } - message.AppendLiteral(","); + message += ","; } } } else if (!strcmp(aCommand, "+CLCC: ")) { bool rv = true; uint32_t callNumbers = mCurrentCallArray.Length(); for (uint32_t i = 1; i < callNumbers; i++) { Call& call = mCurrentCallArray[i]; if (call.mState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) { continue; } message.AssignLiteral("+CLCC: "); message.AppendInt(i); - message.AppendLiteral(","); + message += ","; message.AppendInt(call.mDirection); - message.AppendLiteral(","); + message += ","; switch (call.mState) { case nsITelephonyProvider::CALL_STATE_CONNECTED: message.AppendInt(0); break; case nsITelephonyProvider::CALL_STATE_HELD: message.AppendInt(1); break; @@ -1103,19 +1109,19 @@ BluetoothHfpManager::SendCommand(const c break; case nsITelephonyProvider::CALL_STATE_INCOMING: message.AppendInt((i == mCurrentCallIndex) ? 4 : 5); break; default: NS_WARNING("Not handling call status for CLCC"); break; } - message.AppendLiteral(",0,0,\""); - message.Append(NS_ConvertUTF16toUTF8(call.mNumber)); - message.AppendLiteral("\","); + message += ",0,0,\""; + message += NS_ConvertUTF16toUTF8(call.mNumber).get(); + message += "\","; message.AppendInt(call.mType); rv &= SendLine(message.get()); } return rv; } else { message.AppendInt(value); } @@ -1136,18 +1142,17 @@ BluetoothHfpManager::UpdateCIND(uint8_t } void BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex, uint16_t aCallState, const nsAString& aNumber, bool aSend) { - if (mSocket->GetConnectionStatus() != - SocketConnectionStatus::SOCKET_CONNECTED) { + if (GetConnectionStatus() != SocketConnectionStatus::SOCKET_CONNECTED) { return; } while (aCallIndex >= mCurrentCallArray.Length()) { Call call; mCurrentCallArray.AppendElement(call); } @@ -1171,18 +1176,18 @@ BluetoothHfpManager::HandleCallStateChan SendCommand("+CIEV: ", CINDType::CALLHELD); break; case nsITelephonyProvider::CALL_STATE_INCOMING: mCurrentCallArray[aCallIndex].mDirection = true; if (mCurrentCallIndex) { if (mCCWA) { nsAutoCString ccwaMsg("+CCWA: \""); - ccwaMsg.Append(NS_ConvertUTF16toUTF8(aNumber)); - ccwaMsg.AppendLiteral("\","); + ccwaMsg += NS_ConvertUTF16toUTF8(aNumber).get(); + ccwaMsg += "\","; ccwaMsg.AppendInt(mCurrentCallArray[aCallIndex].mType); SendLine(ccwaMsg.get()); } UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, aSend); } else { // Start sending RING indicator to HF sStopSendingRingFlag = false; UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, aSend); @@ -1196,37 +1201,37 @@ BluetoothHfpManager::HandleCallStateChan new SendRingIndicatorTask(number, mCurrentCallArray[aCallIndex].mType), sRingInterval); } break; case nsITelephonyProvider::CALL_STATE_DIALING: mCurrentCallArray[aCallIndex].mDirection = false; UpdateCIND(CINDType::CALLSETUP, CallSetupState::OUTGOING, aSend); - mSocket->GetAddress(address); + GetSocketAddr(address); OpenScoSocket(address); break; case nsITelephonyProvider::CALL_STATE_ALERTING: mCurrentCallArray[aCallIndex].mDirection = false; UpdateCIND(CINDType::CALLSETUP, CallSetupState::OUTGOING_ALERTING, aSend); // If there's an ongoing call when the headset is just connected, we have // to open a sco socket here. - mSocket->GetAddress(address); + GetSocketAddr(address); OpenScoSocket(address); break; case nsITelephonyProvider::CALL_STATE_CONNECTED: mCurrentCallIndex = aCallIndex; switch (prevCallState) { case nsITelephonyProvider::CALL_STATE_INCOMING: case nsITelephonyProvider::CALL_STATE_DISCONNECTED: // Incoming call, no break sStopSendingRingFlag = true; - mSocket->GetAddress(address); + GetSocketAddr(address); OpenScoSocket(address); case nsITelephonyProvider::CALL_STATE_ALERTING: // Outgoing call UpdateCIND(CINDType::CALL, CallState::IN_PROGRESS, aSend); UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, aSend); break; case nsITelephonyProvider::CALL_STATE_HELD: // Check whether to update CINDType::CALLHELD or not @@ -1300,77 +1305,66 @@ BluetoothHfpManager::HandleCallStateChan NS_WARNING("Not handling state changed"); sCINDItems[CINDType::CALL].value = CallState::NO_CALL; sCINDItems[CINDType::CALLSETUP].value = CallSetupState::NO_CALLSETUP; sCINDItems[CINDType::CALLHELD].value = CallHeldState::NO_CALLHELD; } } void -BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket) +BluetoothHfpManager::OnConnectSuccess() { - MOZ_ASSERT(aSocket == mSocket); - nsCOMPtr<nsITelephonyProvider> provider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID); NS_ENSURE_TRUE_VOID(provider); provider->EnumerateCalls(mListener->GetListener()); // For active connection request, we need to reply the DOMRequest if (mRunnable) { BluetoothValue v = true; nsString errorStr; DispatchBluetoothReply(mRunnable, v, errorStr); mRunnable.forget(); } // Cache device path for NotifySettings() since we can't get socket address // when a headset disconnect with us - mSocket->GetAddress(mDevicePath); - mPrevSocketStatus = mSocket->GetConnectionStatus(); + GetSocketAddr(mDevicePath); + mSocketStatus = GetConnectionStatus(); NotifySettings(); } void -BluetoothHfpManager::OnConnectError(BluetoothSocket* aSocket) +BluetoothHfpManager::OnConnectError() { - MOZ_ASSERT(aSocket == mSocket); - // For active connection request, we need to reply the DOMRequest if (mRunnable) { BluetoothValue v; nsString errorStr; errorStr.AssignLiteral("Failed to connect with a bluetooth headset!"); DispatchBluetoothReply(mRunnable, v, errorStr); mRunnable.forget(); } // If connecting for some reason didn't work, restart listening + CloseSocket(); + mSocketStatus = GetConnectionStatus(); Listen(); } void -BluetoothHfpManager::OnDisconnect(BluetoothSocket* aSocket) +BluetoothHfpManager::OnDisconnect() { - MOZ_ASSERT(aSocket == mSocket); - // When we close a connected socket, then restart listening again and // notify Settings app. - if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) { + if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) { Listen(); NotifySettings(); - } else if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTING) { + } else if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTING) { NS_WARNING("BluetoothHfpManager got unexpected socket status!"); } CloseScoSocket(); Reset(); } - -bool -BluetoothHfpManager::IsConnected() -{ - return mSocket->GetConnectionStatus() == - SocketConnectionStatus::SOCKET_CONNECTED; -}
--- a/dom/bluetooth/BluetoothHfpManager.h +++ b/dom/bluetooth/BluetoothHfpManager.h @@ -3,26 +3,24 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_bluetooth_bluetoothhfpmanager_h__ #define mozilla_dom_bluetooth_bluetoothhfpmanager_h__ #include "BluetoothCommon.h" -#include "BluetoothSocketObserver.h" #include "BluetoothTelephonyListener.h" #include "mozilla/ipc/UnixSocket.h" #include "nsIObserver.h" BEGIN_BLUETOOTH_NAMESPACE +class BluetoothReplyRunnable; class BluetoothHfpManagerObserver; -class BluetoothReplyRunnable; -class BluetoothSocket; class Call; /** * These costants are defined in 4.33.2 "AT Capabilities Re-Used from GSM 07.07 * and 3GPP 27.007" in Bluetooth hands-free profile 1.6 */ enum BluetoothCmeError { AG_FAILURE = 0, @@ -45,51 +43,42 @@ enum BluetoothCmeError { INVALID_CHARACTERS_IN_TEXT_STRING = 25, DIAL_STRING_TOO_LONG = 26, INVALID_CHARACTERS_IN_DIAL_STRING = 27, NO_NETWORK_SERVICE = 30, NETWORK_TIMEOUT = 31, NETWORK_NOT_ALLOWED = 32 }; -class BluetoothHfpManager : public BluetoothSocketObserver +class BluetoothHfpManager : public mozilla::ipc::UnixSocketConsumer { public: static BluetoothHfpManager* Get(); - ~BluetoothHfpManager(); - - virtual void ReceiveSocketData( - BluetoothSocket* aSocket, - nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE; - virtual void OnConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE; - virtual void OnConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE; - virtual void OnDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE; + virtual void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) + MOZ_OVERRIDE; bool Connect(const nsAString& aDeviceObjectPath, const bool aIsHandsfree, BluetoothReplyRunnable* aRunnable); void Disconnect(); bool Listen(); /** * @param aSend A boolean indicates whether we need to notify headset or not */ void HandleCallStateChanged(uint32_t aCallIndex, uint16_t aCallState, const nsAString& aNumber, bool aSend); - bool IsConnected(); private: class GetVolumeTask; - class SendRingIndicatorTask; - friend class GetVolumeTask; - friend class SendRingIndicatorTask; friend class BluetoothHfpManagerObserver; BluetoothHfpManager(); + ~BluetoothHfpManager(); nsresult HandleIccInfoChanged(); nsresult HandleShutdown(); nsresult HandleVolumeChanged(const nsAString& aData); nsresult HandleVoiceConnectionChanged(); bool Init(); void Cleanup(); void Reset(); @@ -97,31 +86,34 @@ private: void NotifyDialer(const nsAString& aCommand); void NotifySettings(); bool SendCommand(const char* aCommand, uint8_t aValue = 0); bool SendLine(const char* aMessage); void UpdateCIND(uint8_t aType, uint8_t aValue, bool aSend); + virtual void OnConnectSuccess() MOZ_OVERRIDE; + virtual void OnConnectError() MOZ_OVERRIDE; + virtual void OnDisconnect() MOZ_OVERRIDE; + int mCurrentVgs; int mCurrentVgm; uint32_t mCurrentCallIndex; bool mCCWA; bool mCLIP; bool mCMEE; bool mCMER; int mNetworkSelectionMode; bool mReceiveVgsFlag; nsString mDevicePath; nsString mMsisdn; nsString mOperatorName; - SocketConnectionStatus mPrevSocketStatus; + enum mozilla::ipc::SocketConnectionStatus mSocketStatus; nsTArray<Call> mCurrentCallArray; nsAutoPtr<BluetoothTelephonyListener> mListener; nsRefPtr<BluetoothReplyRunnable> mRunnable; - nsRefPtr<BluetoothSocket> mSocket; }; END_BLUETOOTH_NAMESPACE #endif
--- a/dom/bluetooth/BluetoothOppManager.cpp +++ b/dom/bluetooth/BluetoothOppManager.cpp @@ -4,17 +4,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "base/basictypes.h" #include "BluetoothOppManager.h" #include "BluetoothReplyRunnable.h" #include "BluetoothService.h" -#include "BluetoothSocket.h" #include "BluetoothUtils.h" #include "BluetoothUuid.h" #include "ObexBase.h" #include "mozilla/dom/bluetooth/BluetoothTypes.h" #include "mozilla/RefPtr.h" #include "mozilla/Services.h" #include "mozilla/StaticPtr.h" @@ -80,17 +79,17 @@ namespace { static const uint32_t kUpdateProgressBase = 50 * 1024; /* * The format of the header of an PUT request is * [opcode:1][packet length:2][headerId:1][header length:2] */ static const uint32_t kPutRequestHeaderSize = 6; -StaticAutoPtr<BluetoothOppManager> sInstance; +StaticRefPtr<BluetoothOppManager> sInstance; StaticRefPtr<BluetoothOppManagerObserver> sOppObserver; /* * FIXME / Bug 806749 * * Currently Bluetooth*Manager inherits mozilla::ipc::UnixSocketConsumer, * which means that each Bluetooth*Manager can handle only one socket * connection at a time. We need to support concurrent multiple socket @@ -190,33 +189,28 @@ public: private: nsCOMPtr<nsIInputStream> mInputStream; uint32_t mAvailablePacketSize; }; class CloseSocketTask : public Task { public: - CloseSocketTask(BluetoothSocket* aSocket) : mSocket(aSocket) - { - MOZ_ASSERT(aSocket); - } - void Run() MOZ_OVERRIDE { - MOZ_ASSERT(NS_IsMainThread()); + if (!sInstance) { + NS_WARNING("BluetoothOppManager no longer exists, cannot close socket!"); + return; + } - if (mSocket->GetConnectionStatus() == - SocketConnectionStatus::SOCKET_CONNECTED) { - mSocket->Disconnect(); + if (sInstance->GetConnectionStatus() == + SocketConnectionStatus::SOCKET_CONNECTED) { + sInstance->CloseSocket(); } } - -private: - nsRefPtr<BluetoothSocket> mSocket; }; BluetoothOppManager::BluetoothOppManager() : mConnected(false) , mRemoteObexVersion(0) , mRemoteConnectionFlags(0) , mRemoteMaxPacketLength(0) , mLastCommand(0) , mPacketLeftLength(0) @@ -224,57 +218,50 @@ BluetoothOppManager::BluetoothOppManager , mReceivedDataBufferOffset(0) , mAbortFlag(false) , mNewFileFlag(false) , mPutFinalFlag(false) , mSendTransferCompleteFlag(false) , mSuccessFlag(false) , mWaitingForConfirmationFlag(false) { - mConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE); - - mSocket = new BluetoothSocket(this, - BluetoothSocketType::RFCOMM, - true, - true); - mPrevSocketStatus = mSocket->GetConnectionStatus(); + mConnectedDeviceAddress.AssignLiteral("00:00:00:00:00:00"); + mSocketStatus = GetConnectionStatus(); } BluetoothOppManager::~BluetoothOppManager() { } //static BluetoothOppManager* BluetoothOppManager::Get() { MOZ_ASSERT(NS_IsMainThread()); - if (!sInstance) { + if (sInstance == nullptr) { sInstance = new BluetoothOppManager(); } return sInstance; } bool BluetoothOppManager::Connect(const nsAString& aDeviceObjectPath, BluetoothReplyRunnable* aRunnable) { MOZ_ASSERT(NS_IsMainThread()); - SocketConnectionStatus s = mSocket->GetConnectionStatus(); - - if (s == SocketConnectionStatus::SOCKET_CONNECTED || - s == SocketConnectionStatus::SOCKET_CONNECTING) { + if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED || + GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTING) { NS_WARNING("BluetoothOppManager has been already connected"); return false; } - Disconnect(); + CloseSocket(); BluetoothService* bs = BluetoothService::Get(); if (!bs) { NS_WARNING("BluetoothService not available!"); return false; } nsString uuid; @@ -282,58 +269,70 @@ BluetoothOppManager::Connect(const nsASt mRunnable = aRunnable; nsresult rv = bs->GetSocketViaService(aDeviceObjectPath, uuid, BluetoothSocketType::RFCOMM, true, true, - mSocket, + this, mRunnable); return NS_FAILED(rv) ? false : true; } void BluetoothOppManager::Disconnect() { - mSocket->Disconnect(); + if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_DISCONNECTED) { + NS_WARNING("BluetoothOppManager has been disconnected!"); + return; + } + + CloseSocket(); } nsresult BluetoothOppManager::HandleShutdown() { MOZ_ASSERT(NS_IsMainThread()); sInShutdown = true; - Disconnect(); + CloseSocket(); sInstance = nullptr; return NS_OK; } bool BluetoothOppManager::Listen() { MOZ_ASSERT(NS_IsMainThread()); - if (mSocket->GetConnectionStatus() == - SocketConnectionStatus::SOCKET_LISTENING) { + if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_LISTENING) { NS_WARNING("BluetoothOppManager has been already listening"); return true; } - Disconnect(); + CloseSocket(); - if (!mSocket->Listen(BluetoothReservedChannels::CHANNEL_OPUSH)) { - NS_WARNING("[OPP] Can't listen on socket!"); + BluetoothService* bs = BluetoothService::Get(); + if (!bs) { + NS_WARNING("BluetoothService not available!"); return false; } - mPrevSocketStatus = mSocket->GetConnectionStatus(); - return true; + nsresult rv = + bs->ListenSocketViaService(BluetoothReservedChannels::CHANNEL_OPUSH, + BluetoothSocketType::RFCOMM, + true, + true, + this); + mSocketStatus = GetConnectionStatus(); + + return NS_FAILED(rv) ? false : true; } bool BluetoothOppManager::SendFile(BlobParent* aActor) { if (mBlob) { // Means there's a sending process. Reply error. return false; @@ -687,18 +686,17 @@ BluetoothOppManager::ServerDataHandler(U packetLength = mPacketLeftLength; } else { opCode = aMessage->mData[0]; packetLength = (((int)aMessage->mData[1]) << 8) | aMessage->mData[2]; // When there's a Put packet right after a PutFinal packet, // which means it's the start point of a new file. if (mPutFinalFlag && - (opCode == ObexRequestCode::Put || - opCode == ObexRequestCode::PutFinal)) { + (opCode == ObexRequestCode::Put || opCode == ObexRequestCode::PutFinal)) { mNewFileFlag = true; AfterFirstPut(); } } ObexHeaderSet pktHeaders(opCode); if (opCode == ObexRequestCode::Connect) { // Section 3.3.1 "Connect", IrOBEX 1.2 @@ -861,17 +859,17 @@ BluetoothOppManager::ClientDataHandler(U SendDisconnectRequest(); FileTransferComplete(); } else if (mLastCommand == ObexRequestCode::Disconnect) { AfterOppDisconnected(); // Most devices will directly terminate connection after receiving // Disconnect request, so we make a delay here. If the socket hasn't been // disconnected, we will close it. MessageLoop::current()-> - PostDelayedTask(FROM_HERE, new CloseSocketTask(mSocket), 1000); + PostDelayedTask(FROM_HERE, new CloseSocketTask(), 1000); } else if (mLastCommand == ObexRequestCode::Connect) { MOZ_ASSERT(!sFileName.IsEmpty()); MOZ_ASSERT(mBlob); AfterOppConnected(); // Keep remote information mRemoteObexVersion = aMessage->mData[3]; @@ -923,18 +921,17 @@ BluetoothOppManager::ClientDataHandler(U } } else { NS_WARNING("Unhandled ObexRequestCode"); } } // Virtual function of class SocketConsumer void -BluetoothOppManager::ReceiveSocketData(BluetoothSocket* aSocket, - nsAutoPtr<UnixSocketRawData>& aMessage) +BluetoothOppManager::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage) { if (mLastCommand) { ClientDataHandler(aMessage); return; } ServerDataHandler(aMessage); } @@ -955,17 +952,17 @@ BluetoothOppManager::SendConnectRequest( req[5] = BluetoothOppManager::MAX_PACKET_LENGTH >> 8; req[6] = (uint8_t)BluetoothOppManager::MAX_PACKET_LENGTH; SetObexPacketInfo(req, ObexRequestCode::Connect, index); mLastCommand = ObexRequestCode::Connect; UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); - mSocket->SendSocketData(s); + SendSocketData(s); } void BluetoothOppManager::SendPutHeaderRequest(const nsAString& aFileName, int aFileSize) { uint8_t* req = new uint8_t[mRemoteMaxPacketLength]; @@ -985,17 +982,17 @@ BluetoothOppManager::SendPutHeaderReques index += AppendHeaderName(&req[index], (char*)fileName, (len + 1) * 2); index += AppendHeaderLength(&req[index], aFileSize); SetObexPacketInfo(req, ObexRequestCode::Put, index); mLastCommand = ObexRequestCode::Put; UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); - mSocket->SendSocketData(s); + SendSocketData(s); delete [] fileName; delete [] req; } void BluetoothOppManager::SendPutRequest(uint8_t* aFileBody, int aFileBodyLength) @@ -1015,17 +1012,17 @@ BluetoothOppManager::SendPutRequest(uint int index = 3; index += AppendHeaderBody(&req[index], aFileBody, aFileBodyLength); SetObexPacketInfo(req, ObexRequestCode::Put, index); mLastCommand = ObexRequestCode::Put; UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); - mSocket->SendSocketData(s); + SendSocketData(s); delete [] req; } void BluetoothOppManager::SendPutFinalRequest() { if (!mConnected) return; @@ -1041,17 +1038,17 @@ BluetoothOppManager::SendPutFinalRequest int index = 3; uint8_t* req = new uint8_t[mRemoteMaxPacketLength]; index += AppendHeaderEndOfBody(&req[index]); SetObexPacketInfo(req, ObexRequestCode::PutFinal, index); mLastCommand = ObexRequestCode::PutFinal; UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); - mSocket->SendSocketData(s); + SendSocketData(s); sWaitingToSendPutFinal = false; delete [] req; } void BluetoothOppManager::SendDisconnectRequest() @@ -1061,33 +1058,33 @@ BluetoothOppManager::SendDisconnectReque uint8_t req[255]; int index = 3; SetObexPacketInfo(req, ObexRequestCode::Disconnect, index); mLastCommand = ObexRequestCode::Disconnect; UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); - mSocket->SendSocketData(s); + SendSocketData(s); } void BluetoothOppManager::SendAbortRequest() { // Section 3.3.5 "Abort", IrOBEX 1.2 // [opcode:1][length:2][Headers:var] uint8_t req[255]; int index = 3; SetObexPacketInfo(req, ObexRequestCode::Abort, index); mLastCommand = ObexRequestCode::Abort; UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); - mSocket->SendSocketData(s); + SendSocketData(s); } bool BluetoothOppManager::IsTransferring() { return (mConnected && !mSendTransferCompleteFlag); } @@ -1107,17 +1104,17 @@ BluetoothOppManager::ReplyToConnect() req[4] = 0x00; // flag=0x00 req[5] = BluetoothOppManager::MAX_PACKET_LENGTH >> 8; req[6] = (uint8_t)BluetoothOppManager::MAX_PACKET_LENGTH; SetObexPacketInfo(req, ObexResponseCode::Success, index); UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); - mSocket->SendSocketData(s); + SendSocketData(s); } void BluetoothOppManager::ReplyToDisconnect() { if (!mConnected) return; mConnected = false; @@ -1125,17 +1122,17 @@ BluetoothOppManager::ReplyToDisconnect() // [opcode:1][length:2][Headers:var] uint8_t req[255]; int index = 3; SetObexPacketInfo(req, ObexResponseCode::Success, index); UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); - mSocket->SendSocketData(s); + SendSocketData(s); } void BluetoothOppManager::ReplyToPut(bool aFinal, bool aContinue) { if (!mConnected) return; // Section 3.3.2 "Disconnect", IrOBEX 1.2 @@ -1156,17 +1153,17 @@ BluetoothOppManager::ReplyToPut(bool aFi SetObexPacketInfo(req, ObexResponseCode::Unauthorized & (~FINAL_BIT), index); } } UnixSocketRawData* s = new UnixSocketRawData(index); memcpy(s->mData, req, s->mSize); - mSocket->SendSocketData(s); + SendSocketData(s); } void BluetoothOppManager::FileTransferComplete() { if (mSendTransferCompleteFlag) { return; } @@ -1298,89 +1295,83 @@ BluetoothOppManager::ReceivingFileConfir if (!BroadcastSystemMessage(type, parameters)) { NS_WARNING("Failed to send [bluetooth-opp-receiving-file-confirmation]"); return; } } void -BluetoothOppManager::OnConnectSuccess(BluetoothSocket* aSocket) +BluetoothOppManager::OnConnectSuccess() { - MOZ_ASSERT(aSocket == mSocket); - if (mRunnable) { BluetoothReply* reply = new BluetoothReply(BluetoothReplySuccess(true)); mRunnable->SetReply(reply); if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) { NS_WARNING("Failed to dispatch to main thread!"); } mRunnable.forget(); } // Cache device address since we can't get socket address when a remote // device disconnect with us. - mSocket->GetAddress(mConnectedDeviceAddress); - mPrevSocketStatus = mSocket->GetConnectionStatus(); + GetSocketAddr(mConnectedDeviceAddress); + + mSocketStatus = GetConnectionStatus(); } void -BluetoothOppManager::OnConnectError(BluetoothSocket* aSocket) +BluetoothOppManager::OnConnectError() { - MOZ_ASSERT(aSocket == mSocket); - if (mRunnable) { nsString errorStr; errorStr.AssignLiteral("Failed to connect with a bluetooth opp manager!"); BluetoothReply* reply = new BluetoothReply(BluetoothReplyError(errorStr)); mRunnable->SetReply(reply); if (NS_FAILED(NS_DispatchToMainThread(mRunnable))) { NS_WARNING("Failed to dispatch to main thread!"); } mRunnable.forget(); } - mSocket->Disconnect(); - mPrevSocketStatus = mSocket->GetConnectionStatus(); + CloseSocket(); + mSocketStatus = GetConnectionStatus(); Listen(); } void -BluetoothOppManager::OnDisconnect(BluetoothSocket* aSocket) +BluetoothOppManager::OnDisconnect() { - MOZ_ASSERT(aSocket == mSocket); - /** * It is valid for a bluetooth device which is transfering file via OPP * closing socket without sending OBEX disconnect request first. So we * delete the broken file when we failed to receive a file from the remote, * and notify the transfer has been completed (but failed). We also call * AfterOppDisconnected here to ensure all variables will be cleaned. */ - if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) { + if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) { if (mTransferMode) { if (!mSuccessFlag) { DeleteReceivedFile(); } else if (mDsFile) { nsString data; CopyASCIItoUTF16("modified", data); - nsCOMPtr<nsIObserverService> obs = - mozilla::services::GetObserverService(); + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { obs->NotifyObservers(mDsFile, "file-watcher-notify", data.get()); } } } if (!mSuccessFlag) { FileTransferComplete(); } Listen(); - } else if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTING) { + } else if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTING) { NS_WARNING("BluetoothOppManager got unexpected socket status!"); } AfterOppDisconnected(); - mConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE); + mConnectedDeviceAddress.AssignLiteral("00:00:00:00:00:00"); mSuccessFlag = false; }
--- a/dom/bluetooth/BluetoothOppManager.h +++ b/dom/bluetooth/BluetoothOppManager.h @@ -3,43 +3,43 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_bluetooth_bluetoothoppmanager_h__ #define mozilla_dom_bluetooth_bluetoothoppmanager_h__ #include "BluetoothCommon.h" -#include "BluetoothSocketObserver.h" #include "mozilla/dom/ipc/Blob.h" #include "mozilla/ipc/UnixSocket.h" #include "DeviceStorage.h" class nsIOutputStream; class nsIInputStream; BEGIN_BLUETOOTH_NAMESPACE class BluetoothReplyRunnable; -class BluetoothSocket; class ObexHeaderSet; -class BluetoothOppManager : public BluetoothSocketObserver +class BluetoothOppManager : public mozilla::ipc::UnixSocketConsumer { public: /* * Channel of reserved services are fixed values, please check * function add_reserved_service_records() in * external/bluetooth/bluez/src/adapter.c for more information. */ static const int DEFAULT_OPP_CHANNEL = 10; static const int MAX_PACKET_LENGTH = 0xFFFE; ~BluetoothOppManager(); static BluetoothOppManager* Get(); + void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) + MOZ_OVERRIDE; void ClientDataHandler(mozilla::ipc::UnixSocketRawData* aMessage); void ServerDataHandler(mozilla::ipc::UnixSocketRawData* aMessage); /* * If a application wnats to send a file, first, it needs to * call Connect() to create a valid RFCOMM connection. After * that, call SendFile()/StopSendingFile() to control file-sharing * process. During the file transfering process, the application @@ -67,29 +67,16 @@ public: void ExtractPacketHeaders(const ObexHeaderSet& aHeader); bool ExtractBlobHeaders(); nsresult HandleShutdown(); // Return true if there is an ongoing file-transfer session, please see // Bug 827267 for more information. bool IsTransferring(); - - // Implement interface BluetoothSocketObserver - void ReceiveSocketData( - BluetoothSocket* aSocket, - nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE; - - virtual void OnConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE; - virtual void OnConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE; - virtual void OnDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE; - void OnConnectSuccess() MOZ_OVERRIDE; - void OnConnectError() MOZ_OVERRIDE; - void OnDisconnect() MOZ_OVERRIDE; - private: BluetoothOppManager(); void StartFileTransfer(); void FileTransferComplete(); void UpdateProgress(); void ReceivingFileConfirmation(); bool CreateFile(); bool WriteToFile(const uint8_t* aData, int aDataLength); @@ -98,20 +85,24 @@ private: void ReplyToDisconnect(); void ReplyToPut(bool aFinal, bool aContinue); void AfterOppConnected(); void AfterFirstPut(); void AfterOppDisconnected(); void ValidateFileName(); bool IsReservedChar(PRUnichar c); + virtual void OnConnectSuccess() MOZ_OVERRIDE; + virtual void OnConnectError() MOZ_OVERRIDE; + virtual void OnDisconnect() MOZ_OVERRIDE; + /** * RFCOMM socket status. */ - mozilla::ipc::SocketConnectionStatus mPrevSocketStatus; + enum mozilla::ipc::SocketConnectionStatus mSocketStatus; /** * OBEX session status. * Set when OBEX session is established. */ bool mConnected; nsString mConnectedDeviceAddress; @@ -177,14 +168,13 @@ private: nsCOMPtr<nsIDOMBlob> mBlob; nsCOMPtr<nsIThread> mReadFileThread; nsCOMPtr<nsIOutputStream> mOutputStream; nsCOMPtr<nsIInputStream> mInputStream; nsRefPtr<BluetoothReplyRunnable> mRunnable; nsRefPtr<DeviceStorageFile> mDsFile; - nsRefPtr<BluetoothSocket> mSocket; }; END_BLUETOOTH_NAMESPACE #endif
--- a/dom/bluetooth/BluetoothScoManager.cpp +++ b/dom/bluetooth/BluetoothScoManager.cpp @@ -5,17 +5,16 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "base/basictypes.h" #include "BluetoothScoManager.h" #include "BluetoothReplyRunnable.h" #include "BluetoothService.h" -#include "BluetoothSocket.h" #include "BluetoothUtils.h" #include "mozilla/Services.h" #include "mozilla/StaticPtr.h" #include "mozilla/dom/bluetooth/BluetoothTypes.h" #include "nsContentUtils.h" #include "nsIAudioManager.h" #include "nsIObserverService.h" @@ -89,17 +88,17 @@ BluetoothScoManager::NotifyAudioManager( do_GetService("@mozilla.org/telephony/audiomanager;1"); NS_ENSURE_TRUE_VOID(am); am->SetForceForUse(am->USE_COMMUNICATION, am->FORCE_BT_SCO); } NS_IMPL_ISUPPORTS1(BluetoothScoManagerObserver, nsIObserver) namespace { -StaticAutoPtr<BluetoothScoManager> gBluetoothScoManager; +StaticRefPtr<BluetoothScoManager> gBluetoothScoManager; StaticRefPtr<BluetoothScoManagerObserver> sScoObserver; bool gInShutdown = false; } // anonymous namespace NS_IMETHODIMP BluetoothScoManagerObserver::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData) @@ -115,21 +114,17 @@ BluetoothScoManagerObserver::Observe(nsI BluetoothScoManager::BluetoothScoManager() { } bool BluetoothScoManager::Init() { - mSocket = new BluetoothSocket(this, - BluetoothSocketType::SCO, - true, - false); - mPrevSocketStatus = mSocket->GetConnectionStatus(); + mSocketStatus = GetConnectionStatus(); sScoObserver = new BluetoothScoManagerObserver(); if (!sScoObserver->Init()) { NS_WARNING("Cannot set up SCO observers!"); } return true; } @@ -158,133 +153,135 @@ BluetoothScoManager::Get() // If we're in shutdown, don't create a new instance if (gInShutdown) { NS_WARNING("BluetoothScoManager can't be created during shutdown"); return nullptr; } // Create new instance, register, return - BluetoothScoManager* manager = new BluetoothScoManager(); - NS_ENSURE_TRUE(manager->Init(), nullptr); + nsRefPtr<BluetoothScoManager> manager = new BluetoothScoManager(); + NS_ENSURE_TRUE(manager, nullptr); + + if (!manager->Init()) { + return nullptr; + } gBluetoothScoManager = manager; return gBluetoothScoManager; } // Virtual function of class SocketConsumer void -BluetoothScoManager::ReceiveSocketData(BluetoothSocket* aSocket, - nsAutoPtr<UnixSocketRawData>& aMessage) +BluetoothScoManager::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage) { // SCO socket do nothing here MOZ_NOT_REACHED("This should never be called!"); } nsresult BluetoothScoManager::HandleShutdown() { MOZ_ASSERT(NS_IsMainThread()); gInShutdown = true; - mSocket->Disconnect(); + CloseSocket(); gBluetoothScoManager = nullptr; return NS_OK; } bool BluetoothScoManager::Connect(const nsAString& aDeviceAddress) { MOZ_ASSERT(NS_IsMainThread()); if (gInShutdown) { MOZ_ASSERT(false, "Connect called while in shutdown!"); return false; } - if (mSocket->GetConnectionStatus() == - SocketConnectionStatus::SOCKET_CONNECTED) { + if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED) { NS_WARNING("Sco socket has been connected"); return false; } - mSocket->Disconnect(); + CloseSocket(); BluetoothService* bs = BluetoothService::Get(); if (!bs) { NS_WARNING("BluetoothService not available!"); return false; } nsresult rv = bs->GetScoSocket(aDeviceAddress, true, false, - mSocket); + this); return NS_FAILED(rv) ? false : true; } bool BluetoothScoManager::Listen() { MOZ_ASSERT(NS_IsMainThread()); if (gInShutdown) { MOZ_ASSERT(false, "Listen called while in shutdown!"); return false; } - if (mSocket->GetConnectionStatus() == - SocketConnectionStatus::SOCKET_LISTENING) { - NS_WARNING("BluetoothScoManager has been already listening"); - return true; - } + CloseSocket(); - mSocket->Disconnect(); - - if (!mSocket->Listen(-1)) { - NS_WARNING("[SCO] Can't listen on socket!"); + BluetoothService* bs = BluetoothService::Get(); + if (!bs) { + NS_WARNING("BluetoothService not available!"); return false; } - mPrevSocketStatus = mSocket->GetConnectionStatus(); - return true; + nsresult rv = bs->ListenSocketViaService(-1, + BluetoothSocketType::SCO, + true, + true, + this); + + mSocketStatus = GetConnectionStatus(); + + return NS_FAILED(rv) ? false : true; } void BluetoothScoManager::Disconnect() { - mSocket->Disconnect(); + if (GetConnectionStatus() == SocketConnectionStatus::SOCKET_DISCONNECTED) { + return; + } + + CloseSocket(); } void -BluetoothScoManager::OnConnectSuccess(BluetoothSocket* aSocket) +BluetoothScoManager::OnConnectSuccess() { - MOZ_ASSERT(aSocket == mSocket); - nsString address; - mSocket->GetAddress(address); + GetSocketAddr(address); NotifyAudioManager(address); - mPrevSocketStatus = mSocket->GetConnectionStatus(); + mSocketStatus = GetConnectionStatus(); } void -BluetoothScoManager::OnConnectError(BluetoothSocket* aSocket) +BluetoothScoManager::OnConnectError() { - MOZ_ASSERT(aSocket == mSocket); - - mSocket->Disconnect(); - mPrevSocketStatus = mSocket->GetConnectionStatus(); + CloseSocket(); + mSocketStatus = GetConnectionStatus(); Listen(); } void -BluetoothScoManager::OnDisconnect(BluetoothSocket* aSocket) +BluetoothScoManager::OnDisconnect() { - MOZ_ASSERT(aSocket == mSocket); - - if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) { + if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) { Listen(); nsString address = NS_LITERAL_STRING(""); NotifyAudioManager(address); } }
--- a/dom/bluetooth/BluetoothScoManager.h +++ b/dom/bluetooth/BluetoothScoManager.h @@ -3,49 +3,46 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_bluetooth_bluetoothscomanager_h__ #define mozilla_dom_bluetooth_bluetoothscomanager_h__ #include "BluetoothCommon.h" -#include "BluetoothSocketObserver.h" +#include "mozilla/ipc/UnixSocket.h" #include "nsIObserver.h" BEGIN_BLUETOOTH_NAMESPACE class BluetoothReplyRunnable; class BluetoothScoManagerObserver; -class BluetoothSocket; -class BluetoothScoManager : public BluetoothSocketObserver +class BluetoothScoManager : public mozilla::ipc::UnixSocketConsumer { public: - static BluetoothScoManager* Get(); ~BluetoothScoManager(); - virtual void ReceiveSocketData( - BluetoothSocket* aSocket, - nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE; - virtual void OnConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE; - virtual void OnConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE; - virtual void OnDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE; + static BluetoothScoManager* Get(); + void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) + MOZ_OVERRIDE; bool Connect(const nsAString& aDeviceObjectPath); void Disconnect(); bool Listen(); private: friend class BluetoothScoManagerObserver; BluetoothScoManager(); bool Init(); void Cleanup(); nsresult HandleShutdown(); void NotifyAudioManager(const nsAString& aAddress); + virtual void OnConnectSuccess() MOZ_OVERRIDE; + virtual void OnConnectError() MOZ_OVERRIDE; + virtual void OnDisconnect() MOZ_OVERRIDE; - SocketConnectionStatus mPrevSocketStatus; - nsRefPtr<BluetoothSocket> mSocket; + int mSocketStatus; }; END_BLUETOOTH_NAMESPACE #endif
--- a/dom/bluetooth/BluetoothService.h +++ b/dom/bluetooth/BluetoothService.h @@ -244,16 +244,23 @@ public: BlobParent* aBlobParent, BlobChild* aBlobChild, BluetoothReplyRunnable* aRunnable) = 0; virtual void StopSendingFile(const nsAString& aDeviceAddress, BluetoothReplyRunnable* aRunnable) = 0; + virtual nsresult + ListenSocketViaService(int aChannel, + BluetoothSocketType aType, + bool aAuth, + bool aEncrypt, + mozilla::ipc::UnixSocketConsumer* aConsumer) = 0; + virtual void ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirm, BluetoothReplyRunnable* aRunnable) = 0; bool IsEnabled() const { return mEnabled;
deleted file mode 100644 --- a/dom/bluetooth/BluetoothSocket.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "BluetoothSocket.h" - -#include "BluetoothSocketObserver.h" -#include "BluetoothUnixSocketConnector.h" -#include "nsThreadUtils.h" - -using namespace mozilla::ipc; -USING_BLUETOOTH_NAMESPACE - -BluetoothSocket::BluetoothSocket(BluetoothSocketObserver* aObserver, - BluetoothSocketType aType, - bool aAuth, - bool aEncrypt) - : mObserver(aObserver) - , mType(aType) - , mAuth(aAuth) - , mEncrypt(aEncrypt) -{ - MOZ_ASSERT(aObserver); -} - -bool -BluetoothSocket::Connect(const nsACString& aDeviceAddress, int aChannel) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(!aDeviceAddress.IsEmpty()); - - nsAutoPtr<BluetoothUnixSocketConnector> c( - new BluetoothUnixSocketConnector(mType, aChannel, mAuth, mEncrypt)); - - if (!ConnectSocket(c.forget(), aDeviceAddress.BeginReading())) { - nsAutoString addr; - GetAddress(addr); - BT_LOG("%s failed. Current connected device address: %s", - __FUNCTION__, NS_ConvertUTF16toUTF8(addr).get()); - return false; - } - - return true; -} - -bool -BluetoothSocket::Listen(int aChannel) -{ - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr<BluetoothUnixSocketConnector> c( - new BluetoothUnixSocketConnector(mType, aChannel, mAuth, mEncrypt)); - - if (!ListenSocket(c.forget())) { - nsAutoString addr; - GetAddress(addr); - BT_LOG("%s failed. Current connected device address: %s", - __FUNCTION__, NS_ConvertUTF16toUTF8(addr).get()); - return false; - } - - return true; -} - -void -BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mObserver); - mObserver->ReceiveSocketData(this, aMessage); -} - -void -BluetoothSocket::OnConnectSuccess() -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mObserver); - mObserver->OnConnectSuccess(this); -} - -void -BluetoothSocket::OnConnectError() -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mObserver); - mObserver->OnConnectError(this); -} - -void -BluetoothSocket::OnDisconnect() -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mObserver); - mObserver->OnDisconnect(this); -} -
deleted file mode 100644 --- a/dom/bluetooth/BluetoothSocket.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_bluetooth_BluetoothSocket_h -#define mozilla_dom_bluetooth_BluetoothSocket_h - -#include "BluetoothCommon.h" -#include "mozilla/ipc/UnixSocket.h" - -BEGIN_BLUETOOTH_NAMESPACE - -class BluetoothSocketObserver; - -class BluetoothSocket : public mozilla::ipc::UnixSocketConsumer -{ -public: - BluetoothSocket(BluetoothSocketObserver* aObserver, - BluetoothSocketType aType, - bool aAuth, - bool aEncrypt); - - bool Connect(const nsACString& aDeviceAddress, int aChannel); - bool Listen(int aChannel); - inline void Disconnect() - { - CloseSocket(); - } - - virtual void OnConnectSuccess() MOZ_OVERRIDE; - virtual void OnConnectError() MOZ_OVERRIDE; - virtual void OnDisconnect() MOZ_OVERRIDE; - virtual void ReceiveSocketData( - nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE; - - inline void GetAddress(nsAString& aDeviceAddress) - { - GetSocketAddr(aDeviceAddress); - } - -private: - BluetoothSocketObserver* mObserver; - BluetoothSocketType mType; - bool mAuth; - bool mEncrypt; -}; - -END_BLUETOOTH_NAMESPACE - -#endif
deleted file mode 100644 --- a/dom/bluetooth/BluetoothSocketObserver.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_bluetooth_BluetoothSocketObserver_h -#define mozilla_dom_bluetooth_BluetoothSocketObserver_h - -#include "BluetoothCommon.h" -#include <mozilla/ipc/UnixSocket.h> - -using namespace mozilla::ipc; - -BEGIN_BLUETOOTH_NAMESPACE - -class BluetoothSocket; - -class BluetoothSocketObserver -{ -public: - virtual void ReceiveSocketData(BluetoothSocket* aSocket, - nsAutoPtr<UnixSocketRawData>& aMessage) = 0; - - /** - * A callback function which would be called when a socket connection - * is established successfully. To be more specific, this would be called - * when socket state changes from CONNECTING/LISTENING to CONNECTED. - */ - virtual void OnConnectSuccess(BluetoothSocket* aSocket) = 0; - - /** - * A callback function which would be called when BluetoothSocket::Connect() - * fails. - */ - virtual void OnConnectError(BluetoothSocket* aSocket) = 0; - - /** - * A callback function which would be called when a socket connection - * is dropped. To be more specific, this would be called when socket state - * changes from CONNECTED/LISTENING to DISCONNECTED. - */ - virtual void OnDisconnect(BluetoothSocket* aSocket) = 0; - -}; - -END_BLUETOOTH_NAMESPACE - -#endif
--- a/dom/bluetooth/Makefile.in +++ b/dom/bluetooth/Makefile.in @@ -49,17 +49,16 @@ CPPSRCS += \ BluetoothParent.cpp \ BluetoothServiceChildProcess.cpp \ BluetoothUnixSocketConnector.cpp \ BluetoothHfpManager.cpp \ BluetoothOppManager.cpp \ ObexBase.cpp \ BluetoothScoManager.cpp \ BluetoothUuid.cpp \ - BluetoothSocket.cpp \ $(NULL) ifdef MOZ_B2G_RIL CPPSRCS += BluetoothTelephonyListener.cpp endif ifeq (gonk,$(MOZ_WIDGET_TOOLKIT)) VPATH += \
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp +++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp @@ -207,16 +207,29 @@ BluetoothServiceChildProcess::GetSocketV bool aEncrypt, mozilla::ipc::UnixSocketConsumer* aConsumer, BluetoothReplyRunnable* aRunnable) { MOZ_NOT_REACHED("This should never be called!"); return NS_ERROR_FAILURE; } + +nsresult +BluetoothServiceChildProcess::ListenSocketViaService( + int aChannel, + BluetoothSocketType aType, + bool aAuth, + bool aEncrypt, + mozilla::ipc::UnixSocketConsumer* aConsumer) +{ + MOZ_NOT_REACHED("This should never be called!"); + return NS_ERROR_FAILURE; +} + bool BluetoothServiceChildProcess::SetPinCodeInternal( const nsAString& aDeviceAddress, const nsAString& aPinCode, BluetoothReplyRunnable* aRunnable) { SendRequest(aRunnable, SetPinCodeRequest(nsString(aDeviceAddress), nsString(aPinCode)));
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.h +++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.h @@ -86,16 +86,23 @@ public: GetSocketViaService(const nsAString& aObjectPath, const nsAString& aService, BluetoothSocketType aType, bool aAuth, bool aEncrypt, mozilla::ipc::UnixSocketConsumer* aConsumer, BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE; + virtual nsresult + ListenSocketViaService(int aChannel, + BluetoothSocketType aType, + bool aAuth, + bool aEncrypt, + mozilla::ipc::UnixSocketConsumer* aConsumer) MOZ_OVERRIDE; + virtual bool SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode, BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE; virtual bool SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp +++ b/dom/bluetooth/linux/BluetoothDBusService.cpp @@ -828,27 +828,27 @@ public: class ShutdownProfileManagersRunnable : public nsRunnable { public: NS_IMETHOD Run() { BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); if (hfp) { - hfp->Disconnect(); + hfp->CloseSocket(); } BluetoothOppManager* opp = BluetoothOppManager::Get(); if (opp) { - opp->Disconnect(); + opp->CloseSocket(); } BluetoothScoManager* sco = BluetoothScoManager::Get(); if (sco) { - sco->Disconnect(); + sco->CloseSocket(); } return NS_OK; } }; class PrepareAdapterRunnable : public nsRunnable { @@ -2542,17 +2542,18 @@ BluetoothDBusService::Disconnect(const u bool BluetoothDBusService::IsConnected(const uint16_t aProfileId) { NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!"); if (aProfileId == BluetoothServiceClass::HANDSFREE || aProfileId == BluetoothServiceClass::HEADSET) { BluetoothHfpManager* hfp = BluetoothHfpManager::Get(); - return (hfp->IsConnected()); + return (hfp->GetConnectionStatus() == + SocketConnectionStatus::SOCKET_CONNECTED); } else if (aProfileId == BluetoothServiceClass::OBJECT_PUSH) { BluetoothOppManager* opp = BluetoothOppManager::Get(); return opp->IsTransferring(); } return false; } @@ -2788,8 +2789,27 @@ BluetoothDBusService::ConfirmReceivingFi if (!opp->ConfirmReceivingFile(aConfirm)) { errorStr.AssignLiteral("Calling ConfirmReceivingFile() failed"); } DispatchBluetoothReply(aRunnable, v, errorStr); } +nsresult +BluetoothDBusService::ListenSocketViaService( + int aChannel, + BluetoothSocketType aType, + bool aAuth, + bool aEncrypt, + mozilla::ipc::UnixSocketConsumer* aConsumer) +{ + NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!"); + + BluetoothUnixSocketConnector* c = + new BluetoothUnixSocketConnector(aType, aChannel, aAuth, aEncrypt); + if (!aConsumer->ListenSocket(c)) { + NS_WARNING("Can't listen on socket!"); + return NS_ERROR_FAILURE; + } + + return NS_OK; +}
--- a/dom/bluetooth/linux/BluetoothDBusService.h +++ b/dom/bluetooth/linux/BluetoothDBusService.h @@ -82,16 +82,23 @@ public: const nsAString& aService, BluetoothSocketType aType, bool aAuth, bool aEncrypt, mozilla::ipc::UnixSocketConsumer* aConsumer, BluetoothReplyRunnable* aRunnable); virtual nsresult + ListenSocketViaService(int aChannel, + BluetoothSocketType aType, + bool aAuth, + bool aEncrypt, + mozilla::ipc::UnixSocketConsumer* aConsumer); + + virtual nsresult CreatePairedDeviceInternal(const nsAString& aDeviceAddress, int aTimeout, BluetoothReplyRunnable* aRunnable); virtual nsresult RemoveDeviceInternal(const nsAString& aDeviceObjectPath, BluetoothReplyRunnable* aRunnable);
--- a/ipc/unixsocket/UnixSocket.h +++ b/ipc/unixsocket/UnixSocket.h @@ -137,17 +137,17 @@ enum SocketConnectionStatus { class UnixSocketConsumer : public RefCounted<UnixSocketConsumer> { public: UnixSocketConsumer(); virtual ~UnixSocketConsumer(); - SocketConnectionStatus GetConnectionStatus() const + SocketConnectionStatus GetConnectionStatus() { return mConnectionStatus; } /** * Function to be called whenever data is received. This is only called on the * main thread. *