mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 860166 - Use two server sockets to listen to both HFP and HSP services, r=gyeh, r=mrbkap
This commit is contained in:
parent
61e8e696a1
commit
a7bc2c708b
@ -393,12 +393,6 @@ BluetoothHfpManager::Init()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mSocket = new BluetoothSocket(this,
|
||||
BluetoothSocketType::RFCOMM,
|
||||
true,
|
||||
true);
|
||||
mPrevSocketStatus = mSocket->GetConnectionStatus();
|
||||
|
||||
sHfpObserver = new BluetoothHfpManagerObserver();
|
||||
if (!sHfpObserver->Init()) {
|
||||
NS_WARNING("Cannot set up Hfp Observers!");
|
||||
@ -422,6 +416,8 @@ BluetoothHfpManager::Init()
|
||||
rv = settingsLock->Get(AUDIO_VOLUME_BT_SCO, callback);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
Listen();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -476,8 +472,7 @@ BluetoothHfpManager::NotifySettings()
|
||||
type.AssignLiteral("bluetooth-hfp-status-changed");
|
||||
|
||||
name.AssignLiteral("connected");
|
||||
v = (mSocket->GetConnectionStatus() ==
|
||||
SocketConnectionStatus::SOCKET_CONNECTED);
|
||||
v = IsConnected();
|
||||
parameters.AppendElement(BluetoothNamedValue(name, v));
|
||||
|
||||
name.AssignLiteral("address");
|
||||
@ -573,7 +568,7 @@ BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData)
|
||||
}
|
||||
|
||||
// Only send volume back when there's a connected headset
|
||||
if (mSocket->GetConnectionStatus() == SocketConnectionStatus::SOCKET_CONNECTED) {
|
||||
if (IsConnected()) {
|
||||
SendCommand("+VGS: ", mCurrentVgs);
|
||||
}
|
||||
|
||||
@ -945,15 +940,21 @@ BluetoothHfpManager::Connect(const nsAString& aDevicePath,
|
||||
return false;
|
||||
}
|
||||
|
||||
SocketConnectionStatus s = mSocket->GetConnectionStatus();
|
||||
|
||||
if (s == SocketConnectionStatus::SOCKET_CONNECTED ||
|
||||
s == SocketConnectionStatus::SOCKET_CONNECTING) {
|
||||
if (mSocket) {
|
||||
NS_WARNING("BluetoothHfpManager has been already connected");
|
||||
return false;
|
||||
}
|
||||
|
||||
mSocket->Disconnect();
|
||||
// Stop listening because currently we only support one connection at a time.
|
||||
if (mHandsfreeSocket) {
|
||||
mHandsfreeSocket->Disconnect();
|
||||
mHandsfreeSocket = nullptr;
|
||||
}
|
||||
|
||||
if (mHeadsetSocket) {
|
||||
mHeadsetSocket->Disconnect();
|
||||
mHeadsetSocket = nullptr;
|
||||
}
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE(bs, false);
|
||||
@ -966,6 +967,8 @@ BluetoothHfpManager::Connect(const nsAString& aDevicePath,
|
||||
}
|
||||
|
||||
mRunnable = aRunnable;
|
||||
mSocket =
|
||||
new BluetoothSocket(this, BluetoothSocketType::RFCOMM, true, true);
|
||||
|
||||
nsresult rv = bs->GetSocketViaService(aDevicePath,
|
||||
uuid,
|
||||
@ -988,32 +991,54 @@ BluetoothHfpManager::Listen()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mSocket->GetConnectionStatus() ==
|
||||
SocketConnectionStatus::SOCKET_LISTENING) {
|
||||
NS_WARNING("BluetoothHfpManager has been already listening");
|
||||
return true;
|
||||
}
|
||||
|
||||
mSocket->Disconnect();
|
||||
|
||||
if (!mSocket->Listen(BluetoothReservedChannels::CHANNEL_HANDSFREE_AG)) {
|
||||
NS_WARNING("[HFP] Can't listen on socket!");
|
||||
if (mSocket) {
|
||||
NS_WARNING("mSocket exists. Failed to listen.");
|
||||
return false;
|
||||
}
|
||||
|
||||
mPrevSocketStatus = mSocket->GetConnectionStatus();
|
||||
if (!mHandsfreeSocket) {
|
||||
mHandsfreeSocket =
|
||||
new BluetoothSocket(this, BluetoothSocketType::RFCOMM, true, true);
|
||||
|
||||
if (!mHandsfreeSocket->Listen(
|
||||
BluetoothReservedChannels::CHANNEL_HANDSFREE_AG)) {
|
||||
NS_WARNING("[HFP] Can't listen on RFCOMM socket!");
|
||||
mHandsfreeSocket = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mHeadsetSocket) {
|
||||
mHeadsetSocket =
|
||||
new BluetoothSocket(this, BluetoothSocketType::RFCOMM, true, true);
|
||||
|
||||
if (!mHeadsetSocket->Listen(
|
||||
BluetoothReservedChannels::CHANNEL_HEADSET_AG)) {
|
||||
NS_WARNING("[HSP] Can't listen on RFCOMM socket!");
|
||||
mHandsfreeSocket->Disconnect();
|
||||
mHandsfreeSocket = nullptr;
|
||||
mHeadsetSocket = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHfpManager::Disconnect()
|
||||
{
|
||||
mSocket->Disconnect();
|
||||
if (mSocket) {
|
||||
mSocket->Disconnect();
|
||||
mSocket = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothHfpManager::SendLine(const char* aMessage)
|
||||
{
|
||||
MOZ_ASSERT(mSocket);
|
||||
|
||||
nsAutoCString msg;
|
||||
|
||||
msg.AppendLiteral(kHfpCrlf);
|
||||
@ -1026,7 +1051,8 @@ BluetoothHfpManager::SendLine(const char* aMessage)
|
||||
bool
|
||||
BluetoothHfpManager::SendCommand(const char* aCommand, uint8_t aValue)
|
||||
{
|
||||
if (mPrevSocketStatus != SocketConnectionStatus::SOCKET_CONNECTED) {
|
||||
if (!IsConnected()) {
|
||||
NS_WARNING("Trying to SendCommand() without a SLC");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1141,8 +1167,8 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
|
||||
const nsAString& aNumber,
|
||||
bool aSend)
|
||||
{
|
||||
if (mSocket->GetConnectionStatus() !=
|
||||
SocketConnectionStatus::SOCKET_CONNECTED) {
|
||||
if (!IsConnected()) {
|
||||
// Normal case. No need to print out warnings.
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1192,8 +1218,10 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
|
||||
number.AssignLiteral("");
|
||||
}
|
||||
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
new SendRingIndicatorTask(number, mCurrentCallArray[aCallIndex].mType),
|
||||
MessageLoop::current()->PostDelayedTask(
|
||||
FROM_HERE,
|
||||
new SendRingIndicatorTask(number,
|
||||
mCurrentCallArray[aCallIndex].mType),
|
||||
sRingInterval);
|
||||
}
|
||||
break;
|
||||
@ -1266,7 +1294,8 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
|
||||
break;
|
||||
case nsITelephonyProvider::CALL_STATE_CONNECTED:
|
||||
// No call is ongoing
|
||||
if (sCINDItems[CINDType::CALLHELD].value == CallHeldState::NO_CALLHELD) {
|
||||
if (sCINDItems[CINDType::CALLHELD].value ==
|
||||
CallHeldState::NO_CALLHELD) {
|
||||
UpdateCIND(CINDType::CALL, CallState::NO_CALL, aSend);
|
||||
}
|
||||
break;
|
||||
@ -1307,7 +1336,28 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
|
||||
void
|
||||
BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket)
|
||||
{
|
||||
MOZ_ASSERT(aSocket == mSocket);
|
||||
MOZ_ASSERT(aSocket);
|
||||
|
||||
/**
|
||||
* If the created connection is an inbound connection, close another server
|
||||
* socket because currently only one SLC is allowed. After that, we need to
|
||||
* make sure that both server socket would be nulled out. As for outbound
|
||||
* connections, we do nothing since sockets have been already handled in
|
||||
* function Connect().
|
||||
*/
|
||||
if (aSocket == mHandsfreeSocket) {
|
||||
MOZ_ASSERT(!mSocket);
|
||||
mHandsfreeSocket.swap(mSocket);
|
||||
|
||||
mHeadsetSocket->Disconnect();
|
||||
mHeadsetSocket = nullptr;
|
||||
} else if (aSocket == mHeadsetSocket) {
|
||||
MOZ_ASSERT(!mSocket);
|
||||
mHeadsetSocket.swap(mSocket);
|
||||
|
||||
mHandsfreeSocket->Disconnect();
|
||||
mHandsfreeSocket = nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITelephonyProvider> provider =
|
||||
do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
|
||||
@ -1326,7 +1376,6 @@ BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket)
|
||||
// Cache device path for NotifySettings() since we can't get socket address
|
||||
// when a headset disconnect with us
|
||||
mSocket->GetAddress(mDevicePath);
|
||||
mPrevSocketStatus = mSocket->GetConnectionStatus();
|
||||
|
||||
NotifySettings();
|
||||
}
|
||||
@ -1334,8 +1383,6 @@ BluetoothHfpManager::OnConnectSuccess(BluetoothSocket* aSocket)
|
||||
void
|
||||
BluetoothHfpManager::OnConnectError(BluetoothSocket* aSocket)
|
||||
{
|
||||
MOZ_ASSERT(aSocket == mSocket);
|
||||
|
||||
// For active connection request, we need to reply the DOMRequest
|
||||
if (mRunnable) {
|
||||
BluetoothValue v;
|
||||
@ -1346,6 +1393,10 @@ BluetoothHfpManager::OnConnectError(BluetoothSocket* aSocket)
|
||||
mRunnable.forget();
|
||||
}
|
||||
|
||||
mSocket = nullptr;
|
||||
mHandsfreeSocket = nullptr;
|
||||
mHeadsetSocket = nullptr;
|
||||
|
||||
// If connecting for some reason didn't work, restart listening
|
||||
Listen();
|
||||
}
|
||||
@ -1353,24 +1404,28 @@ BluetoothHfpManager::OnConnectError(BluetoothSocket* aSocket)
|
||||
void
|
||||
BluetoothHfpManager::OnDisconnect(BluetoothSocket* aSocket)
|
||||
{
|
||||
MOZ_ASSERT(aSocket == mSocket);
|
||||
MOZ_ASSERT(aSocket);
|
||||
|
||||
// When we close a connected socket, then restart listening again and
|
||||
// notify Settings app.
|
||||
if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
|
||||
Listen();
|
||||
NotifySettings();
|
||||
} else if (mPrevSocketStatus == SocketConnectionStatus::SOCKET_CONNECTING) {
|
||||
NS_WARNING("BluetoothHfpManager got unexpected socket status!");
|
||||
if (aSocket != mSocket) {
|
||||
// Do nothing when a listening server socket is closed.
|
||||
return;
|
||||
}
|
||||
|
||||
mSocket = nullptr;
|
||||
CloseScoSocket();
|
||||
|
||||
Listen();
|
||||
NotifySettings();
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool
|
||||
BluetoothHfpManager::IsConnected()
|
||||
{
|
||||
return mSocket->GetConnectionStatus() ==
|
||||
SocketConnectionStatus::SOCKET_CONNECTED;
|
||||
if (mSocket) {
|
||||
return mSocket->GetConnectionStatus() ==
|
||||
SocketConnectionStatus::SOCKET_CONNECTED;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -114,12 +114,22 @@ private:
|
||||
nsString mDevicePath;
|
||||
nsString mMsisdn;
|
||||
nsString mOperatorName;
|
||||
SocketConnectionStatus mPrevSocketStatus;
|
||||
|
||||
nsTArray<Call> mCurrentCallArray;
|
||||
nsAutoPtr<BluetoothTelephonyListener> mListener;
|
||||
nsRefPtr<BluetoothReplyRunnable> mRunnable;
|
||||
|
||||
// If a connection has been established, mSocket will be the socket
|
||||
// communicating with the remote socket. We maintain the invariant that if
|
||||
// mSocket is non-null, mHandsfreeSocket and mHeadsetSocket must be null (and
|
||||
// vice versa).
|
||||
nsRefPtr<BluetoothSocket> mSocket;
|
||||
|
||||
// Server sockets. Once an inbound connection is established, it will hand
|
||||
// over the ownership to mSocket, and get a new server socket while Listen()
|
||||
// is called.
|
||||
nsRefPtr<BluetoothSocket> mHandsfreeSocket;
|
||||
nsRefPtr<BluetoothSocket> mHeadsetSocket;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -105,7 +105,7 @@ BluetoothScoManagerObserver::Observe(nsISupports* aSubject,
|
||||
const PRUnichar* aData)
|
||||
{
|
||||
MOZ_ASSERT(gBluetoothScoManager);
|
||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
return gBluetoothScoManager->HandleShutdown();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user