Bug 1103872: Add Handsfree interface for Bluetooth daemon (under bluetooth2/), r=btian
authorThomas Zimmermann <tdz@users.sourceforge.net>
Fri, 28 Nov 2014 11:37:47 +0100
changeset 243873 6708343dd7eeb0743f9c82e5c0e53cf1f4a0d1a6
parent 243872 b9b07db1e846a5b712400762f11fd2d580e85e4d
child 243874 eb2a8052241ba2c1374e3e816a6d112202f3e6fc
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbtian
bugs1103872
milestone36.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 1103872: Add Handsfree interface for Bluetooth daemon (under bluetooth2/), r=btian
dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.cpp
dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.h
--- a/dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.cpp
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BluetoothDaemonHandsfreeInterface.h"
+#include "BluetoothDaemonSetupInterface.h"
 #include "mozilla/unused.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 //
 // Handsfree module
 //
 
@@ -948,9 +949,292 @@ BluetoothDaemonHandsfreeModule::HandleNt
   if (NS_WARN_IF(!(index < MOZ_ARRAY_LENGTH(HandleNtf))) ||
       NS_WARN_IF(!HandleNtf[index])) {
     return;
   }
 
   (this->*(HandleNtf[index]))(aHeader, aPDU);
 }
 
+//
+// Handsfree interface
+//
+
+BluetoothDaemonHandsfreeInterface::BluetoothDaemonHandsfreeInterface(
+  BluetoothDaemonHandsfreeModule* aModule)
+  : mModule(aModule)
+{ }
+
+BluetoothDaemonHandsfreeInterface::~BluetoothDaemonHandsfreeInterface()
+{ }
+
+class BluetoothDaemonHandsfreeInterface::InitResultHandler MOZ_FINAL
+  : public BluetoothSetupResultHandler
+{
+public:
+  InitResultHandler(BluetoothHandsfreeResultHandler* aRes)
+    : mRes(aRes)
+  {
+    MOZ_ASSERT(mRes);
+  }
+
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    mRes->OnError(aStatus);
+  }
+
+  void RegisterModule() MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    mRes->Init();
+  }
+
+private:
+  nsRefPtr<BluetoothHandsfreeResultHandler> mRes;
+};
+
+void
+BluetoothDaemonHandsfreeInterface::Init(
+  BluetoothHandsfreeNotificationHandler* aNotificationHandler,
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  // Set notification handler _before_ registering the module. It could
+  // happen that we receive notifications, before the result handler runs.
+  mModule->SetNotificationHandler(aNotificationHandler);
+
+  InitResultHandler* res;
+
+  if (aRes) {
+    res = new InitResultHandler(aRes);
+  } else {
+    // We don't need a result handler if the caller is not interested.
+    res = nullptr;
+  }
+
+  nsresult rv = mModule->RegisterModule(
+    BluetoothDaemonHandsfreeModule::SERVICE_ID, MODE_NARROWBAND_SPEECH, res);
+
+  if (NS_FAILED(rv) && aRes) {
+    DispatchError(aRes, STATUS_FAIL);
+  }
+}
+
+class BluetoothDaemonHandsfreeInterface::CleanupResultHandler MOZ_FINAL
+  : public BluetoothSetupResultHandler
+{
+public:
+  CleanupResultHandler(BluetoothDaemonHandsfreeModule* aModule,
+                       BluetoothHandsfreeResultHandler* aRes)
+    : mModule(aModule)
+    , mRes(aRes)
+  {
+    MOZ_ASSERT(mModule);
+  }
+
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    if (mRes) {
+      mRes->OnError(aStatus);
+    }
+  }
+
+  void UnregisterModule() MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    // Clear notification handler _after_ module has been
+    // unregistered. While unregistering the module, we might
+    // still receive notifications.
+    mModule->SetNotificationHandler(nullptr);
+
+    if (mRes) {
+      mRes->Cleanup();
+    }
+  }
+
+private:
+  BluetoothDaemonHandsfreeModule* mModule;
+  nsRefPtr<BluetoothHandsfreeResultHandler> mRes;
+};
+
+void
+BluetoothDaemonHandsfreeInterface::Cleanup(
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  mModule->UnregisterModule(BluetoothDaemonHandsfreeModule::SERVICE_ID,
+                            new CleanupResultHandler(mModule, aRes));
+}
+
+/* Connect / Disconnect */
+
+void
+BluetoothDaemonHandsfreeInterface::Connect(
+  const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->ConnectCmd(aBdAddr, aRes);
+}
+
+void
+BluetoothDaemonHandsfreeInterface::Disconnect(
+  const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->DisconnectCmd(aBdAddr, aRes);
+}
+
+void
+BluetoothDaemonHandsfreeInterface::ConnectAudio(
+  const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->ConnectAudioCmd(aBdAddr, aRes);
+}
+
+void
+BluetoothDaemonHandsfreeInterface::DisconnectAudio(
+  const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->DisconnectAudioCmd(aBdAddr, aRes);
+}
+
+/* Voice Recognition */
+
+void
+BluetoothDaemonHandsfreeInterface::StartVoiceRecognition(
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->StartVoiceRecognitionCmd(aRes);
+}
+
+void
+BluetoothDaemonHandsfreeInterface::StopVoiceRecognition(
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->StopVoiceRecognitionCmd(aRes);
+}
+
+/* Volume */
+
+void
+BluetoothDaemonHandsfreeInterface::VolumeControl(
+  BluetoothHandsfreeVolumeType aType, int aVolume,
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->VolumeControlCmd(aType, aVolume, aRes);
+}
+
+/* Device status */
+
+void
+BluetoothDaemonHandsfreeInterface::DeviceStatusNotification(
+  BluetoothHandsfreeNetworkState aNtkState,
+  BluetoothHandsfreeServiceType aSvcType, int aSignal, int aBattChg,
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->DeviceStatusNotificationCmd(aNtkState, aSvcType, aSignal,
+                                       aBattChg, aRes);
+}
+
+/* Responses */
+
+void
+BluetoothDaemonHandsfreeInterface::CopsResponse(
+  const char* aCops, BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->CopsResponseCmd(aCops, aRes);
+}
+
+void
+BluetoothDaemonHandsfreeInterface::CindResponse(
+  int aSvc, int aNumActive, int aNumHeld,
+  BluetoothHandsfreeCallState aCallSetupState,
+  int aSignal, int aRoam, int aBattChg,
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->CindResponseCmd(aSvc, aNumActive, aNumHeld, aCallSetupState,
+                           aSignal, aRoam, aBattChg, aRes);
+}
+
+void
+BluetoothDaemonHandsfreeInterface::FormattedAtResponse(
+  const char* aRsp, BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->FormattedAtResponseCmd(aRsp, aRes);
+}
+
+void
+BluetoothDaemonHandsfreeInterface::AtResponse(
+  BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->AtResponseCmd(aResponseCode, aErrorCode, aRes);
+}
+
+void
+BluetoothDaemonHandsfreeInterface::ClccResponse(
+  int aIndex, BluetoothHandsfreeCallDirection aDir,
+  BluetoothHandsfreeCallState aState,
+  BluetoothHandsfreeCallMode aMode,
+  BluetoothHandsfreeCallMptyType aMpty,
+  const nsAString& aNumber,
+  BluetoothHandsfreeCallAddressType aType,
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->ClccResponseCmd(aIndex, aDir, aState, aMode, aMpty, aNumber,
+                           aType, aRes);
+}
+
+/* Phone State */
+
+void
+BluetoothDaemonHandsfreeInterface::PhoneStateChange(
+  int aNumActive, int aNumHeld,
+  BluetoothHandsfreeCallState aCallSetupState,
+  const nsAString& aNumber,
+  BluetoothHandsfreeCallAddressType aType,
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->PhoneStateChangeCmd(aNumActive, aNumHeld, aCallSetupState, aNumber,
+                               aType, aRes);
+}
+
+void
+BluetoothDaemonHandsfreeInterface::DispatchError(
+  BluetoothHandsfreeResultHandler* aRes, BluetoothStatus aStatus)
+{
+  BluetoothResultRunnable1<BluetoothHandsfreeResultHandler, void,
+                           BluetoothStatus, BluetoothStatus>::Dispatch(
+    aRes, &BluetoothHandsfreeResultHandler::OnError,
+    ConstantInitOp1<BluetoothStatus>(aStatus));
+}
+
 END_BLUETOOTH_NAMESPACE
--- a/dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.h
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonHandsfreeInterface.h
@@ -318,11 +318,95 @@ protected:
 
   void HandleNtf(const BluetoothDaemonPDUHeader& aHeader,
                  BluetoothDaemonPDU& aPDU,
                  void* aUserData);
 
   static BluetoothHandsfreeNotificationHandler* sNotificationHandler;
 };
 
+class BluetoothDaemonHandsfreeInterface MOZ_FINAL
+  : public BluetoothHandsfreeInterface
+{
+  class CleanupResultHandler;
+  class InitResultHandler;
+
+  enum {
+    MODE_HEADSET = 0x00,
+    MODE_NARROWBAND_SPEECH = 0x01,
+    MODE_NARROWBAND_WIDEBAND_SPEECH = 0x02
+  };
+
+public:
+  BluetoothDaemonHandsfreeInterface(BluetoothDaemonHandsfreeModule* aModule);
+  ~BluetoothDaemonHandsfreeInterface();
+
+  void Init(
+    BluetoothHandsfreeNotificationHandler* aNotificationHandler,
+    BluetoothHandsfreeResultHandler* aRes);
+  void Cleanup(BluetoothHandsfreeResultHandler* aRes);
+
+  /* Connect / Disconnect */
+
+  void Connect(const nsAString& aBdAddr,
+               BluetoothHandsfreeResultHandler* aRes);
+  void Disconnect(const nsAString& aBdAddr,
+                  BluetoothHandsfreeResultHandler* aRes);
+  void ConnectAudio(const nsAString& aBdAddr,
+                    BluetoothHandsfreeResultHandler* aRes);
+  void DisconnectAudio(const nsAString& aBdAddr,
+                       BluetoothHandsfreeResultHandler* aRes);
+
+  /* Voice Recognition */
+
+  void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes);
+  void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes);
+
+  /* Volume */
+
+  void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
+                     BluetoothHandsfreeResultHandler* aRes);
+
+  /* Device status */
+
+  void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState,
+                                BluetoothHandsfreeServiceType aSvcType,
+                                int aSignal, int aBattChg,
+                                BluetoothHandsfreeResultHandler* aRes);
+
+  /* Responses */
+
+  void CopsResponse(const char* aCops,
+                    BluetoothHandsfreeResultHandler* aRes);
+  void CindResponse(int aSvc, int aNumActive, int aNumHeld,
+                    BluetoothHandsfreeCallState aCallSetupState,
+                    int aSignal, int aRoam, int aBattChg,
+                    BluetoothHandsfreeResultHandler* aRes);
+  void FormattedAtResponse(const char* aRsp,
+                           BluetoothHandsfreeResultHandler* aRes);
+  void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
+                  BluetoothHandsfreeResultHandler* aRes);
+  void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir,
+                    BluetoothHandsfreeCallState aState,
+                    BluetoothHandsfreeCallMode aMode,
+                    BluetoothHandsfreeCallMptyType aMpty,
+                    const nsAString& aNumber,
+                    BluetoothHandsfreeCallAddressType aType,
+                    BluetoothHandsfreeResultHandler* aRes);
+
+  /* Phone State */
+
+  void PhoneStateChange(int aNumActive, int aNumHeld,
+                        BluetoothHandsfreeCallState aCallSetupState,
+                        const nsAString& aNumber,
+                        BluetoothHandsfreeCallAddressType aType,
+                        BluetoothHandsfreeResultHandler* aRes);
+
+private:
+  void DispatchError(BluetoothHandsfreeResultHandler* aRes,
+                     BluetoothStatus aStatus);
+
+  BluetoothDaemonHandsfreeModule* mModule;
+};
+
 END_BLUETOOTH_NAMESPACE
 
 #endif