mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Bug 820143 - implemented Calling Line Identification (CLI), r=gyeh
This commit is contained in:
parent
d81584a36d
commit
093aeb72ad
@ -34,6 +34,14 @@
|
||||
#define TOA_UNKNOWN 0x81
|
||||
#define TOA_INTERNATIONAL 0x91
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::ipc;
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
@ -216,7 +224,9 @@ BluetoothHfpManagerObserver::Observe(nsISupports* aSubject,
|
||||
class SendRingIndicatorTask : public Task
|
||||
{
|
||||
public:
|
||||
SendRingIndicatorTask()
|
||||
SendRingIndicatorTask(const char* aNumber, int aType = TOA_UNKNOWN)
|
||||
: mNumber(aNumber)
|
||||
, mType(aType)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
@ -231,15 +241,27 @@ public:
|
||||
NS_WARNING("BluetoothHfpManager no longer exists, cannot send ring!");
|
||||
return;
|
||||
}
|
||||
|
||||
gBluetoothHfpManager->SendLine("RING");
|
||||
|
||||
if (!mNumber.IsEmpty()) {
|
||||
nsAutoCString resultCode("+CLIP: \"");
|
||||
resultCode += mNumber;
|
||||
resultCode += "\",";
|
||||
resultCode.AppendInt(mType);
|
||||
|
||||
gBluetoothHfpManager->SendLine(resultCode.get());
|
||||
}
|
||||
|
||||
MessageLoop::current()->
|
||||
PostDelayedTask(FROM_HERE,
|
||||
new SendRingIndicatorTask(),
|
||||
new SendRingIndicatorTask(mNumber.get(), mType),
|
||||
sRingInterval);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCString mNumber;
|
||||
int mType;
|
||||
};
|
||||
|
||||
void
|
||||
@ -517,36 +539,43 @@ BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
const char* msg = (const char*)aMessage->mData;
|
||||
int currentCallState = mCurrentCallStateArray[mCurrentCallIndex];
|
||||
|
||||
nsAutoCString msg((const char*)aMessage->mData);
|
||||
msg.StripWhitespace();
|
||||
|
||||
nsTArray<nsCString> atCommandValues;
|
||||
|
||||
// For more information, please refer to 4.34.1 "Bluetooth Defined AT
|
||||
// Capabilities" in Bluetooth hands-free profile 1.6
|
||||
if (!strncmp(msg, "AT+BRSF=", 8)) {
|
||||
if (msg.Find("AT+BRSF=") != -1) {
|
||||
SendCommand("+BRSF: ", 23);
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "AT+CIND=?", 9)) {
|
||||
} else if (msg.Find("AT+CIND=?") != -1) {
|
||||
// Asking for CIND range
|
||||
SendCommand("+CIND: ", 0);
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "AT+CIND?", 8)) {
|
||||
} else if (msg.Find("AT+CIND?") != -1) {
|
||||
// Asking for CIND value
|
||||
SendCommand("+CIND: ", 1);
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "AT+CMER=", 8)) {
|
||||
// SLC establishment
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "AT+CHLD=?", 9)) {
|
||||
} else if (msg.Find("AT+CMER=") != -1) {
|
||||
/**
|
||||
* SLC establishment is done when AT+CMER has been received.
|
||||
* Do nothing but respond with "OK".
|
||||
*/
|
||||
} else if (msg.Find("AT+CHLD=?") != -1) {
|
||||
SendLine("+CHLD: (1,2)");
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "AT+CHLD=", 8)) {
|
||||
int length = strlen(msg) - 9;
|
||||
nsAutoCString chldString(nsDependentCSubstring(msg+8, length));
|
||||
} else if (msg.Find("AT+CHLD=") != -1) {
|
||||
ParseAtCommand(msg, 8, atCommandValues);
|
||||
|
||||
if (atCommandValues.IsEmpty()) {
|
||||
NS_WARNING("Could't get the value of command [AT+VGS=]");
|
||||
goto respond_with_ok;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
int chld = chldString.ToInteger(&rv);
|
||||
int chld = atCommandValues[0].ToInteger(&rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to extract volume value from bluetooth headset!");
|
||||
goto respond_with_ok;
|
||||
}
|
||||
|
||||
switch(chld) {
|
||||
@ -564,23 +593,25 @@ BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "AT+VGS=", 7)) {
|
||||
} else if (msg.Find("AT+VGS=") != -1) {
|
||||
// Adjust volume by headset
|
||||
mReceiveVgsFlag = true;
|
||||
ParseAtCommand(msg, 7, atCommandValues);
|
||||
|
||||
int length = strlen(msg) - 8;
|
||||
nsAutoCString vgsString(nsDependentCSubstring(msg+7, length));
|
||||
if (atCommandValues.IsEmpty()) {
|
||||
NS_WARNING("Could't get the value of command [AT+VGS=]");
|
||||
goto respond_with_ok;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
int newVgs = vgsString.ToInteger(&rv);
|
||||
int newVgs = atCommandValues[0].ToInteger(&rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to extract volume value from bluetooth headset!");
|
||||
goto respond_with_ok;
|
||||
}
|
||||
|
||||
if (newVgs == mCurrentVgs) {
|
||||
SendLine("OK");
|
||||
return;
|
||||
goto respond_with_ok;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -591,34 +622,36 @@ BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
data.AppendInt(newVgs);
|
||||
os->NotifyObservers(nullptr, "bluetooth-volume-change", data.get());
|
||||
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "AT+BLDN", 7)) {
|
||||
} else if (msg.Find("AT+BLDN") != -1) {
|
||||
NotifyDialer(NS_LITERAL_STRING("BLDN"));
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "ATA", 3)) {
|
||||
} else if (msg.Find("ATA") != -1) {
|
||||
NotifyDialer(NS_LITERAL_STRING("ATA"));
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "AT+CHUP", 7)) {
|
||||
} else if (msg.Find("AT+CHUP") != -1) {
|
||||
NotifyDialer(NS_LITERAL_STRING("CHUP"));
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "ATD>", 4)) {
|
||||
} else if (msg.Find("ATD>") != -1) {
|
||||
// Currently, we don't support memory dialing in Dialer app
|
||||
SendLine("ERROR");
|
||||
} else if (!strncmp(msg, "ATD", 3)) {
|
||||
} else if (msg.Find("ATD") != -1) {
|
||||
nsAutoCString message(msg), newMsg;
|
||||
int end = message.FindChar(';');
|
||||
if (end < 0) {
|
||||
NS_WARNING("Could't get the value of command [ATD]");
|
||||
SendLine("OK");
|
||||
return;
|
||||
goto respond_with_ok;
|
||||
}
|
||||
|
||||
newMsg += nsDependentCSubstring(message, 0, end);
|
||||
NotifyDialer(NS_ConvertUTF8toUTF16(newMsg));
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "AT+CKPD", 7)) {
|
||||
// For Headset
|
||||
} else if (msg.Find("AT+CLIP=") != -1) {
|
||||
ParseAtCommand(msg, 8, atCommandValues);
|
||||
|
||||
if (atCommandValues.IsEmpty()) {
|
||||
NS_WARNING("Could't get the value of command [AT+CLIP=]");
|
||||
goto respond_with_ok;
|
||||
}
|
||||
|
||||
mCLIP = (atCommandValues[0].EqualsLiteral("1"));
|
||||
} else if (msg.Find("AT+CKPD") != -1) {
|
||||
// For Headset Profile (HSP)
|
||||
switch (currentCallState) {
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
|
||||
NotifyDialer(NS_LITERAL_STRING("ATA"));
|
||||
@ -637,8 +670,7 @@ BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
SendLine("OK");
|
||||
} else if (!strncmp(msg, "AT+CNUM", 7)) {
|
||||
} else if (msg.Find("AT+CNUM") != -1) {
|
||||
if (!mMsisdn.IsEmpty()) {
|
||||
nsAutoCString message("+CNUM: ,\"");
|
||||
message += NS_ConvertUTF16toUTF8(mMsisdn).get();
|
||||
@ -647,7 +679,6 @@ BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
message += ",,4";
|
||||
SendLine(message.get());
|
||||
}
|
||||
SendLine("OK");
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
nsCString warningMsg;
|
||||
@ -655,8 +686,11 @@ BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage)
|
||||
warningMsg.Append(msg);
|
||||
NS_WARNING(warningMsg.get());
|
||||
#endif
|
||||
SendLine("OK");
|
||||
}
|
||||
|
||||
respond_with_ok:
|
||||
// We always respond to remote device with "OK" in general cases.
|
||||
SendLine("OK");
|
||||
}
|
||||
|
||||
bool
|
||||
@ -815,12 +849,13 @@ BluetoothHfpManager::SendCommand(const char* aCommand, const int aValue)
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHfpManager::SetupCIND(int aCallIndex, int aCallState, bool aInitial)
|
||||
BluetoothHfpManager::SetupCIND(int aCallIndex, int aCallState,
|
||||
const char* aNumber, bool aInitial)
|
||||
{
|
||||
nsRefPtr<nsRunnable> sendRingTask;
|
||||
nsString address;
|
||||
|
||||
while (aCallIndex >= mCurrentCallStateArray.Length()) {
|
||||
while (aCallIndex >= (int)mCurrentCallStateArray.Length()) {
|
||||
mCurrentCallStateArray.AppendElement((int)nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED);
|
||||
}
|
||||
|
||||
@ -836,8 +871,21 @@ BluetoothHfpManager::SetupCIND(int aCallIndex, int aCallState, bool aInitial)
|
||||
if (!mCurrentCallIndex) {
|
||||
// Start sending RING indicator to HF
|
||||
sStopSendingRingFlag = false;
|
||||
MessageLoop::current()->PostTask(FROM_HERE,
|
||||
new SendRingIndicatorTask());
|
||||
|
||||
if (!mCLIP) {
|
||||
MessageLoop::current()->PostTask(FROM_HERE,
|
||||
new SendRingIndicatorTask(""));
|
||||
} else {
|
||||
// Same logic as implementation in ril_worker.js
|
||||
int type = TOA_UNKNOWN;
|
||||
|
||||
if (aNumber && strlen(aNumber) > 0 && aNumber[0] == '+') {
|
||||
type = TOA_INTERNATIONAL;
|
||||
}
|
||||
|
||||
MessageLoop::current()->PostTask(FROM_HERE,
|
||||
new SendRingIndicatorTask(aNumber, type));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case nsIRadioInterfaceLayer::CALL_STATE_DIALING:
|
||||
@ -921,18 +969,18 @@ BluetoothHfpManager::SetupCIND(int aCallIndex, int aCallState, bool aInitial)
|
||||
// Find the first non-disconnected call (like connected, held),
|
||||
// and update mCurrentCallIndex
|
||||
int c;
|
||||
for (c = 1; c < mCurrentCallStateArray.Length(); c++) {
|
||||
for (c = 1; c < (int)mCurrentCallStateArray.Length(); c++) {
|
||||
if (mCurrentCallStateArray[c] != nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED) {
|
||||
mCurrentCallIndex = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// There is no call
|
||||
if (c == mCurrentCallStateArray.Length()) {
|
||||
// There is no call
|
||||
if (c == (int)mCurrentCallStateArray.Length()) {
|
||||
mCurrentCallIndex = 0;
|
||||
CloseScoSocket();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -964,7 +1012,7 @@ void
|
||||
BluetoothHfpManager::EnumerateCallState(int aCallIndex, int aCallState,
|
||||
const char* aNumber, bool aIsActive)
|
||||
{
|
||||
SetupCIND(aCallIndex, aCallState, true);
|
||||
SetupCIND(aCallIndex, aCallState, aNumber, true);
|
||||
|
||||
if (sCINDItems[CINDType::CALL].value == CallState::IN_PROGRESS ||
|
||||
sCINDItems[CINDType::CALLSETUP].value == CallSetupState::OUTGOING ||
|
||||
@ -988,7 +1036,7 @@ BluetoothHfpManager::CallStateChanged(int aCallIndex, int aCallState,
|
||||
return;
|
||||
}
|
||||
|
||||
SetupCIND(aCallIndex, aCallState, false);
|
||||
SetupCIND(aCallIndex, aCallState, aNumber, false);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1051,4 +1099,5 @@ BluetoothHfpManager::OnDisconnect()
|
||||
sCINDItems[CINDType::CALL].value = CallState::NO_CALL;
|
||||
sCINDItems[CINDType::CALLSETUP].value = CallSetupState::NO_CALLSETUP;
|
||||
sCINDItems[CINDType::CALLHELD].value = CallHeldState::NO_CALLHELD;
|
||||
mCLIP = false;
|
||||
}
|
||||
|
@ -34,7 +34,8 @@ public:
|
||||
const char* aNumber, bool aIsActive);
|
||||
void EnumerateCallState(int aCallIndex, int aCallState,
|
||||
const char* aNumber, bool aIsActive);
|
||||
void SetupCIND(int aCallIndex, int aCallState, bool aInitial);
|
||||
void SetupCIND(int aCallIndex, int aCallState,
|
||||
const char* aPhoneNumber, bool aInitial);
|
||||
bool Listen();
|
||||
void SetVolume(int aVolume);
|
||||
|
||||
@ -55,6 +56,7 @@ private:
|
||||
|
||||
int mCurrentVgs;
|
||||
int mCurrentCallIndex;
|
||||
bool mCLIP;
|
||||
bool mReceiveVgsFlag;
|
||||
nsString mDevicePath;
|
||||
nsString mMsisdn;
|
||||
|
@ -136,5 +136,25 @@ DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
|
||||
}
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
void
|
||||
ParseAtCommand(const nsACString& aAtCommand, const int aStart,
|
||||
nsTArray<nsCString>& aRetValues)
|
||||
{
|
||||
int length = aAtCommand.Length();
|
||||
int begin = aStart;
|
||||
|
||||
for (int i = aStart; i < length; ++i) {
|
||||
// Use ',' as separator
|
||||
if (aAtCommand[i] == ',') {
|
||||
nsCString tmp(nsDependentCSubstring(aAtCommand, begin, i - begin));
|
||||
aRetValues.AppendElement(tmp);
|
||||
|
||||
begin = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
nsCString tmp(nsDependentCSubstring(aAtCommand, begin));
|
||||
aRetValues.AppendElement(tmp);
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define mozilla_dom_bluetooth_bluetoothutils_h__
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
struct JSContext;
|
||||
struct JSObject;
|
||||
@ -39,6 +40,10 @@ DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
|
||||
const BluetoothValue& aValue,
|
||||
const nsAString& aErrorStr);
|
||||
|
||||
void
|
||||
ParseAtCommand(const nsACString& aAtCommand, const int aStart,
|
||||
nsTArray<nsCString>& aRetValues);
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user