Bug 921991 - B2G BT: support multiple sim cards, r=echou
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -410,17 +410,17 @@ BluetoothHfpManager::Init()
BT_WARNING("Failed to add observers!");
return false;
}
hal::RegisterBatteryObserver(this);
#ifdef MOZ_B2G_RIL
mListener = new BluetoothRilListener();
- if (!mListener->StartListening()) {
+ if (!mListener->Listen(true)) {
BT_WARNING("Failed to start listening RIL");
return false;
}
#endif
nsCOMPtr<nsISettingsService> settings =
do_GetService("@mozilla.org/settingsService;1");
NS_ENSURE_TRUE(settings, false);
@@ -442,17 +442,17 @@ BluetoothHfpManager::Init()
mScoSocketStatus = mScoSocket->GetConnectionStatus();
ListenSco();
return true;
}
BluetoothHfpManager::~BluetoothHfpManager()
{
#ifdef MOZ_B2G_RIL
- if (!mListener->StopListening()) {
+ if (!mListener->Listen(false)) {
BT_WARNING("Failed to stop listening RIL");
}
mListener = nullptr;
#endif
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
NS_ENSURE_TRUE_VOID(obs);
@@ -581,40 +581,40 @@ BluetoothHfpManager::HandleVolumeChanged
// Only send volume back when there's a connected headset
if (IsConnected()) {
SendCommand("+VGS: ", mCurrentVgs);
}
}
#ifdef MOZ_B2G_RIL
void
-BluetoothHfpManager::HandleVoiceConnectionChanged()
+BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId)
{
nsCOMPtr<nsIMobileConnectionProvider> connection =
do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
NS_ENSURE_TRUE_VOID(connection);
nsCOMPtr<nsIDOMMozMobileConnectionInfo> voiceInfo;
- // TODO: Bug 921991 - B2G BT: support multiple sim cards
- connection->GetVoiceConnectionInfo(0, getter_AddRefs(voiceInfo));
+ connection->GetVoiceConnectionInfo(aClientId, getter_AddRefs(voiceInfo));
NS_ENSURE_TRUE_VOID(voiceInfo);
nsString type;
voiceInfo->GetType(type);
mPhoneType = GetPhoneType(type);
bool roaming;
voiceInfo->GetRoaming(&roaming);
UpdateCIND(CINDType::ROAM, roaming);
- bool service = false;
nsString regState;
voiceInfo->GetState(regState);
- if (regState.EqualsLiteral("registered")) {
- service = true;
+ bool service = regState.EqualsLiteral("registered");
+ if (service != sCINDItems[CINDType::SERVICE].value) {
+ // Notify BluetoothRilListener of service change
+ mListener->ServiceChanged(aClientId, service);
}
UpdateCIND(CINDType::SERVICE, service);
uint8_t signal;
JS::Value value;
voiceInfo->GetRelSignalStrength(&value);
if (!value.isNumber()) {
BT_WARNING("Failed to get relSignalStrength in BluetoothHfpManager");
@@ -625,18 +625,17 @@ BluetoothHfpManager::HandleVoiceConnecti
/**
* Possible return values for mode are:
* - null (unknown): set mNetworkSelectionMode to 0 (auto)
* - automatic: set mNetworkSelectionMode to 0 (auto)
* - manual: set mNetworkSelectionMode to 1 (manual)
*/
nsString mode;
- // TODO: Bug 921991 - B2G BT: support multiple sim cards
- connection->GetNetworkSelectionMode(0, mode);
+ connection->GetNetworkSelectionMode(aClientId, mode);
if (mode.EqualsLiteral("manual")) {
mNetworkSelectionMode = 1;
} else {
mNetworkSelectionMode = 0;
}
nsCOMPtr<nsIDOMMozMobileNetworkInfo> network;
voiceInfo->GetNetwork(getter_AddRefs(network));
@@ -653,25 +652,24 @@ BluetoothHfpManager::HandleVoiceConnecti
// Please see Bug 871366 for more information.
if (mOperatorName.Length() > 16) {
BT_WARNING("The operator name was longer than 16 characters. We cut it.");
mOperatorName.Left(mOperatorName, 16);
}
}
void
-BluetoothHfpManager::HandleIccInfoChanged()
+BluetoothHfpManager::HandleIccInfoChanged(uint32_t aClientId)
{
nsCOMPtr<nsIIccProvider> icc =
do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
NS_ENSURE_TRUE_VOID(icc);
nsCOMPtr<nsIDOMMozIccInfo> iccInfo;
- // TODO: Bug 921991 - B2G BT: support multiple sim cards
- icc->GetIccInfo(0, getter_AddRefs(iccInfo));
+ icc->GetIccInfo(aClientId, getter_AddRefs(iccInfo));
NS_ENSURE_TRUE_VOID(iccInfo);
nsCOMPtr<nsIDOMMozGsmIccInfo> gsmIccInfo = do_QueryInterface(iccInfo);
NS_ENSURE_TRUE_VOID(gsmIccInfo);
gsmIccInfo->GetMsisdn(mMsisdn);
}
#endif // MOZ_B2G_RIL
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -116,18 +116,18 @@ public:
#ifdef MOZ_B2G_RIL
/**
* @param aSend A boolean indicates whether we need to notify headset or not
*/
void HandleCallStateChanged(uint32_t aCallIndex, uint16_t aCallState,
const nsAString& aError, const nsAString& aNumber,
const bool aIsOutgoing, bool aSend);
- void HandleIccInfoChanged();
- void HandleVoiceConnectionChanged();
+ void HandleIccInfoChanged(uint32_t aClientId);
+ void HandleVoiceConnectionChanged(uint32_t aClientId);
#endif
bool IsConnected();
bool IsScoConnected();
#ifdef MOZ_B2G_RIL
// CDMA-specific functions
void UpdateSecondNumber(const nsAString& aNumber);
--- a/dom/bluetooth/BluetoothRilListener.cpp
+++ b/dom/bluetooth/BluetoothRilListener.cpp
@@ -2,46 +2,34 @@
/* 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 "BluetoothRilListener.h"
#include "BluetoothHfpManager.h"
-#include "nsIIccProvider.h"
-#include "nsIMobileConnectionProvider.h"
-#include "nsITelephonyProvider.h"
+#include "nsIDOMMobileConnection.h"
+#include "nsIRadioInterfaceLayer.h"
#include "nsRadioInterfaceLayer.h"
#include "nsServiceManagerUtils.h"
#include "nsString.h"
USING_BLUETOOTH_NAMESPACE
-namespace {
-
/**
* IccListener
*/
-class IccListener : public nsIIccListener
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIICCLISTENER
-
- IccListener() { }
-};
-
NS_IMPL_ISUPPORTS1(IccListener, nsIIccListener)
NS_IMETHODIMP
IccListener::NotifyIccInfoChanged()
{
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
- hfp->HandleIccInfoChanged();
+ hfp->HandleIccInfoChanged(mOwner->mClientId);
return NS_OK;
}
NS_IMETHODIMP
IccListener::NotifyStkCommand(const nsAString & aMessage)
{
return NS_OK;
@@ -54,35 +42,49 @@ IccListener::NotifyStkSessionEnd()
}
NS_IMETHODIMP
IccListener::NotifyCardStateChanged()
{
return NS_OK;
}
+bool
+IccListener::Listen(bool aStart)
+{
+ nsCOMPtr<nsIIccProvider> provider =
+ do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+ NS_ENSURE_TRUE(provider, false);
+
+ nsresult rv;
+ if (aStart) {
+ rv = provider->RegisterIccMsg(mOwner->mClientId, this);
+ } else {
+ rv = provider->UnregisterIccMsg(mOwner->mClientId, this);
+ }
+
+ return NS_SUCCEEDED(rv);
+}
+
+void
+IccListener::SetOwner(BluetoothRilListener *aOwner)
+{
+ mOwner = aOwner;
+}
+
/**
* MobileConnectionListener
*/
-class MobileConnectionListener : public nsIMobileConnectionListener
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIMOBILECONNECTIONLISTENER
-
- MobileConnectionListener() { }
-};
-
NS_IMPL_ISUPPORTS1(MobileConnectionListener, nsIMobileConnectionListener)
NS_IMETHODIMP
MobileConnectionListener::NotifyVoiceChanged()
{
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
- hfp->HandleVoiceConnectionChanged();
+ hfp->HandleVoiceConnectionChanged(mClientId);
return NS_OK;
}
NS_IMETHODIMP
MobileConnectionListener::NotifyDataChanged()
{
return NS_OK;
@@ -126,30 +128,36 @@ MobileConnectionListener::NotifyOtaStatu
}
NS_IMETHODIMP
MobileConnectionListener::NotifyIccChanged()
{
return NS_OK;
}
+bool
+MobileConnectionListener::Listen(bool aStart)
+{
+ nsCOMPtr<nsIMobileConnectionProvider> provider =
+ do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+ NS_ENSURE_TRUE(provider, false);
+
+ nsresult rv;
+ if (aStart) {
+ rv = provider->RegisterMobileConnectionMsg(mClientId, this);
+ } else {
+ rv = provider->UnregisterMobileConnectionMsg(mClientId, this);
+ }
+
+ return NS_SUCCEEDED(rv);
+}
+
/**
* TelephonyListener Implementation
- *
- * TODO: Bug 921991 - B2G BT: support multiple sim cards
*/
-class TelephonyListener : public nsITelephonyListener
-{
-public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSITELEPHONYLISTENER
-
- TelephonyListener() { }
-};
-
NS_IMPL_ISUPPORTS1(TelephonyListener, nsITelephonyListener)
NS_IMETHODIMP
TelephonyListener::CallStateChanged(uint32_t aServiceId,
uint32_t aCallIndex,
uint16_t aCallState,
const nsAString& aNumber,
bool aIsActive,
@@ -238,122 +246,149 @@ TelephonyListener::NotifyCdmaCallWaiting
const nsAString& aNumber)
{
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
hfp->UpdateSecondNumber(aNumber);
return NS_OK;
}
-} // anonymous namespace
+bool
+TelephonyListener::Listen(bool aStart)
+{
+ nsCOMPtr<nsITelephonyProvider> provider =
+ do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
+ NS_ENSURE_TRUE(provider, false);
+
+ nsresult rv;
+ if (aStart) {
+ rv = provider->RegisterListener(this);
+ } else {
+ rv = provider->UnregisterListener(this);
+ }
+
+ return NS_SUCCEEDED(rv);
+}
/**
* BluetoothRilListener
*/
BluetoothRilListener::BluetoothRilListener()
{
- mIccListener = new IccListener();
- mMobileConnectionListener = new MobileConnectionListener();
- mTelephonyListener = new TelephonyListener();
+ // Query number of total clients (sim slots)
+ uint32_t numOfClients;
+ nsCOMPtr<nsIRadioInterfaceLayer> radioInterfaceLayer =
+ do_GetService(NS_RADIOINTERFACELAYER_CONTRACTID);
+ NS_ENSURE_TRUE_VOID(radioInterfaceLayer);
+
+ radioInterfaceLayer->GetNumRadioInterfaces(&numOfClients);
+
+ // Init MobileConnectionListener array and IccInfoListener
+ for (uint32_t i = 0; i < numOfClients; i++) {
+ MobileConnectionListener listener(i);
+ mMobileConnListeners.AppendElement(listener);
+ }
+ mIccListener.SetOwner(this);
+
+ // Probe for available client
+ SelectClient();
}
bool
-BluetoothRilListener::StartListening()
+BluetoothRilListener::Listen(bool aStart)
{
- NS_ENSURE_TRUE(StartIccListening(), false);
- NS_ENSURE_TRUE(StartMobileConnectionListening(), false);
- NS_ENSURE_TRUE(StartTelephonyListening(), false);
+ NS_ENSURE_TRUE(ListenMobileConnAndIccInfo(aStart), false);
+ NS_ENSURE_TRUE(mTelephonyListener.Listen(aStart), false);
return true;
}
-bool
-BluetoothRilListener::StopListening()
+void
+BluetoothRilListener::SelectClient()
{
- NS_ENSURE_TRUE(StopIccListening(), false);
- NS_ENSURE_TRUE(StopMobileConnectionListening(), false);
- NS_ENSURE_TRUE(StopTelephonyListening(), false);
+ // Reset mClientId
+ mClientId = mMobileConnListeners.Length();
+
+ nsCOMPtr<nsIMobileConnectionProvider> connection =
+ do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+ NS_ENSURE_TRUE_VOID(connection);
+
+ uint32_t i;
+ for (i = 0; i < mMobileConnListeners.Length(); i++) {
+ nsCOMPtr<nsIDOMMozMobileConnectionInfo> voiceInfo;
+ connection->GetVoiceConnectionInfo(i, getter_AddRefs(voiceInfo));
+ if (!voiceInfo) {
+ BT_WARNING("%s: Failed to get voice connection info", __FUNCTION__);
+ continue;
+ }
- return true;
+ nsString regState;
+ voiceInfo->GetState(regState);
+ if (regState.EqualsLiteral("registered")) {
+ // Found available client
+ mClientId = i;
+ return;
+ }
+ }
+}
+
+void
+BluetoothRilListener::ServiceChanged(uint32_t aClientId, bool aRegistered)
+{
+ // Stop listening
+ ListenMobileConnAndIccInfo(false);
+
+ /**
+ * aRegistered:
+ * - TRUE: service becomes registered. We were listening to all clients
+ * and one of them becomes available. Select it to listen.
+ * - FALSE: service becomes un-registered. The client we were listening
+ * becomes unavailable. Select another registered one to listen.
+ */
+ if (aRegistered) {
+ mClientId = aClientId;
+ } else {
+ SelectClient();
+ }
+
+ // Restart listening
+ ListenMobileConnAndIccInfo(true);
+
+ BT_LOGR("%s: %d client %d. new mClientId %d", __FUNCTION__, aRegistered, aClientId,
+ (mClientId < mMobileConnListeners.Length()) ? mClientId : -1);
}
void
BluetoothRilListener::EnumerateCalls()
{
nsCOMPtr<nsITelephonyProvider> provider =
do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
NS_ENSURE_TRUE_VOID(provider);
- provider->EnumerateCalls(mTelephonyListener);
-}
-
-// private
-bool
-BluetoothRilListener::StartIccListening()
-{
- nsCOMPtr<nsIIccProvider> provider =
- do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
- NS_ENSURE_TRUE(provider, false);
+ nsCOMPtr<nsITelephonyListener> listener(
+ do_QueryInterface(&mTelephonyListener));
- // TODO: Bug 921991 - B2G BT: support multiple sim cards
- nsresult rv = provider->RegisterIccMsg(0, mIccListener);
- return NS_SUCCEEDED(rv);
-}
-
-bool
-BluetoothRilListener::StopIccListening()
-{
- nsCOMPtr<nsIIccProvider> provider =
- do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
- NS_ENSURE_TRUE(provider, false);
-
- // TODO: Bug 921991 - B2G BT: support multiple sim cards
- nsresult rv = provider->UnregisterIccMsg(0, mIccListener);
- return NS_SUCCEEDED(rv);
+ provider->EnumerateCalls(listener);
}
bool
-BluetoothRilListener::StartMobileConnectionListening()
+BluetoothRilListener::ListenMobileConnAndIccInfo(bool aStart)
{
- nsCOMPtr<nsIMobileConnectionProvider> provider =
- do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
- NS_ENSURE_TRUE(provider, false);
-
- // TODO: Bug 921991 - B2G BT: support multiple sim cards
- nsresult rv = provider->
- RegisterMobileConnectionMsg(0, mMobileConnectionListener);
- return NS_SUCCEEDED(rv);
-}
-
-bool
-BluetoothRilListener::StopMobileConnectionListening()
-{
- nsCOMPtr<nsIMobileConnectionProvider> provider =
- do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
- NS_ENSURE_TRUE(provider, false);
+ /**
+ * mClientId < number of total clients:
+ * The client with mClientId is available. Start/Stop listening
+ * mobile connection and icc info of this client only.
+ *
+ * mClientId >= number of total clients:
+ * All clients are unavailable. Start/Stop listening mobile
+ * connections of all clients.
+ */
+ if (mClientId < mMobileConnListeners.Length()) {
+ NS_ENSURE_TRUE(mMobileConnListeners[mClientId].Listen(aStart), false);
+ NS_ENSURE_TRUE(mIccListener.Listen(aStart), false);
+ } else {
+ for (uint32_t i = 0; i < mMobileConnListeners.Length(); i++) {
+ NS_ENSURE_TRUE(mMobileConnListeners[i].Listen(aStart), false);
+ }
+ }
- // TODO: Bug 921991 - B2G BT: support multiple sim cards
- nsresult rv = provider->
- UnregisterMobileConnectionMsg(0, mMobileConnectionListener);
- return NS_SUCCEEDED(rv);
+ return true;
}
-
-bool
-BluetoothRilListener::StartTelephonyListening()
-{
- nsCOMPtr<nsITelephonyProvider> provider =
- do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
- NS_ENSURE_TRUE(provider, false);
-
- nsresult rv = provider->RegisterListener(mTelephonyListener);
- return NS_SUCCEEDED(rv);
-}
-
-bool
-BluetoothRilListener::StopTelephonyListening()
-{
- nsCOMPtr<nsITelephonyProvider> provider =
- do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
- NS_ENSURE_TRUE(provider, false);
-
- nsresult rv = provider->UnregisterListener(mTelephonyListener);
- return NS_SUCCEEDED(rv);
-}
--- a/dom/bluetooth/BluetoothRilListener.h
+++ b/dom/bluetooth/BluetoothRilListener.h
@@ -4,44 +4,121 @@
* 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_bluetoothrillistener_h__
#define mozilla_dom_bluetooth_bluetoothrillistener_h__
#include "BluetoothCommon.h"
-#include "nsCOMPtr.h"
-
-class nsIIccListener;
-class nsIMobileConnectionListener;
-class nsITelephonyListener;
+#include "nsIIccProvider.h"
+#include "nsIMobileConnectionProvider.h"
+#include "nsITelephonyProvider.h"
BEGIN_BLUETOOTH_NAMESPACE
+class BluetoothRilListener;
+
+class IccListener : public nsIIccListener
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIICCLISTENER
+
+ IccListener() { }
+
+ bool Listen(bool aStart);
+ void SetOwner(BluetoothRilListener *aOwner);
+
+private:
+ BluetoothRilListener* mOwner;
+};
+
+class MobileConnectionListener : public nsIMobileConnectionListener
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIMOBILECONNECTIONLISTENER
+
+ MobileConnectionListener(uint32_t aClientId)
+ : mClientId(aClientId) { }
+
+ bool Listen(bool aStart);
+
+private:
+ uint32_t mClientId;
+};
+
+class TelephonyListener : public nsITelephonyListener
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSITELEPHONYLISTENER
+
+ TelephonyListener() { }
+
+ bool Listen(bool aStart);
+};
+
class BluetoothRilListener
{
public:
BluetoothRilListener();
- bool StartListening();
- bool StopListening();
+ /**
+ * Start/Stop listening.
+ *
+ * @param aStart [in] whether to start/stop listening
+ */
+ bool Listen(bool aStart);
+ /**
+ * Be informed that certain client's service has changed.
+ *
+ * @param aClientId [in] the client id with service change
+ * @param aRegistered [in] whether changed service is registered
+ */
+ void ServiceChanged(uint32_t aClientId, bool aRegistered);
+
+ /**
+ * Enumerate current calls.
+ */
void EnumerateCalls();
+ /**
+ * The id of client that mobile connection and icc info listeners
+ * are listening to.
+ *
+ * mClientId equals to number of total clients (array length of
+ * mobile connection listeners) if there is no available client to listen.
+ */
+ uint32_t mClientId;
+
private:
- bool StartIccListening();
- bool StopIccListening();
-
- bool StartMobileConnectionListening();
- bool StopMobileConnectionListening();
+ /**
+ * Start/Stop listening of mobile connection and icc info.
+ *
+ * @param aStart [in] whether to start/stop listening
+ */
+ bool ListenMobileConnAndIccInfo(bool aStart);
- bool StartTelephonyListening();
- bool StopTelephonyListening();
+ /**
+ * Select available client to listen and assign mClientId.
+ *
+ * mClientId is assigned to number of total clients (array length of
+ * mobile connection listeners) if there is no available client to listen.
+ */
+ void SelectClient();
- nsCOMPtr<nsIIccListener> mIccListener;
- nsCOMPtr<nsIMobileConnectionListener> mMobileConnectionListener;
- nsCOMPtr<nsITelephonyListener> mTelephonyListener;
+ /**
+ * Array of mobile connection listeners.
+ *
+ * The length equals to number of total clients.
+ */
+ nsTArray<MobileConnectionListener> mMobileConnListeners;
+
+ IccListener mIccListener;
+ TelephonyListener mTelephonyListener;
};
END_BLUETOOTH_NAMESPACE
#endif
--- a/dom/system/gonk/nsRadioInterfaceLayer.h
+++ b/dom/system/gonk/nsRadioInterfaceLayer.h
@@ -6,9 +6,11 @@
#define NS_RADIOINTERFACELAYER_CID \
{ 0x2d831c8d, 0x6017, 0x435b, \
{ 0xa8, 0x0c, 0xe5, 0xd4, 0x22, 0x81, 0x0c, 0xea } }
#define NS_RILCONTENTHELPER_CID \
{ 0x472816e1, 0x1fd6, 0x4405, \
{ 0x99, 0x6c, 0x80, 0x6f, 0x9e, 0xa6, 0x81, 0x74 } }
+
+#define NS_RADIOINTERFACELAYER_CONTRACTID "@mozilla.org/ril;1"
#define NS_RILCONTENTHELPER_CONTRACTID "@mozilla.org/ril/content-helper;1"