Bug 1141616: Implement |BluetoothService::GetServiceChannel|, r=btian
authorThomas Zimmermann <tdz@users.sourceforge.net>
Wed, 09 Sep 2015 13:20:45 +0200
changeset 294099 21b1705ef65c7b7d7c53fc452cb3442d3edc98e2
parent 294098 1de29ebab9c15874ab4f9003dc202bb5244cbc01
child 294100 a08d93552eba364d3ea3e4ccc5bad56673ec044b
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbtian
bugs1141616
milestone43.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 1141616: Implement |BluetoothService::GetServiceChannel|, r=btian This patch adds support for reading a service channel from a remote device.
dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
dom/bluetooth/common/BluetoothCommon.h
dom/bluetooth/common/BluetoothUtils.cpp
dom/bluetooth/common/BluetoothUtils.h
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
@@ -836,22 +836,118 @@ BluetoothServiceBluedroid::SetProperty(B
   mSetAdapterPropertyRunnables.AppendElement(aRunnable);
   sBtInterface->SetAdapterProperty(aValue,
     new DispatchReplyErrorResultHandler(mSetAdapterPropertyRunnables,
                                         aRunnable));
 
   return NS_OK;
 }
 
+struct BluetoothServiceBluedroid::GetRemoteServiceRecordRequest final
+{
+  GetRemoteServiceRecordRequest(const nsAString& aDeviceAddress,
+                                const BluetoothUuid& aUuid,
+                                BluetoothProfileManagerBase* aManager)
+    : mDeviceAddress(aDeviceAddress)
+    , mUuid(aUuid)
+    , mManager(aManager)
+  {
+    MOZ_ASSERT(!mDeviceAddress.IsEmpty());
+    MOZ_ASSERT(mManager);
+  }
+
+  nsString mDeviceAddress;
+  BluetoothUuid mUuid;
+  BluetoothProfileManagerBase* mManager;
+};
+
+class BluetoothServiceBluedroid::GetRemoteServiceRecordResultHandler final
+  : public BluetoothResultHandler
+{
+public:
+  GetRemoteServiceRecordResultHandler(
+    nsTArray<GetRemoteServiceRecordRequest>& aGetRemoteServiceRecordArray,
+    const nsAString& aDeviceAddress,
+    const BluetoothUuid& aUuid)
+    : mGetRemoteServiceRecordArray(aGetRemoteServiceRecordArray)
+    , mDeviceAddress(aDeviceAddress)
+    , mUuid(aUuid)
+  {
+    MOZ_ASSERT(!mDeviceAddress.IsEmpty());
+  }
+
+  void OnError(BluetoothStatus aStatus) override
+  {
+    // Find call in array
+
+    ssize_t i = FindRequest();
+
+    if (i == -1) {
+      BT_WARNING("No GetRemoteService request found");
+      return;
+    }
+
+    // Signal error to profile manager
+
+    nsAutoString uuidStr;
+    UuidToString(mUuid, uuidStr);
+    mGetRemoteServiceRecordArray[i].mManager->OnGetServiceChannel(
+      mDeviceAddress, uuidStr, -1);
+    mGetRemoteServiceRecordArray.RemoveElementAt(i);
+  }
+
+  void CancelDiscovery() override
+  {
+    // Disabled discovery mode, now perform SDP operation.
+    sBtInterface->GetRemoteServiceRecord(mDeviceAddress, mUuid.mUuid, this);
+  }
+
+private:
+  ssize_t FindRequest() const
+  {
+    for (size_t i = 0; i < mGetRemoteServiceRecordArray.Length(); ++i) {
+      if ((mGetRemoteServiceRecordArray[i].mDeviceAddress == mDeviceAddress) &&
+          (mGetRemoteServiceRecordArray[i].mUuid == mUuid)) {
+        return i;
+      }
+    }
+
+    return -1;
+  }
+
+  nsTArray<GetRemoteServiceRecordRequest>& mGetRemoteServiceRecordArray;
+  nsString mDeviceAddress;
+  BluetoothUuid mUuid;
+};
+
 nsresult
 BluetoothServiceBluedroid::GetServiceChannel(
   const nsAString& aDeviceAddress,
   const nsAString& aServiceUuid,
   BluetoothProfileManagerBase* aManager)
 {
+  BluetoothUuid uuid;
+  StringToUuid(aServiceUuid, uuid);
+  mGetRemoteServiceRecordArray.AppendElement(
+    GetRemoteServiceRecordRequest(aDeviceAddress, uuid, aManager));
+
+  nsRefPtr<BluetoothResultHandler> res =
+    new GetRemoteServiceRecordResultHandler(mGetRemoteServiceRecordArray,
+                                            aDeviceAddress, uuid);
+
+  /* Stop discovery of remote devices here, because SDP operations
+   * won't be performed while the adapter is in discovery mode.
+   */
+  if (mDiscovering) {
+    sBtInterface->CancelDiscovery(res);
+  } else {
+    sBtInterface->GetRemoteServiceRecord(
+      aDeviceAddress, uuid.mUuid, res);
+  }
+
   return NS_OK;
 }
 
 bool
 BluetoothServiceBluedroid::UpdateSdpRecords(
   const nsAString& aDeviceAddress,
   BluetoothProfileManagerBase* aManager)
 {
@@ -1652,16 +1748,38 @@ BluetoothServiceBluedroid::RemoteDeviceP
         }
       }
       AppendNamedValue(propertiesArray, "UUIDs", uuids);
 
     } else if (p.mType == PROPERTY_TYPE_OF_DEVICE) {
       AppendNamedValue(propertiesArray, "Type",
                        static_cast<uint32_t>(p.mTypeOfDevice));
 
+    } else if (p.mType == PROPERTY_SERVICE_RECORD) {
+
+      size_t i;
+
+      // Find call in array
+
+      for (i = 0; i < mGetRemoteServiceRecordArray.Length(); ++i) {
+        if ((mGetRemoteServiceRecordArray[i].mDeviceAddress == aBdAddr) &&
+            (mGetRemoteServiceRecordArray[i].mUuid == p.mServiceRecord.mUuid)) {
+
+          // Signal channel to profile manager
+          nsAutoString uuidStr;
+          UuidToString(mGetRemoteServiceRecordArray[i].mUuid, uuidStr);
+
+          mGetRemoteServiceRecordArray[i].mManager->OnGetServiceChannel(
+            aBdAddr, uuidStr, p.mServiceRecord.mChannel);
+
+          mGetRemoteServiceRecordArray.RemoveElementAt(i);
+          break;
+        }
+      }
+      unused << NS_WARN_IF(i == mGetRemoteServiceRecordArray.Length());
     } else if (p.mType == PROPERTY_UNKNOWN) {
       /* Bug 1065999: working around unknown properties */
     } else {
       BT_LOGD("Other non-handled device properties. Type: %d", p.mType);
     }
   }
 
   // The order of operations below is
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.h
@@ -17,24 +17,26 @@ BEGIN_BLUETOOTH_NAMESPACE
 class BluetoothServiceBluedroid : public BluetoothService
                                 , public BluetoothNotificationHandler
 {
   class CleanupResultHandler;
   class DisableResultHandler;
   class DispatchReplyErrorResultHandler;
   class EnableResultHandler;
   class GetRemoteDevicePropertiesResultHandler;
+  class GetRemoteServiceRecordResultHandler;
   class InitResultHandler;
   class PinReplyResultHandler;
   class ProfileDeinitResultHandler;
   class ProfileInitResultHandler;
   class SetAdapterPropertyDiscoverableResultHandler;
   class SspReplyResultHandler;
 
   class GetDeviceRequest;
+  struct GetRemoteServiceRecordRequest;
 
 public:
   BluetoothServiceBluedroid();
   ~BluetoothServiceBluedroid();
 
   virtual nsresult StartInternal(BluetoothReplyRunnable* aRunnable);
   virtual nsresult StopInternal(BluetoothReplyRunnable* aRunnable);
 
@@ -389,13 +391,16 @@ protected:
   // Array of get device requests. Each request remembers
   // 1) remaining device count to receive properties,
   // 2) received remote device properties, and
   // 3) runnable to reply success/error
   nsTArray<GetDeviceRequest> mGetDeviceRequests;
 
   // <address, name> mapping table for remote devices
   nsDataHashtable<nsStringHashKey, nsString> mDeviceNameMap;
+
+  // Arrays for SDP operations
+  nsTArray<GetRemoteServiceRecordRequest> mGetRemoteServiceRecordArray;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif // mozilla_dom_bluetooth_bluedroid_BluetoothServiceBluedroid_h
--- a/dom/bluetooth/common/BluetoothCommon.h
+++ b/dom/bluetooth/common/BluetoothCommon.h
@@ -300,16 +300,21 @@ struct BluetoothUuid {
   {
     for (uint8_t i = 0; i < sizeof(mUuid); i++) {
       if (mUuid[i] != aOther.mUuid[i]) {
         return false;
       }
     }
     return true;
   }
+
+  bool operator!=(const BluetoothUuid& aOther) const
+  {
+    return !(*this == aOther);
+  }
 };
 
 struct BluetoothServiceRecord {
   BluetoothUuid mUuid;
   uint16_t mChannel;
   char mName[256];
 };
 
--- a/dom/bluetooth/common/BluetoothUtils.cpp
+++ b/dom/bluetooth/common/BluetoothUtils.cpp
@@ -62,16 +62,22 @@ StringToUuid(const char* aString, Blueto
   memcpy(&aUuid.mUuid[4], &uuid1, sizeof(uint16_t));
   memcpy(&aUuid.mUuid[6], &uuid2, sizeof(uint16_t));
   memcpy(&aUuid.mUuid[8], &uuid3, sizeof(uint16_t));
   memcpy(&aUuid.mUuid[10], &uuid4, sizeof(uint32_t));
   memcpy(&aUuid.mUuid[14], &uuid5, sizeof(uint16_t));
 }
 
 void
+StringToUuid(const nsAString& aString, BluetoothUuid& aUuid)
+{
+  StringToUuid(NS_ConvertUTF16toUTF8(aString).get(), aUuid);
+}
+
+void
 GenerateUuid(nsAString &aUuidString)
 {
   nsresult rv;
   nsCOMPtr<nsIUUIDGenerator> uuidGenerator =
     do_GetService("@mozilla.org/uuid-generator;1", &rv);
   NS_ENSURE_SUCCESS_VOID(rv);
 
   nsID uuid;
--- a/dom/bluetooth/common/BluetoothUtils.h
+++ b/dom/bluetooth/common/BluetoothUtils.h
@@ -34,16 +34,25 @@ UuidToString(const BluetoothUuid& aUuid,
  *
  * Note: This utility function is used by gecko internal only to convert uuid
  * string created by gecko back to BluetoothUuid representation.
  */
 void
 StringToUuid(const char* aString, BluetoothUuid& aUuid);
 
 /**
+ * Convert xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx uuid string to BluetoothUuid object.
+ *
+ * This utility function is used by gecko internal only to convert uuid string
+ * created by gecko back to BluetoothUuid representation.
+ */
+void
+StringToUuid(const nsAString& aString, BluetoothUuid& aUuid);
+
+/**
  * Generate a random uuid.
  *
  * @param aUuidString [out] String to store the generated uuid.
  */
 void
 GenerateUuid(nsAString &aUuidString);
 
 //