Bug 945149 - No event AdapterAdded is received after turning on Bluetooth, r=echou
authorGina Yeh <gyeh@mozilla.com>
Wed, 04 Dec 2013 10:18:33 +0800
changeset 174388 263f538a5509495d75c5f4e23b61bf0ed8d11b06
parent 174375 d997913037df89a04960346a36de1860425d6458
child 174389 fd1c6a12ab0b79ebf8a20cad2d72228a5e1e2292
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechou
bugs945149
milestone28.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 945149 - No event AdapterAdded is received after turning on Bluetooth, r=echou
dom/bluetooth/bluez/linux/BluetoothDBusService.cpp
--- a/dom/bluetooth/bluez/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/bluez/linux/BluetoothDBusService.cpp
@@ -41,16 +41,17 @@
 #include "mozilla/ipc/UnixSocket.h"
 #include "mozilla/ipc/DBusThread.h"
 #include "mozilla/ipc/DBusUtils.h"
 #include "mozilla/ipc/RawDBusConnection.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/NullPtr.h"
 #include "mozilla/StaticMutex.h"
 #include "mozilla/Util.h"
+
 #if defined(MOZ_WIDGET_GONK)
 #include "cutils/properties.h"
 #endif
 
 /**
  * Some rules for dealing with memory in DBus:
  * - A DBusError only needs to be deleted if it's been set, not just
  *   initialized. This is why LOG_AND_FREE... is called only when an error is
@@ -166,23 +167,42 @@ static const char* sBluetoothDBusSignals
   "type='signal',interface='org.bluez.Control'"
 };
 
 /**
  * DBus Connection held for the BluetoothCommandThread to use. Should never be
  * used by any other thread.
  */
 static nsRefPtr<RawDBusConnection> gThreadConnection;
-static nsDataHashtable<nsStringHashKey, DBusMessage* >* sPairingReqTable;
+
+// Only A2DP and HID are authorized.
 static nsTArray<uint32_t> sAuthorizedServiceClass;
+
+// The object path of adpater which should be updated after switching Bluetooth.
 static nsString sAdapterPath;
+
+/**
+ * The adapter name may not be ready whenever event 'AdapterAdded' is received,
+ * so we'd like to wait for a bit.
+ */
 static bool sAdapterNameIsReady = false;
+static int sWaitingForAdapterNameInterval = 1000; //unit: ms
+
+// Keep the pairing requests.
 static Atomic<int32_t> sIsPairing(0);
+static nsDataHashtable<nsStringHashKey, DBusMessage* >* sPairingReqTable;
+
+/**
+ * Disconnect all profiles before turning off Bluetooth. Please see Bug 891257
+ * for more details.
+ */
 static int sConnectedDeviceCount = 0;
 static StaticAutoPtr<Monitor> sStopBluetoothMonitor;
+
+// A quene for connect/disconnect request. See Bug 913372 for details.
 static nsTArray<nsRefPtr<BluetoothProfileController> > sControllerArray;
 
 typedef void (*UnpackFunc)(DBusMessage*, DBusError*, BluetoothValue&, nsAString&);
 typedef bool (*FilterFunc)(const BluetoothValue&);
 
 BluetoothDBusService::BluetoothDBusService()
 {
   sStopBluetoothMonitor = new Monitor("BluetoothService.sStopBluetoothMonitor");
@@ -330,32 +350,56 @@ public:
     hid->HandleInputPropertyChanged(mSignal);
     return NS_OK;
   }
 
 private:
   BluetoothSignal mSignal;
 };
 
-class TryFiringAdapterAddedTask : public nsRunnable
+class TryFiringAdapterAddedTask : public Task
 {
 public:
-  NS_IMETHOD
-  Run()
+  void Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     BluetoothService* bs = BluetoothService::Get();
-    NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
+    NS_ENSURE_TRUE_VOID(bs);
 
     bs->AdapterAddedReceived();
     bs->TryFiringAdapterAdded();
+  }
+};
+
+class TryFiringAdapterAddedRunnable : public nsRunnable
+{
+public:
+  TryFiringAdapterAddedRunnable(bool aDelay)
+    : mDelay(aDelay)
+  { }
+
+  nsresult Run()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    if (mDelay) {
+      MessageLoop::current()->
+        PostDelayedTask(FROM_HERE, new TryFiringAdapterAddedTask(),
+                        sWaitingForAdapterNameInterval);
+    } else {
+      MessageLoop::current()->
+        PostTask(FROM_HERE, new TryFiringAdapterAddedTask());
+    }
 
     return NS_OK;
   }
+
+private:
+  bool mDelay;
 };
 
 static bool
 IsDBusMessageError(DBusMessage* aMsg, DBusError* aErr, nsAString& aErrorStr)
 {
   if (aErr && dbus_error_is_set(aErr)) {
     aErrorStr = NS_ConvertUTF8toUTF16(aErr->message);
     LOG_AND_FREE_DBUS_ERROR(aErr);
@@ -722,17 +766,17 @@ GetProperty(DBusMessageIter aIter, Prope
   } else if (!sAdapterNameIsReady &&
              aPropertyTypes == sAdapterProperties &&
              propertyName.EqualsLiteral("Name")) {
     MOZ_ASSERT(propertyValue.type() == BluetoothValue::TnsString);
 
     // Notify BluetoothManager whenever adapter name is ready.
     if (!propertyValue.get_nsString().IsEmpty()) {
       sAdapterNameIsReady = true;
-      NS_DispatchToMainThread(new TryFiringAdapterAddedTask());
+      NS_DispatchToMainThread(new TryFiringAdapterAddedRunnable(false));
     }
   }
 
   aProperties.AppendElement(BluetoothNamedValue(propertyName, propertyValue));
   return true;
 }
 
 static void
@@ -1300,16 +1344,18 @@ class PrepareAdapterRunnable : public ns
 {
 public:
   PrepareAdapterRunnable(const nsAString& aAdapterPath)
     : mAdapterPath(aAdapterPath)
   { }
 
   NS_IMETHOD Run()
   {
+    MOZ_ASSERT(NS_IsMainThread());
+
     static const dbus_uint32_t sServices[] = {
       BluetoothServiceClass::HANDSFREE_AG,
       BluetoothServiceClass::HEADSET_AG,
       BluetoothServiceClass::OBJECT_PUSH
     };
 
     MOZ_ASSERT(NS_IsMainThread());
 
@@ -1571,16 +1617,17 @@ EventFilter(DBusConnection* aConn, DBusM
     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!");
     } else {
       v = NS_ConvertUTF8toUTF16(str);
+      NS_DispatchToMainThread(new TryFiringAdapterAddedRunnable(true));
       NS_DispatchToMainThread(new PrepareAdapterRunnable(v.get_nsString()));
 
       /**
        * The adapter name isn't ready for the time being. Wait for the upcoming
        * signal PropertyChanged of adapter name, and then propagate signal
        * AdapterAdded to BluetoothManager.
        */
       return DBUS_HANDLER_RESULT_HANDLED;