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 108825 9a88f0d57e7d6cb4a810cb007f359300ff4286f0
parent 108824 826ef2970e19fe08b1587f2f1ffbb43cbe90ae2a
child 108826 02ba33fdf2d21d7bf43ff1f4a845a4a4f4fbdc65
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewerscjones
bugs790739
milestone18.0a1
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