Bug 853221 - Patch 1: Distribute connection/pair status to BluetoothAdapter, r=echou
authorGina Yeh <gyeh@mozilla.com>
Fri, 02 Aug 2013 18:32:57 +0800
changeset 141182 989eeb2e71fffaeea5c8763ec918a5d66afb45ea
parent 141124 73dcf35e07cf2e2a3b2e76c3985a9c78093181bf
child 141183 cf744991c7e07ce67400c03b14e3a0c681aac460
push id32011
push userryanvm@gmail.com
push dateFri, 02 Aug 2013 20:55:05 +0000
treeherdermozilla-inbound@d2ce76654a6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechou
bugs853221
milestone25.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
Bug 853221 - Patch 1: Distribute connection/pair status to BluetoothAdapter, r=echou
dom/bluetooth/BluetoothA2dpManager.cpp
dom/bluetooth/BluetoothA2dpManager.h
dom/bluetooth/BluetoothCommon.h
dom/bluetooth/BluetoothHfpManager.cpp
dom/bluetooth/BluetoothHfpManager.h
dom/bluetooth/BluetoothService.cpp
dom/bluetooth/BluetoothUtils.cpp
dom/bluetooth/BluetoothUtils.h
dom/bluetooth/linux/BluetoothDBusService.cpp
--- a/dom/bluetooth/BluetoothA2dpManager.cpp
+++ b/dom/bluetooth/BluetoothA2dpManager.cpp
@@ -199,17 +199,18 @@ BluetoothA2dpManager::HandleSinkProperty
   MOZ_ASSERT(arr.Length() == 1);
 
   const nsString& name = arr[0].name();
   const BluetoothValue& value = arr[0].value();
   if (name.EqualsLiteral("Connected")) {
     // Indicates if a stream is setup to a A2DP sink on the remote device.
     MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
     mA2dpConnected = value.get_bool();
-    NotifyStatusChanged();
+    NotifyConnectionStatusChanged();
+    DispatchConnectionStatusChanged();
   } else if (name.EqualsLiteral("Playing")) {
     // Indicates if a stream is active to a A2DP sink on the remote device.
     MOZ_ASSERT(value.type() == BluetoothValue::Tbool);
     mPlaying = value.get_bool();
   } else if (name.EqualsLiteral("State")) {
     MOZ_ASSERT(value.type() == BluetoothValue::TnsString);
     HandleSinkStateChanged(StatusStringToSinkState(value.get_nsString()));
   } else {
@@ -249,17 +250,26 @@ BluetoothA2dpManager::HandleSinkStateCha
   if (aState == SinkState::SINK_DISCONNECTED) {
     mDeviceAddress.Truncate();
   }
 
   mSinkState = aState;
 }
 
 void
-BluetoothA2dpManager::NotifyStatusChanged()
+BluetoothA2dpManager::DispatchConnectionStatusChanged()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  DispatchStatusChangedEvent(
+    NS_LITERAL_STRING(A2DP_STATUS_CHANGED_ID), mDeviceAddress, mA2dpConnected);
+}
+
+void
+BluetoothA2dpManager::NotifyConnectionStatusChanged()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Broadcast system message to Gaia
   NS_NAMED_LITERAL_STRING(type, BLUETOOTH_A2DP_STATUS_CHANGED_ID);
   InfallibleTArray<BluetoothNamedValue> parameters;
 
   BluetoothValue v = mA2dpConnected;
--- a/dom/bluetooth/BluetoothA2dpManager.h
+++ b/dom/bluetooth/BluetoothA2dpManager.h
@@ -67,22 +67,24 @@ public:
 
 private:
   BluetoothA2dpManager();
   bool Init();
 
   void HandleSinkStateChanged(SinkState aState);
   void HandleShutdown();
 
-  void NotifyStatusChanged();
+  void DispatchConnectionStatusChanged();
+  void NotifyConnectionStatusChanged();
+
+  nsString mDeviceAddress;
 
   // A2DP data member
   bool mA2dpConnected;
   bool mPlaying;
-  nsString mDeviceAddress;
   SinkState mSinkState;
 
   // AVRCP data member
   bool mAvrcpConnected;
   nsString mAlbum;
   nsString mArtist;
   nsString mTitle;
   uint32_t mDuration;
--- a/dom/bluetooth/BluetoothCommon.h
+++ b/dom/bluetooth/BluetoothCommon.h
@@ -47,22 +47,36 @@ extern bool gBluetoothDebugFlag;
   using namespace mozilla::dom::bluetooth;
 
 #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"
 
 /**
- * When connection status of Bluetooth profiles change, we'll notify observers
- * of following topics.
+ * When the connection status of a Bluetooth profile is changed, we'll notify
+ * observers which register the following topics.
  */
-#define BLUETOOTH_HFP_STATUS_CHANGED_ID      "bluetooth-hfp-status-changed"
-#define BLUETOOTH_SCO_STATUS_CHANGED_ID      "bluetooth-sco-status-changed"
-#define BLUETOOTH_A2DP_STATUS_CHANGED_ID     "bluetooth-a2dp-status-changed"
+#define BLUETOOTH_A2DP_STATUS_CHANGED_ID "bluetooth-a2dp-status-changed"
+#define BLUETOOTH_HFP_STATUS_CHANGED_ID  "bluetooth-hfp-status-changed"
+#define BLUETOOTH_SCO_STATUS_CHANGED_ID  "bluetooth-sco-status-changed"
+
+/**
+ * When the connection status of a Bluetooth profile is changed, we'll
+ * distribute one of the following events.
+ */
+#define A2DP_STATUS_CHANGED_ID               "a2dpstatuschanged"
+#define HFP_STATUS_CHANGED_ID                "hfpstatuschanged"
+#define SCO_STATUS_CHANGED_ID                "scostatuschanged"
+
+/**
+ * When the pair status of a Bluetooth device is changed, we'll distribute an
+ * event.
+ */
+#define PAIRED_STATUS_CHANGED_ID             "pairedstatuschanged"
 
 // 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 {
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -449,50 +449,67 @@ BluetoothHfpManager::Get()
   BluetoothHfpManager* manager = new BluetoothHfpManager();
   NS_ENSURE_TRUE(manager->Init(), nullptr);
 
   sBluetoothHfpManager = manager;
   return sBluetoothHfpManager;
 }
 
 void
-BluetoothHfpManager::NotifyStatusChanged(const char* aType)
+BluetoothHfpManager::DispatchConnectionStatusChanged(const nsAString& aType)
 {
-  // Broadcast system message to Gaia
+  MOZ_ASSERT(NS_IsMainThread());
+
+  bool status = false;
+  if (aType.EqualsLiteral(HFP_STATUS_CHANGED_ID)) {
+    status = IsConnected();
+  } else if (aType.EqualsLiteral(SCO_STATUS_CHANGED_ID)) {
+    status = IsScoConnected();
+  } else {
+    BT_WARNING("Wrong type for DispatchConnectionStatusChanged");
+    return;
+  }
+
+  DispatchStatusChangedEvent(aType, mDeviceAddress, status);
+}
+
+void
+BluetoothHfpManager::NotifyConnectionStatusChanged(const nsAString& aType)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
   BluetoothValue v;
   InfallibleTArray<BluetoothNamedValue> parameters;
-  nsAutoString type, name;
-  type = NS_ConvertUTF8toUTF16(aType);
-  name.AssignLiteral("connected");
-
-  if (type.EqualsLiteral(BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
+  nsString name = NS_LITERAL_STRING("connected");
+  if (aType.EqualsLiteral(BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
     v = IsConnected();
-  } else if (type.EqualsLiteral(BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
+  } else if (aType.EqualsLiteral(BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
     v = IsScoConnected();
   } else {
-    NS_WARNING("Wrong type for NotifyStatusChanged");
+    BT_WARNING("Wrong type for NotifyConnectionStatusChanged");
     return;
   }
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
   name.AssignLiteral("address");
   v = mDeviceAddress;
   parameters.AppendElement(BluetoothNamedValue(name, v));
 
-  if (!BroadcastSystemMessage(type, parameters)) {
+  if (!BroadcastSystemMessage(aType, parameters)) {
     NS_WARNING("Failed to broadcast system message to settings");
   }
 
   // Notify Gecko observers
   nsCOMPtr<nsIObserverService> obs =
     do_GetService("@mozilla.org/observer-service;1");
   NS_ENSURE_TRUE_VOID(obs);
 
-  if (NS_FAILED(obs->NotifyObservers(this, aType, mDeviceAddress.get()))) {
-    NS_WARNING("Failed to notify bluetooth-sco-status-changed observsers!");
+  if (NS_FAILED(obs->NotifyObservers(this, NS_ConvertUTF16toUTF8(aType).get(),
+                                     mDeviceAddress.get()))) {
+    NS_WARNING("Failed to notify observsers!");
   }
 }
 
 void
 BluetoothHfpManager::NotifyDialer(const nsAString& aCommand)
 {
   nsString type, name;
   BluetoothValue v;
@@ -1477,17 +1494,18 @@ BluetoothHfpManager::OnConnectSuccess(Bl
     mRunnable = nullptr;
   }
 
   mFirstCKPD = true;
 
   // Cache device path for NotifySettings() since we can't get socket address
   // when a headset disconnect with us
   mSocket->GetAddress(mDeviceAddress);
-  NotifyStatusChanged(BLUETOOTH_HFP_STATUS_CHANGED_ID);
+  NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
+  DispatchConnectionStatusChanged(NS_LITERAL_STRING(HFP_STATUS_CHANGED_ID));
 
   ListenSco();
 
   BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
   NS_ENSURE_TRUE_VOID(a2dp);
   a2dp->Connect(mDeviceAddress);
 }
 
@@ -1532,17 +1550,18 @@ BluetoothHfpManager::OnDisconnect(Blueto
     // Do nothing when a listening server socket is closed.
     return;
   }
 
   mSocket = nullptr;
   DisconnectSco();
 
   Listen();
-  NotifyStatusChanged(BLUETOOTH_HFP_STATUS_CHANGED_ID);
+  NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
+  DispatchConnectionStatusChanged(NS_LITERAL_STRING(HFP_STATUS_CHANGED_ID));
   Reset();
 }
 
 void
 BluetoothHfpManager::OnUpdateSdpRecords(const nsAString& aDeviceAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!aDeviceAddress.IsEmpty());
@@ -1612,17 +1631,18 @@ BluetoothHfpManager::OnScoConnectSuccess
 {
   // For active connection request, we need to reply the DOMRequest
   if (mScoRunnable) {
     DispatchBluetoothReply(mScoRunnable,
                            BluetoothValue(true), EmptyString());
     mScoRunnable = nullptr;
   }
 
-  NotifyStatusChanged(BLUETOOTH_SCO_STATUS_CHANGED_ID);
+  NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_SCO_STATUS_CHANGED_ID));
+  DispatchConnectionStatusChanged(NS_LITERAL_STRING(SCO_STATUS_CHANGED_ID));
 
   mScoSocketStatus = mScoSocket->GetConnectionStatus();
 }
 
 void
 BluetoothHfpManager::OnScoConnectError()
 {
   if (mScoRunnable) {
@@ -1635,17 +1655,18 @@ BluetoothHfpManager::OnScoConnectError()
   ListenSco();
 }
 
 void
 BluetoothHfpManager::OnScoDisconnect()
 {
   if (mScoSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
     ListenSco();
-    NotifyStatusChanged(BLUETOOTH_SCO_STATUS_CHANGED_ID);
+    NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_SCO_STATUS_CHANGED_ID));
+    DispatchConnectionStatusChanged(NS_LITERAL_STRING(SCO_STATUS_CHANGED_ID));
   }
 }
 
 bool
 BluetoothHfpManager::IsConnected()
 {
   if (mSocket) {
     return mSocket->GetConnectionStatus() ==
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -112,18 +112,19 @@ private:
 
   bool Init();
   void Notify(const hal::BatteryInformation& aBatteryInfo);
   void Reset();
   void ResetCallArray();
   uint32_t FindFirstCall(uint16_t aState);
   uint32_t GetNumberOfCalls(uint16_t aState);
 
+  void DispatchConnectionStatusChanged(const nsAString& aType);
   void NotifyDialer(const nsAString& aCommand);
-  void NotifyStatusChanged(const char* aType);
+  void NotifyConnectionStatusChanged(const nsAString& aType);
 
   bool SendCommand(const char* aCommand, uint32_t aValue = 0);
   bool SendLine(const char* aMessage);
   void UpdateCIND(uint8_t aType, uint8_t aValue, bool aSend = true);
   void OnScoConnectSuccess();
   void OnScoConnectError();
   void OnScoDisconnect();
 
--- a/dom/bluetooth/BluetoothService.cpp
+++ b/dom/bluetooth/BluetoothService.cpp
@@ -783,19 +783,19 @@ BluetoothService::Notify(const Bluetooth
   } else if (aData.name().EqualsLiteral("Authorize")) {
     MOZ_ASSERT(aData.value().get_ArrayOfBluetoothNamedValue().Length() == 2,
       "Authorize: Wrong length of parameters");
     type.AssignLiteral("bluetooth-authorize");
   } else if (aData.name().EqualsLiteral("Cancel")) {
     MOZ_ASSERT(aData.value().get_ArrayOfBluetoothNamedValue().Length() == 0,
       "Cancel: Wrong length of parameters");
     type.AssignLiteral("bluetooth-cancel");
-  } else if (aData.name().EqualsLiteral("PairedStatusChanged")) {
+  } else if (aData.name().EqualsLiteral(PAIRED_STATUS_CHANGED_ID)) {
     MOZ_ASSERT(aData.value().get_ArrayOfBluetoothNamedValue().Length() == 1,
-      "PairedStatusChagned: Wrong length of parameters");
+      "pairedstatuschanged: Wrong length of parameters");
     type.AssignLiteral("bluetooth-pairedstatuschanged");
   } else {
     nsCString warningMsg;
     warningMsg.AssignLiteral("Not handling service signal: ");
     warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
     NS_WARNING(warningMsg.get());
     return;
   }
--- a/dom/bluetooth/BluetoothUtils.cpp
+++ b/dom/bluetooth/BluetoothUtils.cpp
@@ -2,16 +2,17 @@
 /* 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 "base/basictypes.h"
 
 #include "BluetoothReplyRunnable.h"
+#include "BluetoothService.h"
 #include "BluetoothUtils.h"
 #include "jsapi.h"
 #include "mozilla/Scoped.h"
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 #include "nsIScriptContext.h"
 #include "nsISystemMessagesInternal.h"
@@ -168,9 +169,29 @@ ParseAtCommand(const nsACString& aAtComm
       begin = i + 1;
     }
   }
 
   nsCString tmp(nsDependentCSubstring(aAtCommand, begin));
   aRetValues.AppendElement(tmp);
 }
 
+void
+DispatchStatusChangedEvent(const nsAString& aType,
+                           const nsAString& aAddress,
+                           bool aStatus)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  InfallibleTArray<BluetoothNamedValue> data;
+  data.AppendElement(
+    BluetoothNamedValue(NS_LITERAL_STRING("address"), nsString(aAddress)));
+  data.AppendElement(
+    BluetoothNamedValue(NS_LITERAL_STRING("status"), aStatus));
+
+  BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data);
+
+  BluetoothService* bs = BluetoothService::Get();
+  NS_ENSURE_TRUE_VOID(bs);
+  bs->DistributeSignal(signal);
+}
+
 END_BLUETOOTH_NAMESPACE
--- a/dom/bluetooth/BluetoothUtils.h
+++ b/dom/bluetooth/BluetoothUtils.h
@@ -38,11 +38,16 @@ void
 DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
                        const BluetoothValue& aValue,
                        const nsAString& aErrorStr);
 
 void
 ParseAtCommand(const nsACString& aAtCommand, const int aStart,
                nsTArray<nsCString>& aRetValues);
 
+void
+DispatchStatusChangedEvent(const nsAString& aType,
+                           const nsAString& aDeviceAddress,
+                           bool aStatus);
+
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -462,16 +462,18 @@ GetIntCallback(DBusMessage* aMsg, void* 
   RunDBusCallback(aMsg, aBluetoothReplyRunnable,
                   UnpackIntMessage);
 }
 
 #ifdef DEBUG
 static void
 CheckForError(DBusMessage* aMsg, void *aParam, const nsAString& aError)
 {
+  NS_ENSURE_TRUE_VOID(aMsg);
+
   BluetoothValue v;
   nsAutoString replyError;
   UnpackVoidMessage(aMsg, nullptr, v, replyError);
   if (!v.get_bool()) {
     BT_WARNING(NS_ConvertUTF16toUTF8(aError).get());
   }
 }
 #endif
@@ -1479,26 +1481,37 @@ EventFilter(DBusConnection* aConn, DBusM
   } else if (dbus_message_is_signal(aMsg, DBUS_DEVICE_IFACE,
                                     "PropertyChanged")) {
     ParsePropertyChange(aMsg,
                         v,
                         errorStr,
                         sDeviceProperties,
                         ArrayLength(sDeviceProperties));
 
-    // Fire another task for sending system message of
-    // "bluetooth-pairedstatuschanged"
     BluetoothNamedValue& property = v.get_ArrayOfBluetoothNamedValue()[0];
     if (property.name().EqualsLiteral("Paired")) {
+      // Original approach: Broadcast system message of
+      // "bluetooth-pairedstatuschanged" from BluetoothService.
       BluetoothValue newValue(v);
       ToLowerCase(newValue.get_ArrayOfBluetoothNamedValue()[0].name());
-      BluetoothSignal signal(NS_LITERAL_STRING("PairedStatusChanged"),
+      BluetoothSignal signal(NS_LITERAL_STRING(PAIRED_STATUS_CHANGED_ID),
                              NS_LITERAL_STRING(KEY_LOCAL_AGENT),
                              newValue);
       NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
+
+      // New approach: Dispatch event from BluetoothAdapter
+      bool status = property.value();
+      InfallibleTArray<BluetoothNamedValue> parameters;
+      parameters.AppendElement(
+        BluetoothNamedValue(NS_LITERAL_STRING("address"), signalPath));
+      parameters.AppendElement(
+        BluetoothNamedValue(NS_LITERAL_STRING("status"), status));
+      signal.path() = NS_LITERAL_STRING(KEY_ADAPTER);
+      signal.value() = parameters;
+      NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
     }
   } else if (dbus_message_is_signal(aMsg, DBUS_MANAGER_IFACE, "AdapterAdded")) {
     const char* str;
     if (!dbus_message_get_args(aMsg, &err,
                                DBUS_TYPE_OBJECT_PATH, &str,
                                DBUS_TYPE_INVALID)) {
       LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, aMsg);
       errorStr.AssignLiteral("Cannot parse manager path!");