Bug 976943 - Add error handing for connect/disconnect process, f=btian, r=gyeh
authorEric Chou <echou@mozilla.com>
Thu, 06 Mar 2014 19:26:22 +0800
changeset 172676 98e130e325dfe411e906984db0a2950516513b09
parent 172675 819313d5459a2343ba1815390bf4568136bab8c4
child 172677 9f916baff01af08d2f4f0b22b29e7ae6921624f1
push id271
push userpvanderbeken@mozilla.com
push dateMon, 24 Mar 2014 22:43:42 +0000
reviewersgyeh
bugs976943
milestone30.0a1
Bug 976943 - Add error handing for connect/disconnect process, f=btian, r=gyeh
dom/bluetooth/BluetoothProfileController.cpp
dom/bluetooth/BluetoothProfileController.h
dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
dom/bluetooth/bluez/BluetoothDBusService.cpp
--- a/dom/bluetooth/BluetoothProfileController.cpp
+++ b/dom/bluetooth/BluetoothProfileController.cpp
@@ -206,126 +206,129 @@ CheckProfileStatusCallback::Notify(nsITi
   // Continue on the next profile since we haven't got the callback after
   // timeout.
   mController->GiveupAndContinue();
 
   return NS_OK;
 }
 
 void
-BluetoothProfileController::Start()
+BluetoothProfileController::StartSession()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mDeviceAddress.IsEmpty());
   MOZ_ASSERT(mProfilesIndex == -1);
   MOZ_ASSERT(mTimer);
-  NS_ENSURE_TRUE_VOID(mProfiles.Length() > 0);
 
-  ++mProfilesIndex;
-  BT_LOGR_PROFILE(mProfiles[mProfilesIndex], "");
+  if (mProfiles.Length() < 1) {
+    BT_LOGR("No queued profile.");
+    EndSession();
+    return;
+  }
 
   if (mTimer) {
     mTimer->InitWithCallback(mCheckProfileStatusCallback, CONNECTION_TIMEOUT_MS,
                              nsITimer::TYPE_ONE_SHOT);
   }
 
-  if (mConnect) {
-    mProfiles[mProfilesIndex]->Connect(mDeviceAddress, this);
+  BT_LOGR("%s", mConnect ? "connecting" : "disconnecting");
+
+  Next();
+}
+
+void
+BluetoothProfileController::EndSession()
+{
+  MOZ_ASSERT(mRunnable && mCallback);
+
+  BT_LOGR("mSuccess %d", mSuccess);
+
+  // The action has completed, so the DOM request should be replied then invoke
+  // the callback.
+  if (mSuccess) {
+    DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
+  } else if (mConnect) {
+    DispatchBluetoothReply(mRunnable, BluetoothValue(true),
+                           NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
   } else {
-    mProfiles[mProfilesIndex]->Disconnect(this);
+    DispatchBluetoothReply(mRunnable, BluetoothValue(true),
+                           NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
   }
+
+  mCallback();
 }
 
 void
 BluetoothProfileController::Next()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mDeviceAddress.IsEmpty());
   MOZ_ASSERT(mProfilesIndex < (int)mProfiles.Length());
   MOZ_ASSERT(mTimer);
 
   mCurrentProfileFinished = false;
-  if (++mProfilesIndex < (int)mProfiles.Length()) {
-    BT_LOGR_PROFILE(mProfiles[mProfilesIndex], "");
 
-    if (mTimer) {
-      mTimer->InitWithCallback(mCheckProfileStatusCallback,
-                               CONNECTION_TIMEOUT_MS,
-                               nsITimer::TYPE_ONE_SHOT);
-    }
-
-    if (mConnect) {
-      mProfiles[mProfilesIndex]->Connect(mDeviceAddress, this);
-    } else {
-      mProfiles[mProfilesIndex]->Disconnect(this);
-    }
+  if (++mProfilesIndex >= (int)mProfiles.Length()) {
+    EndSession();
     return;
   }
 
-  MOZ_ASSERT(mRunnable && mCallback);
+  BT_LOGR_PROFILE(mProfiles[mProfilesIndex], "");
 
-  // The action has been completed, so the dom request is replied and then
-  // the callback is invoked
-  if (mSuccess) {
-    DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
+  if (mConnect) {
+    mProfiles[mProfilesIndex]->Connect(mDeviceAddress, this);
   } else {
-    DispatchBluetoothReply(mRunnable, BluetoothValue(),
-                           NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
+    mProfiles[mProfilesIndex]->Disconnect(this);
   }
-  mCallback();
 }
 
 void
 BluetoothProfileController::OnConnect(const nsAString& aErrorStr)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mTimer);
 
   BT_LOGR_PROFILE(mProfiles[mProfilesIndex], "<%s>",
-    NS_ConvertUTF16toUTF8(aErrorStr).get());
+                  NS_ConvertUTF16toUTF8(aErrorStr).get());
 
   mCurrentProfileFinished = true;
+
   if (mTimer) {
     mTimer->Cancel();
   }
 
-  if (!aErrorStr.IsEmpty()) {
-    BT_WARNING(NS_ConvertUTF16toUTF8(aErrorStr).get());
-  } else {
-    mSuccess = true;
-  }
+  mSuccess |= aErrorStr.IsEmpty();
 
   Next();
 }
 
 void
 BluetoothProfileController::OnDisconnect(const nsAString& aErrorStr)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mTimer);
+  MOZ_ASSERT(mProfiles.Length() > 0);
 
   BT_LOGR_PROFILE(mProfiles[mProfilesIndex], "<%s>",
-    NS_ConvertUTF16toUTF8(aErrorStr).get());
+                  NS_ConvertUTF16toUTF8(aErrorStr).get());
 
   mCurrentProfileFinished = true;
+
   if (mTimer) {
     mTimer->Cancel();
   }
 
-  if (!aErrorStr.IsEmpty()) {
-    BT_WARNING(NS_ConvertUTF16toUTF8(aErrorStr).get());
-  } else {
-    mSuccess = true;
-  }
+  mSuccess |= aErrorStr.IsEmpty();
 
   Next();
 }
 
 void
 BluetoothProfileController::GiveupAndContinue()
 {
   MOZ_ASSERT(!mCurrentProfileFinished);
   MOZ_ASSERT(mProfilesIndex < (int)mProfiles.Length());
 
   BT_LOGR_PROFILE(mProfiles[mProfilesIndex], ERR_OPERATION_TIMEOUT);
   mProfiles[mProfilesIndex]->Reset();
   Next();
 }
+
--- a/dom/bluetooth/BluetoothProfileController.h
+++ b/dom/bluetooth/BluetoothProfileController.h
@@ -84,17 +84,22 @@ public:
                              uint16_t aServiceUuid,
                              uint32_t aCod = 0);
   ~BluetoothProfileController();
 
   /**
    * The controller starts connecting/disconnecting profiles one by one
    * according to the order in array mProfiles.
    */
-  void Start();
+  void StartSession();
+
+  /**
+   * The original DOM request would be fired in this function.
+   */
+  void EndSession();
 
   /**
    * It is invoked after a profile has tried to establish the connection.
    * An error string is returned when it fails.
    */
   void OnConnect(const nsAString& aErrorStr);
 
   /**
--- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
@@ -583,21 +583,31 @@ BluetoothA2dpManager::Connect(const nsAS
   if (mA2dpConnected) {
     aController->OnConnect(NS_LITERAL_STRING(ERR_ALREADY_CONNECTED));
     return;
   }
 
   mDeviceAddress = aDeviceAddress;
   mController = aController;
 
+  if (!sBtA2dpInterface) {
+    BT_LOGR("sBluetoothA2dpInterface is null");
+    aController->OnConnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
+    return;
+  }
+
   bt_bdaddr_t remoteAddress;
   StringToBdAddressType(aDeviceAddress, &remoteAddress);
-  NS_ENSURE_TRUE_VOID(sBtA2dpInterface);
-  NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-                      sBtA2dpInterface->connect(&remoteAddress));
+
+  bt_status_t result = sBtA2dpInterface->connect(&remoteAddress);
+  if (BT_STATUS_SUCCESS != result) {
+    BT_LOGR("Failed to connect: %x", result);
+    aController->OnConnect(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
+    return;
+  }
 }
 
 void
 BluetoothA2dpManager::Disconnect(BluetoothProfileController* aController)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mController);
 
@@ -615,21 +625,30 @@ BluetoothA2dpManager::Disconnect(Bluetoo
     }
     return;
   }
 
   MOZ_ASSERT(!mDeviceAddress.IsEmpty());
 
   mController = aController;
 
+  if (!sBtA2dpInterface) {
+    BT_LOGR("sBluetoothA2dpInterface is null");
+    aController->OnDisconnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
+    return;
+  }
+
   bt_bdaddr_t remoteAddress;
   StringToBdAddressType(mDeviceAddress, &remoteAddress);
-  if (sBtA2dpInterface) {
-    NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-                        sBtA2dpInterface->disconnect(&remoteAddress));
+
+  bt_status_t result = sBtA2dpInterface->disconnect(&remoteAddress);
+  if (BT_STATUS_SUCCESS != result) {
+    BT_LOGR("Failed to disconnect: %x", result);
+    aController->OnDisconnect(NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
+    return;
   }
 }
 
 void
 BluetoothA2dpManager::OnConnect(const nsAString& aErrorStr)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
@@ -1173,17 +1173,17 @@ NextBluetoothProfileController()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // First, remove the task at the front which has been already done.
   NS_ENSURE_FALSE_VOID(sControllerArray.IsEmpty());
   sControllerArray.RemoveElementAt(0);
   // Re-check if the task array is empty, if it's not, the next task will begin.
   NS_ENSURE_FALSE_VOID(sControllerArray.IsEmpty());
-  sControllerArray[0]->Start();
+  sControllerArray[0]->StartSession();
 }
 
 static void
 ConnectDisconnect(bool aConnect, const nsAString& aDeviceAddress,
                   BluetoothReplyRunnable* aRunnable,
                   uint16_t aServiceUuid, uint32_t aCod = 0)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -1196,17 +1196,17 @@ ConnectDisconnect(bool aConnect, const n
   sControllerArray.AppendElement(controller);
 
   /**
    * If the request is the first element of the quene, start from here. Note
    * that other request is pushed into the quene and is popped out after the
    * first one is completed. See NextBluetoothProfileController() for details.
    */
   if (sControllerArray.Length() == 1) {
-    sControllerArray[0]->Start();
+    sControllerArray[0]->StartSession();
   }
 }
 
 const bt_interface_t*
 BluetoothServiceBluedroid::GetBluetoothInterface()
 {
   return sBtInterface;
 }
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -1226,39 +1226,57 @@ BluetoothHfpManager::Connect(const nsASt
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aController && !mController);
 
   if (sInShutdown) {
     aController->OnConnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
     return;
   }
 
-  NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
+  if (!sBluetoothHfpInterface) {
+    BT_LOGR("sBluetoothHfpInterface is null");
+    aController->OnConnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
+    return;
+  }
 
   bt_bdaddr_t deviceBdAddress;
   StringToBdAddressType(aDeviceAddress, &deviceBdAddress);
-  NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-    sBluetoothHfpInterface->connect(&deviceBdAddress));
+
+  bt_status_t result = sBluetoothHfpInterface->connect(&deviceBdAddress);
+  if (BT_STATUS_SUCCESS != result) {
+    BT_LOGR("Failed to connect: %x", result);
+    aController->OnConnect(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
+    return;
+  }
 
   mDeviceAddress = aDeviceAddress;
   mController = aController;
 }
 
 void
 BluetoothHfpManager::Disconnect(BluetoothProfileController* aController)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mController);
 
-  NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
+  if (!sBluetoothHfpInterface) {
+    BT_LOGR("sBluetoothHfpInterface is null");
+    aController->OnDisconnect(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
+    return;
+  }
 
   bt_bdaddr_t deviceBdAddress;
   StringToBdAddressType(mDeviceAddress, &deviceBdAddress);
-  NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
-    sBluetoothHfpInterface->disconnect(&deviceBdAddress));
+
+  bt_status_t result = sBluetoothHfpInterface->disconnect(&deviceBdAddress);
+  if (BT_STATUS_SUCCESS != result) {
+    BT_LOGR("Failed to disconnect: %x", result);
+    aController->OnDisconnect(NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
+    return;
+  }
 
   mController = aController;
 }
 
 void
 BluetoothHfpManager::OnConnect(const nsAString& aErrorStr)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/bluetooth/bluez/BluetoothDBusService.cpp
+++ b/dom/bluetooth/bluez/BluetoothDBusService.cpp
@@ -3239,17 +3239,17 @@ NextBluetoothProfileController()
   MOZ_ASSERT(NS_IsMainThread());
 
   // First, remove the task at the front which has been already done.
   NS_ENSURE_FALSE_VOID(sControllerArray.IsEmpty());
   sControllerArray.RemoveElementAt(0);
 
   // Re-check if the task array is empty, if it's not, the next task will begin.
   NS_ENSURE_FALSE_VOID(sControllerArray.IsEmpty());
-  sControllerArray[0]->Start();
+  sControllerArray[0]->StartSession();
 }
 
 static void
 ConnectDisconnect(bool aConnect, const nsAString& aDeviceAddress,
                   BluetoothReplyRunnable* aRunnable,
                   uint16_t aServiceUuid, uint32_t aCod = 0)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -3262,17 +3262,17 @@ ConnectDisconnect(bool aConnect, const n
   sControllerArray.AppendElement(controller);
 
   /**
    * If the request is the first element of the quene, start from here. Note
    * that other request is pushed into the quene and is popped out after the
    * first one is completed. See NextBluetoothProfileController() for details.
    */
   if (sControllerArray.Length() == 1) {
-    sControllerArray[0]->Start();
+    sControllerArray[0]->StartSession();
   }
 }
 
 void
 BluetoothDBusService::Connect(const nsAString& aDeviceAddress,
                               uint32_t aCod,
                               uint16_t aServiceUuid,
                               BluetoothReplyRunnable* aRunnable)