Bug 794349 - Send correct +CIND: value to HS at SLC establishment. r=qdot, a=blocking-basecamp
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -23,16 +23,18 @@
#include "nsIRadioInterfaceLayer.h"
#include "nsVariant.h"
#include <unistd.h> /* usleep() */
#define MOZSETTINGS_CHANGED_ID "mozsettings-changed"
#define BLUETOOTH_SCO_STATUS_CHANGED "bluetooth-sco-status-changed"
#define AUDIO_VOLUME_MASTER "audio.volume.master"
+#define HANDSFREE_UUID mozilla::dom::bluetooth::BluetoothServiceUuidStr::Handsfree
+#define HEADSET_UUID mozilla::dom::bluetooth::BluetoothServiceUuidStr::Headset
using namespace mozilla;
using namespace mozilla::ipc;
USING_BLUETOOTH_NAMESPACE
class mozilla::dom::bluetooth::BluetoothHfpManagerObserver : public nsIObserver
{
public:
@@ -173,16 +175,19 @@ CloseScoSocket()
sco->Disconnect();
}
}
BluetoothHfpManager::BluetoothHfpManager()
: mCurrentVgs(-1)
, mCurrentCallIndex(0)
, mCurrentCallState(nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED)
+ , mCall(0)
+ , mCallSetup(0)
+ , mCallHeld(0)
{
}
bool
BluetoothHfpManager::Init()
{
sHfpObserver = new BluetoothHfpManagerObserver();
if (!sHfpObserver->Init()) {
@@ -384,16 +389,33 @@ BluetoothHfpManager::HandleShutdown()
{
MOZ_ASSERT(NS_IsMainThread());
gInShutdown = true;
CloseSocket();
gBluetoothHfpManager = nullptr;
return NS_OK;
}
+bool
+AppendIntegerToString(nsAutoCString& aString, int aValue)
+{
+ nsDiscriminatedUnion du;
+ du.mType = 0;
+ du.u.mInt8Value = aValue;
+
+ nsCString temp;
+ if (NS_FAILED(nsVariant::ConvertToACString(du, temp))) {
+ NS_WARNING("Failed to convert mCall/mCallSetup/mCallHeld to string");
+ return false;
+ }
+ aString += temp;
+ aString += ",";
+ return true;
+}
+
// Virtual function of class SocketConsumer
void
BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage)
{
MOZ_ASSERT(NS_IsMainThread());
const char* msg = (const char*)aMessage->mData;
@@ -411,23 +433,28 @@ BluetoothHfpManager::ReceiveSocketData(U
cindRange += "(\"service\",(0,1)),";
cindRange += "(\"call\",(0,1)),";
cindRange += "(\"callsetup\",(0-3)),";
cindRange += "(\"callheld\",(0-2)),";
cindRange += "(\"roam\",(0,1))";
SendLine(cindRange.get());
SendLine("OK");
- } else if (!strncmp(msg, "AT+CIND", 7)) {
- // FIXME - Bug 794349
- // This value reflects current status of telephony, roaming, battery ...,
- // so obviously fixed value must be wrong if there is an ongoing call.
- // Need a patch for this, but currently just using fixed value for basic
- // SLC establishment.
- SendLine("+CIND: 5,5,1,0,0,0,0");
+ } else if (!strncmp(msg, "AT+CIND?", 8)) {
+ nsAutoCString cind;
+ cind += "+CIND: 5,5,1,";
+
+ if (!AppendIntegerToString(cind, mCall) ||
+ !AppendIntegerToString(cind, mCallSetup) ||
+ !AppendIntegerToString(cind, mCallHeld)) {
+ NS_WARNING("Failed to convert mCall/mCallSetup/mCallHeld to string");
+ }
+ cind += "0";
+
+ SendLine(cind.get());
SendLine("OK");
} else if (!strncmp(msg, "AT+CMER=", 8)) {
// SLC establishment
NotifySettings(true);
SendLine("OK");
} else if (!strncmp(msg, "AT+CHLD=?", 9)) {
SendLine("+CHLD: (0,1,2,3)");
SendLine("OK");
@@ -517,21 +544,26 @@ BluetoothHfpManager::Connect(const nsASt
if (!bs) {
NS_WARNING("BluetoothService not available!");
return false;
}
mDevicePath = aDeviceObjectPath;
nsString serviceUuidStr;
if (aIsHandsfree) {
- serviceUuidStr = NS_ConvertUTF8toUTF16(mozilla::dom::bluetooth::BluetoothServiceUuidStr::Handsfree);
+ serviceUuidStr = NS_ConvertUTF8toUTF16(HANDSFREE_UUID);
} else {
- serviceUuidStr = NS_ConvertUTF8toUTF16(mozilla::dom::bluetooth::BluetoothServiceUuidStr::Headset);
+ serviceUuidStr = NS_ConvertUTF8toUTF16(HEADSET_UUID);
}
+ nsCOMPtr<nsIRILContentHelper> ril =
+ do_GetService("@mozilla.org/ril/content-helper;1");
+ NS_ENSURE_TRUE(ril, NS_ERROR_UNEXPECTED);
+ ril->EnumerateCalls(mListener->GetCallback());
+
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
nsresult rv = bs->GetSocketViaService(aDeviceObjectPath,
serviceUuidStr,
BluetoothSocketType::RFCOMM,
true,
false,
this,
@@ -565,32 +597,90 @@ BluetoothHfpManager::Listen()
return NS_FAILED(rv) ? false : true;
}
void
BluetoothHfpManager::Disconnect()
{
NotifySettings(false);
CloseSocket();
+ mCall = 0;
+ mCallSetup = 0;
+ mCallHeld = 0;
}
bool
BluetoothHfpManager::SendLine(const char* aMessage)
{
const char* kHfpCrlf = "\xd\xa";
nsAutoCString msg;
msg += kHfpCrlf;
msg += aMessage;
msg += kHfpCrlf;
return SendSocketData(msg);
}
/*
+ * EnumerateCallState will be called for each call
+ */
+void
+BluetoothHfpManager::EnumerateCallState(int aCallIndex, int aCallState,
+ const char* aNumber, bool aIsActive)
+{
+ // TODO: enums for mCall, mCallSetup, mCallHeld
+ /* mCall - 0: there are no calls in progress
+ * - 1: at least one call is in progress
+ * mCallSetup - 0: not currently in call set up
+ * - 1: an incoming call process ongoing
+ * - 2: an outgoing call set up is ongoing
+ * - 3: remote party being alerted in an outgoing call
+ * mCallHeld - 0: no calls held
+ * - 1: call is placed on hold or active/held calls swapped
+ * - 2: call o hold, no active call
+ */
+
+ if (mCallHeld == 2 && aIsActive) {
+ mCallHeld = 1;
+ }
+
+ if (mCall || mCallSetup) {
+ return;
+ }
+
+ switch (aCallState) {
+ case nsIRadioInterfaceLayer::CALL_STATE_ALERTING:
+ mCall = 1;
+ mCallSetup = 3;
+ break;
+ case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
+ mCall = 1;
+ mCallSetup = 1;
+ break;
+ case nsIRadioInterfaceLayer::CALL_STATE_CONNECTING:
+ case nsIRadioInterfaceLayer::CALL_STATE_CONNECTED:
+ case nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTING:
+ case nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED:
+ case nsIRadioInterfaceLayer::CALL_STATE_BUSY:
+ mCall = 1;
+ mCallSetup = 2;
+ break;
+ case nsIRadioInterfaceLayer::CALL_STATE_HOLDING:
+ case nsIRadioInterfaceLayer::CALL_STATE_HELD:
+ case nsIRadioInterfaceLayer::CALL_STATE_RESUMING:
+ mCall = 1;
+ mCallHeld = 2;
+ default:
+ mCall = 0;
+ mCallSetup = 0;
+ }
+}
+
+/*
* CallStateChanged will be called whenever call status is changed, and it
* also means we need to notify HS about the change. For more information,
* please refer to 4.13 ~ 4.15 in Bluetooth hands-free profile 1.6.
*/
void
BluetoothHfpManager::CallStateChanged(int aCallIndex, int aCallState,
const char* aNumber, bool aIsActive)
{
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -25,30 +25,35 @@ public:
void ReceiveSocketData(mozilla::ipc::UnixSocketRawData* aMessage);
bool Connect(const nsAString& aDeviceObjectPath,
const bool aIsHandsfree,
BluetoothReplyRunnable* aRunnable);
void Disconnect();
bool SendLine(const char* aMessage);
void CallStateChanged(int aCallIndex, int aCallState,
const char* aNumber, bool aIsActive);
+ void EnumerateCallState(int aCallIndex, int aCallState,
+ const char* aNumber, bool aIsActive);
bool Listen();
private:
friend class BluetoothHfpManagerObserver;
BluetoothHfpManager();
nsresult HandleVolumeChanged(const nsAString& aData);
nsresult HandleShutdown();
bool Init();
void Cleanup();
void NotifyDialer(const nsAString& aCommand);
void NotifySettings(const bool aConnected);
int mCurrentVgs;
int mCurrentCallIndex;
int mCurrentCallState;
+ int mCall;
+ int mCallSetup;
+ int mCallHeld;
nsAutoPtr<BluetoothRilListener> mListener;
nsString mDevicePath;
};
END_BLUETOOTH_NAMESPACE
#endif
--- a/dom/bluetooth/BluetoothRilListener.cpp
+++ b/dom/bluetooth/BluetoothRilListener.cpp
@@ -39,16 +39,19 @@ BluetoothRILTelephonyCallback::CallState
NS_IMETHODIMP
BluetoothRILTelephonyCallback::EnumerateCallState(uint32_t aCallIndex,
uint16_t aCallState,
const nsAString_internal& aNumber,
bool aIsActive,
bool* aResult)
{
+ BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
+ hfp->EnumerateCallState(aCallIndex, aCallState,
+ NS_ConvertUTF16toUTF8(aNumber).get(), aIsActive);
*aResult = true;
return NS_OK;
}
NS_IMETHODIMP
BluetoothRILTelephonyCallback::NotifyError(int32_t aCallIndex,
const nsAString& aError)
{
@@ -82,8 +85,14 @@ BluetoothRilListener::StopListening()
NS_ERROR("No RIL Service!");
return false;
}
nsresult rv = ril->UnregisterTelephonyCallback(mRILTelephonyCallback);
return NS_FAILED(rv) ? false : true;
}
+
+nsIRILTelephonyCallback*
+BluetoothRilListener::GetCallback()
+{
+ return mRILTelephonyCallback;
+}
--- a/dom/bluetooth/BluetoothRilListener.h
+++ b/dom/bluetooth/BluetoothRilListener.h
@@ -17,15 +17,17 @@ BEGIN_BLUETOOTH_NAMESPACE
class BluetoothRilListener
{
public:
BluetoothRilListener();
bool StartListening();
bool StopListening();
+ nsIRILTelephonyCallback* GetCallback();
+
private:
nsCOMPtr<nsIRILTelephonyCallback> mRILTelephonyCallback;
};
END_BLUETOOTH_NAMESPACE
#endif