Bug 790739: Patch 3 - Service and Manager changes for Bluetooth server sockets; r=cjones
authorKyle Machulis <kyle@nonpolynomial.com>
Sun, 30 Sep 2012 22:55:27 -0700
changeset 108716 9a88f0d57e7d6cb4a810cb007f359300ff4286f0
parent 108715 826ef2970e19fe08b1587f2f1ffbb43cbe90ae2a
child 108717 02ba33fdf2d21d7bf43ff1f4a845a4a4f4fbdc65
push id23585
push useremorley@mozilla.com
push dateMon, 01 Oct 2012 13:02:21 +0000
treeherdermozilla-central@d4355e045ea7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs790739
milestone18.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 790739: Patch 3 - Service and Manager changes for Bluetooth server sockets; r=cjones
dom/bluetooth/BluetoothHfpManager.cpp
dom/bluetooth/BluetoothHfpManager.h
dom/bluetooth/BluetoothService.h
dom/bluetooth/BluetoothServiceUuid.h
dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
dom/bluetooth/ipc/BluetoothServiceChildProcess.h
dom/bluetooth/linux/BluetoothDBusService.cpp
dom/bluetooth/linux/BluetoothDBusService.h
ipc/dbus/DBusUtils.cpp
ipc/dbus/DBusUtils.h
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -402,16 +402,35 @@ BluetoothHfpManager::Connect(const nsASt
                                         false,
                                         this,
                                         runnable);
 
   runnable.forget();
   return NS_FAILED(rv) ? false : true;
 }
 
+bool
+BluetoothHfpManager::Listen()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  BluetoothService* bs = BluetoothService::Get();
+  if (!bs) {
+    NS_WARNING("BluetoothService not available!");
+    return false;
+  }
+
+  nsresult rv = bs->ListenSocketViaService(BluetoothReservedChannels::HANDSFREE_AG,
+                                           BluetoothSocketType::RFCOMM,
+                                           true,
+                                           false,
+                                           this);
+  return NS_FAILED(rv) ? false : true;
+}
+
 void
 BluetoothHfpManager::Disconnect()
 {
   CloseSocket();
 }
 
 bool
 BluetoothHfpManager::SendLine(const char* aMessage)
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -29,17 +29,17 @@ public:
   void ReceiveSocketData(mozilla::ipc::UnixSocketRawData* aMessage);
 
   bool Connect(const nsAString& aDeviceObjectPath,
                BluetoothReplyRunnable* aRunnable);
   void Disconnect();
   bool SendLine(const char* aMessage);
   void CallStateChanged(int aCallIndex, int aCallState,
                         const char* aNumber, bool aIsActive);
-
+  bool Listen();
 private:
   BluetoothHfpManager();
 
   bool BroadcastSystemMessage(const char* aCommand,
                               const int aCommandLength);
   nsresult HandleVolumeChanged(const nsAString& aData);
 
   int mCurrentVgs;
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -274,16 +274,23 @@ public:
   virtual bool
   ConnectObjectPush(const nsAString& aDeviceAddress,
                     const nsAString& aAdapterPath,
                     BluetoothReplyRunnable* aRunnable) = 0;
 
   virtual void
   DisconnectObjectPush(BluetoothReplyRunnable* aRunnable) = 0;
 
+  virtual nsresult
+  ListenSocketViaService(int aChannel,
+                         BluetoothSocketType aType,
+                         bool aAuth,
+                         bool aEncrypt,
+                         mozilla::ipc::UnixSocketConsumer* aConsumer) = 0;
+
   bool
   IsEnabled() const
   {
     return mEnabled;
   }
 
 protected:
   BluetoothService()
--- a/dom/bluetooth/BluetoothServiceUuid.h
+++ b/dom/bluetooth/BluetoothServiceUuid.h
@@ -25,14 +25,29 @@ namespace BluetoothServiceUuid {
 namespace BluetoothServiceUuidStr {
   static const char* Headset       = "00001108-0000-1000-8000-00805F9B34FB";
   static const char* HeadsetAG     = "00001112-0000-1000-8000-00805F9B34FB";
   static const char* Handsfree     = "0000111E-0000-1000-8000-00805F9B34FB";
   static const char* HandsfreeAG   = "0000111F-0000-1000-8000-00805F9B34FB";
   static const char* ObjectPush    = "00001105-0000-1000-8000-00805F9B34FB";
 }
 
+// TODO/qdot: Move these back into gonk and make the service handler deal with
+// it there.
+//
+// Gotten from reading the "u8" values in B2G/external/bluez/src/adapter.c
+// These were hardcoded into android
+enum BluetoothReservedChannels {
+  DIALUP_NETWORK = 1,
+  HANDSFREE_AG = 10,
+  HEADSET_AG = 11,
+  OPUSH = 12,
+  SIM_ACCESS = 15,
+  PBAP_PSE = 19,
+  FTP = 20,
+};
+
 }
 }
 }
 
 #endif
 
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.cpp
@@ -221,16 +221,29 @@ BluetoothServiceChildProcess::GetSocketV
                                        bool aEncrypt,
                                        mozilla::ipc::UnixSocketConsumer* aConsumer,
                                        BluetoothReplyRunnable* aRunnable)
 {
   MOZ_NOT_REACHED("This should never be called!");
   return NS_ERROR_FAILURE;
 }
 
+
+nsresult
+BluetoothServiceChildProcess::ListenSocketViaService(
+  int aChannel,
+  BluetoothSocketType aType,
+  bool aAuth,
+  bool aEncrypt,
+  mozilla::ipc::UnixSocketConsumer* aConsumer)
+{
+  MOZ_NOT_REACHED("This should never be called!");
+  return NS_ERROR_FAILURE;
+}
+
 bool
 BluetoothServiceChildProcess::SetPinCodeInternal(
                                                 const nsAString& aDeviceAddress,
                                                 const nsAString& aPinCode,
                                                 BluetoothReplyRunnable* aRunnable)
 {
   SendRequest(aRunnable,
               SetPinCodeRequest(nsString(aDeviceAddress), nsString(aPinCode)));
--- a/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
+++ b/dom/bluetooth/ipc/BluetoothServiceChildProcess.h
@@ -96,16 +96,23 @@ public:
   GetSocketViaService(const nsAString& aObjectPath,
                       const nsAString& aService,
                       BluetoothSocketType aType,
                       bool aAuth,
                       bool aEncrypt,
                       mozilla::ipc::UnixSocketConsumer* aConsumer,
                       BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
+  virtual nsresult
+  ListenSocketViaService(int aChannel,
+                         BluetoothSocketType aType,
+                         bool aAuth,
+                         bool aEncrypt,
+                         mozilla::ipc::UnixSocketConsumer* aConsumer) MOZ_OVERRIDE;
+
   virtual bool
   SetPinCodeInternal(const nsAString& aDeviceAddress,
                      const nsAString& aPinCode,
                      BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
 
   virtual bool
   SetPasskeyInternal(const nsAString& aDeviceAddress,
                      uint32_t aPasskey,
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -256,16 +256,17 @@ public:
     // Due to the fact that we need to queue the dbus call to the command thread
     // inside the bluetoothservice, we have to route the call down to the main
     // thread and then back out to the command thread. There has to be a better
     // way to do this.
     if (NS_FAILED(bs->PrepareAdapterInternal(mPath))) {
       NS_WARNING("prepare adapter failed");
       return NS_ERROR_FAILURE;
     }
+
     return NS_OK;
   }
 
 private:
   nsString mPath;
 };
 
 class DevicePropertiesSignalHandler : public nsRunnable
@@ -723,16 +724,39 @@ ExtractHandles(DBusMessage *aReply, nsTA
     }
   } else {
     LOG_AND_FREE_DBUS_ERROR(&err);
   }
 }
 
 // static
 bool
+BluetoothDBusService::AddServiceRecords(const nsAString& aAdapterPath,
+                                        const char* serviceName,
+                                        unsigned long long uuidMsb,
+                                        unsigned long long uuidLsb,
+                                        int channel)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  DBusMessage *reply;
+  reply = dbus_func_args(gThreadConnection->GetConnection(),
+                         NS_ConvertUTF16toUTF8(aAdapterPath).get(),
+                         DBUS_ADAPTER_IFACE, "AddRfcommServiceRecord",
+                         DBUS_TYPE_STRING, &serviceName,
+                         DBUS_TYPE_UINT64, &uuidMsb,
+                         DBUS_TYPE_UINT64, &uuidLsb,
+                         DBUS_TYPE_UINT16, &channel,
+                         DBUS_TYPE_INVALID);
+
+  return reply ? dbus_returns_uint32(reply) : -1;
+}
+
+// static
+bool
 BluetoothDBusService::AddReservedServicesInternal(const nsAString& aAdapterPath,
                                                   const nsTArray<uint32_t>& aServices,
                                                   nsTArray<uint32_t>& aServiceHandlesContainer)
 {
   MOZ_ASSERT(!NS_IsMainThread());
 
   int length = aServices.Length();
   if (length == 0) return false;
@@ -2272,17 +2296,19 @@ public:
 
   nsresult
   Run()
   {
     MOZ_ASSERT(!NS_IsMainThread());
 
     nsString address = GetAddressFromObjectPath(mObjectPath);
     nsString replyError;
-    BluetoothUnixSocketConnector c(BluetoothSocketType::SCO, -1, mAuth, mEncrypt);
+    BluetoothUnixSocketConnector* c =
+      new BluetoothUnixSocketConnector(BluetoothSocketType::SCO, -1,
+                                       mAuth, mEncrypt);
 
     BluetoothScoManager* sco = BluetoothScoManager::Get();
     if (!mConsumer->ConnectSocket(c, NS_ConvertUTF16toUTF8(address).get())) {
       replyError.AssignLiteral("SocketConnectionError");
       sco->SetConnected(false); 
       return NS_ERROR_FAILURE;
     }
     sco->SetConnected(true);
@@ -2297,47 +2323,47 @@ public:
 
 private:
   nsRefPtr<UnixSocketConsumer> mConsumer;
   nsString mObjectPath;
   bool mAuth;
   bool mEncrypt;
 };
 
-class CreateBluetoothSocketRunnable : public nsRunnable
+class ConnectBluetoothSocketRunnable : public nsRunnable
 {
 public:
-  CreateBluetoothSocketRunnable(BluetoothReplyRunnable* aRunnable,
-                                UnixSocketConsumer* aConsumer,
-                                const nsAString& aObjectPath,
-                                const nsAString& aServiceUUID,
-                                BluetoothSocketType aType,
-                                bool aAuth,
-                                bool aEncrypt)
+  ConnectBluetoothSocketRunnable(BluetoothReplyRunnable* aRunnable,
+                                 UnixSocketConsumer* aConsumer,
+                                 const nsAString& aObjectPath,
+                                 const nsAString& aServiceUUID,
+                                 BluetoothSocketType aType,
+                                 bool aAuth,
+                                 bool aEncrypt)
     : mRunnable(dont_AddRef(aRunnable)),
       mConsumer(aConsumer),
       mObjectPath(aObjectPath),
       mServiceUUID(aServiceUUID),
       mType(aType),
       mAuth(aAuth),
       mEncrypt(aEncrypt)
   {
   }
 
   nsresult
   Run()
   {
-    NS_WARNING("Running create socket!\n");
     MOZ_ASSERT(!NS_IsMainThread());
 
     nsString address = GetAddressFromObjectPath(mObjectPath);
     int channel = GetDeviceServiceChannel(mObjectPath, mServiceUUID, 0x0004);
     BluetoothValue v;
     nsString replyError;
-    BluetoothUnixSocketConnector c(mType, channel, mAuth, mEncrypt);
+    BluetoothUnixSocketConnector* c =
+      new BluetoothUnixSocketConnector(mType, channel, mAuth, mEncrypt);
     if (!mConsumer->ConnectSocket(c, NS_ConvertUTF16toUTF8(address).get())) {
       replyError.AssignLiteral("SocketConnectionError");
       DispatchBluetoothReply(mRunnable, v, replyError);
       return NS_ERROR_FAILURE;
     }
     // Bluetooth value needs to be set to something to succeed.
     v = true;
     DispatchBluetoothReply(mRunnable, v, replyError);
@@ -2390,22 +2416,82 @@ BluetoothDBusService::GetSocketViaServic
 {
   NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
   if (!mConnection || !gThreadConnection) {
     NS_ERROR("Bluetooth service not started yet!");
     return NS_ERROR_FAILURE;
   }
   nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
 
-  nsRefPtr<nsRunnable> func(new CreateBluetoothSocketRunnable(runnable,
+  nsRefPtr<nsRunnable> func(new ConnectBluetoothSocketRunnable(runnable,
                                                               aConsumer,
                                                               aObjectPath,
                                                               aService, aType,
                                                               aAuth, aEncrypt));
   if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
     NS_WARNING("Cannot dispatch firmware loading task!");
     return NS_ERROR_FAILURE;
   }
 
   runnable.forget();
   return NS_OK;
 }
 
+class ListenBluetoothSocketRunnable : public nsRunnable
+{
+public:
+  ListenBluetoothSocketRunnable(UnixSocketConsumer* aConsumer,
+                                int aChannel,
+                                BluetoothSocketType aType,
+                                bool aAuth,
+                                bool aEncrypt)
+    : mConsumer(aConsumer)
+    , mChannel(aChannel)
+    , mType(aType)
+    , mAuth(aAuth)
+    , mEncrypt(aEncrypt)
+  {
+  }
+
+  nsresult
+  Run()
+  {
+    MOZ_ASSERT(!NS_IsMainThread());
+    BluetoothUnixSocketConnector* c =
+      new BluetoothUnixSocketConnector(mType, mChannel, mAuth, mEncrypt);
+    if (!mConsumer->ListenSocket(c)) {
+      NS_WARNING("Can't listen on socket!");
+      return NS_ERROR_FAILURE;
+    }
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<UnixSocketConsumer> mConsumer;
+  int mChannel;
+  BluetoothSocketType mType;
+  bool mAuth;
+  bool mEncrypt;
+};
+
+nsresult
+BluetoothDBusService::ListenSocketViaService(int aChannel,
+                                             BluetoothSocketType aType,
+                                             bool aAuth,
+                                             bool aEncrypt,
+                                             mozilla::ipc::UnixSocketConsumer* aConsumer)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
+  if (!mConnection || !gThreadConnection) {
+    NS_ERROR("Bluetooth service not started yet!");
+    return NS_ERROR_FAILURE;
+  }
+  nsRefPtr<nsRunnable> func(new ListenBluetoothSocketRunnable(aConsumer,
+                                                              aChannel, aType,
+                                                              aAuth,
+                                                              aEncrypt));
+  if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
+    NS_WARNING("Cannot dispatch firmware loading task!");
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -54,16 +54,30 @@ public:
               BluetoothReplyRunnable* aRunnable);
 
   virtual bool
   GetDevicePath(const nsAString& aAdapterPath,
                 const nsAString& aDeviceAddress,
                 nsAString& aDevicePath);
 
   static bool
+  AddServiceRecords(const nsAString& aAdapterPath,
+                    const char* serviceName,
+                    unsigned long long uuidMsb,
+                    unsigned long long uuidLsb,
+                    int channel);
+
+  static bool
+  RemoveServiceRecords(const nsAString& aAdapterPath,
+                       const char* serviceName,
+                       unsigned long long uuidMsb,
+                       unsigned long long uuidLsb,
+                       int channel);
+
+  static bool
   AddReservedServicesInternal(const nsAString& aAdapterPath,
                               const nsTArray<uint32_t>& aServices,
                               nsTArray<uint32_t>& aServiceHandlesContainer);
 
   static bool
   RemoveReservedServicesInternal(const nsAString& aAdapterPath,
                                  const nsTArray<uint32_t>& aServiceHandles);
 
@@ -78,16 +92,23 @@ public:
                       const nsAString& aService,
                       BluetoothSocketType aType,
                       bool aAuth,
                       bool aEncrypt,
                       mozilla::ipc::UnixSocketConsumer* aConsumer,
                       BluetoothReplyRunnable* aRunnable);
 
   virtual nsresult
+  ListenSocketViaService(int aChannel,
+                         BluetoothSocketType aType,
+                         bool aAuth,
+                         bool aEncrypt,
+                         mozilla::ipc::UnixSocketConsumer* aConsumer);
+
+  virtual nsresult
   CreatePairedDeviceInternal(const nsAString& aAdapterPath,
                              const nsAString& aDeviceAddress,
                              int aTimeout,
                              BluetoothReplyRunnable* aRunnable);
 
   virtual nsresult
   RemoveDeviceInternal(const nsAString& aAdapterPath,
                        const nsAString& aDeviceObjectPath,
--- a/ipc/dbus/DBusUtils.cpp
+++ b/ipc/dbus/DBusUtils.cpp
@@ -259,23 +259,39 @@ DBusMessage * dbus_func_args_error(DBusC
                                       first_arg_type, lst);
   va_end(lst);
   return ret;
 }
 
 int dbus_returns_int32(DBusMessage *reply) 
 {
   DBusError err;
-  int ret = -1;
+  int32_t ret = -1;
 
   dbus_error_init(&err);
   if (!dbus_message_get_args(reply, &err,
                              DBUS_TYPE_INT32, &ret,
                              DBUS_TYPE_INVALID)) {
     LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
   }
 
   dbus_message_unref(reply);
   return ret;
 }
 
+int dbus_returns_uint32(DBusMessage *reply)
+{
+  DBusError err;
+  uint32_t ret = -1;
+
+  dbus_error_init(&err);
+  if (!dbus_message_get_args(reply, &err,
+                             DBUS_TYPE_UINT32, &ret,
+                             DBUS_TYPE_INVALID)) {
+    LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
+  }
+
+  dbus_message_unref(reply);
+  return ret;
+}
+
 }
 }
--- a/ipc/dbus/DBusUtils.h
+++ b/ipc/dbus/DBusUtils.h
@@ -103,13 +103,15 @@ DBusMessage*  dbus_func_args_timeout_val
                                             const char* path,
                                             const char* ifc,
                                             const char* func,
                                             int first_arg_type,
                                             va_list args);
 
 int dbus_returns_int32(DBusMessage *reply);
 
+int dbus_returns_uint32(DBusMessage *reply);
+
 }
 }
 
 #endif