dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80: */
     3 /*
     4 ** Copyright 2006, The Android Open Source Project
     5 **
     6 ** Licensed under the Apache License, Version 2.0 (the "License");
     7 ** you may not use this file except in compliance with the License.
     8 ** You may obtain a copy of the License at
     9 **
    10 **     http://www.apache.org/licenses/LICENSE-2.0
    11 **
    12 ** Unless required by applicable law or agreed to in writing, software
    13 ** distributed under the License is distributed on an "AS IS" BASIS,
    14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15 ** See the License for the specific language governing permissions and
    16 ** limitations under the License.
    17 */
    19 #include "BluetoothServiceBluedroid.h"
    21 #include <hardware/hardware.h>
    23 #include "BluetoothA2dpManager.h"
    24 #include "BluetoothHfpManager.h"
    25 #include "BluetoothOppManager.h"
    26 #include "BluetoothProfileController.h"
    27 #include "BluetoothReplyRunnable.h"
    28 #include "BluetoothUtils.h"
    29 #include "BluetoothUuid.h"
    30 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
    31 #include "mozilla/ipc/UnixSocket.h"
    32 #include "mozilla/StaticMutex.h"
    33 #include "mozilla/StaticPtr.h"
    34 #include "mozilla/unused.h"
    36 using namespace mozilla;
    37 using namespace mozilla::ipc;
    38 USING_BLUETOOTH_NAMESPACE
    40 /**
    41  *  Static variables
    42  */
    43 static bluetooth_device_t* sBtDevice;
    44 static const bt_interface_t* sBtInterface;
    45 static bool sAdapterDiscoverable = false;
    46 static bool sIsBtEnabled = false;
    47 static nsString sAdapterBdAddress;
    48 static nsString sAdapterBdName;
    49 static uint32_t sAdapterDiscoverableTimeout;
    50 static InfallibleTArray<nsString> sAdapterBondedAddressArray;
    51 static InfallibleTArray<BluetoothNamedValue> sRemoteDevicesPack;
    52 static nsTArray<nsRefPtr<BluetoothProfileController> > sControllerArray;
    53 static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sBondingRunnableArray;
    54 static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeDiscoveryRunnableArray;
    55 static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sGetDeviceRunnableArray;
    56 static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sSetPropertyRunnableArray;
    57 static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
    58 static nsTArray<int> sRequestedDeviceCountArray;
    60 /**
    61  *  Classes only used in this file
    62  */
    63 class DistributeBluetoothSignalTask : public nsRunnable {
    64 public:
    65   DistributeBluetoothSignalTask(const BluetoothSignal& aSignal) :
    66     mSignal(aSignal)
    67   {
    68   }
    70   NS_IMETHOD
    71   Run()
    72   {
    73     MOZ_ASSERT(NS_IsMainThread());
    75     BluetoothService* bs = BluetoothService::Get();
    76     NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
    78     bs->DistributeSignal(mSignal);
    80     return NS_OK;
    81   }
    83 private:
    84   BluetoothSignal mSignal;
    85 };
    87 class SetupAfterEnabledTask : public nsRunnable
    88 {
    89 public:
    90   SetupAfterEnabledTask()
    91   { }
    93   NS_IMETHOD
    94   Run()
    95   {
    96     MOZ_ASSERT(NS_IsMainThread());
    98     // Bluetooth scan mode is NONE by default
    99     bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE;
   100     bt_property_t prop;
   101     prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
   102     prop.val = (void*)&mode;
   103     prop.len = sizeof(mode);
   105     NS_ENSURE_TRUE(sBtInterface, NS_ERROR_FAILURE);
   107     int ret = sBtInterface->set_adapter_property(&prop);
   108     if (ret != BT_STATUS_SUCCESS) {
   109       BT_LOGR("Fail to set: BT_SCAN_MODE_CONNECTABLE");
   110     }
   112     // Try to fire event 'AdapterAdded' to fit the original behaviour when
   113     // we used BlueZ as backend.
   114     BluetoothService* bs = BluetoothService::Get();
   115     NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
   117     bs->AdapterAddedReceived();
   118     bs->TryFiringAdapterAdded();
   120     // Trigger BluetoothOppManager to listen
   121     BluetoothOppManager* opp = BluetoothOppManager::Get();
   122     if (!opp || !opp->Listen()) {
   123       BT_LOGR("Fail to start BluetoothOppManager listening");
   124     }
   126     return NS_OK;
   127   }
   128 };
   130 /**
   131  *  Static callback functions
   132  */
   133 static void
   134 ClassToIcon(uint32_t aClass, nsAString& aRetIcon)
   135 {
   136   switch ((aClass & 0x1f00) >> 8) {
   137     case 0x01:
   138       aRetIcon.AssignLiteral("computer");
   139       break;
   140     case 0x02:
   141       switch ((aClass & 0xfc) >> 2) {
   142         case 0x01:
   143         case 0x02:
   144         case 0x03:
   145         case 0x05:
   146           aRetIcon.AssignLiteral("phone");
   147           break;
   148         case 0x04:
   149           aRetIcon.AssignLiteral("modem");
   150           break;
   151       }
   152       break;
   153     case 0x03:
   154       aRetIcon.AssignLiteral("network-wireless");
   155       break;
   156     case 0x04:
   157       switch ((aClass & 0xfc) >> 2) {
   158         case 0x01:
   159         case 0x02:
   160         case 0x06:
   161           aRetIcon.AssignLiteral("audio-card");
   162           break;
   163         case 0x0b:
   164         case 0x0c:
   165         case 0x0d:
   166           aRetIcon.AssignLiteral("camera-video");
   167           break;
   168         default:
   169           aRetIcon.AssignLiteral("audio-card");
   170           break;
   171       }
   172       break;
   173     case 0x05:
   174       switch ((aClass & 0xc0) >> 6) {
   175         case 0x00:
   176           switch ((aClass && 0x1e) >> 2) {
   177             case 0x01:
   178             case 0x02:
   179               aRetIcon.AssignLiteral("input-gaming");
   180               break;
   181           }
   182           break;
   183         case 0x01:
   184           aRetIcon.AssignLiteral("input-keyboard");
   185           break;
   186         case 0x02:
   187           switch ((aClass && 0x1e) >> 2) {
   188             case 0x05:
   189               aRetIcon.AssignLiteral("input-tablet");
   190               break;
   191             default:
   192               aRetIcon.AssignLiteral("input-mouse");
   193               break;
   194           }
   195       }
   196       break;
   197     case 0x06:
   198       if (aClass & 0x80) {
   199         aRetIcon.AssignLiteral("printer");
   200         break;
   201       }
   202       if (aClass & 0x20) {
   203         aRetIcon.AssignLiteral("camera-photo");
   204         break;
   205       }
   206       break;
   207   }
   209   if (aRetIcon.IsEmpty()) {
   210     if (HAS_AUDIO(aClass)) {
   211       /**
   212        * Property 'Icon' may be missed due to CoD of major class is TOY(0x08).
   213        * But we need to assign Icon as audio-card if service class is 'Audio'.
   214        * This is for PTS test case TC_AG_COD_BV_02_I. As HFP specification
   215        * defines that service class is 'Audio' can be considered as HFP HF.
   216        */
   217       aRetIcon.AssignLiteral("audio-card");
   218     } else {
   219       BT_LOGR("No icon to match class: %x", aClass);
   220     }
   221   }
   222 }
   224 static ControlPlayStatus
   225 PlayStatusStringToControlPlayStatus(const nsAString& aPlayStatus)
   226 {
   227   ControlPlayStatus playStatus = ControlPlayStatus::PLAYSTATUS_UNKNOWN;
   228   if (aPlayStatus.EqualsLiteral("STOPPED")) {
   229     playStatus = ControlPlayStatus::PLAYSTATUS_STOPPED;
   230   } else if (aPlayStatus.EqualsLiteral("PLAYING")) {
   231     playStatus = ControlPlayStatus::PLAYSTATUS_PLAYING;
   232   } else if (aPlayStatus.EqualsLiteral("PAUSED")) {
   233     playStatus = ControlPlayStatus::PLAYSTATUS_PAUSED;
   234   } else if (aPlayStatus.EqualsLiteral("FWD_SEEK")) {
   235     playStatus = ControlPlayStatus::PLAYSTATUS_FWD_SEEK;
   236   } else if (aPlayStatus.EqualsLiteral("REV_SEEK")) {
   237     playStatus = ControlPlayStatus::PLAYSTATUS_REV_SEEK;
   238   } else if (aPlayStatus.EqualsLiteral("ERROR")) {
   239     playStatus = ControlPlayStatus::PLAYSTATUS_ERROR;
   240   }
   242   return playStatus;
   243 }
   245 static bool
   246 IsReady()
   247 {
   248   if (!sBtInterface || !sIsBtEnabled) {
   249     BT_LOGR("Warning! Bluetooth Service is not ready");
   250     return false;
   251   }
   252   return true;
   253 }
   255 static void
   256 AdapterStateChangeCallback(bt_state_t aStatus)
   257 {
   258   MOZ_ASSERT(!NS_IsMainThread());
   260   BT_LOGR("BT_STATE %d", aStatus);
   262   sIsBtEnabled = (aStatus == BT_STATE_ON);
   264   nsRefPtr<nsRunnable> runnable =
   265     new BluetoothService::ToggleBtAck(sIsBtEnabled);
   266   if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
   267     BT_WARNING("Failed to dispatch to main thread!");
   268     return;
   269   }
   271   if (sIsBtEnabled &&
   272       NS_FAILED(NS_DispatchToMainThread(new SetupAfterEnabledTask()))) {
   273     BT_WARNING("Failed to dispatch to main thread!");
   274   }
   275 }
   277 /**
   278  * AdapterPropertiesCallback will be called after enable() but before
   279  * AdapterStateChangeCallback sIsBtEnabled get updated. At that moment, both
   280  * BluetoothManager/BluetoothAdapter does not register observer yet.
   281  */
   282 static void
   283 AdapterPropertiesCallback(bt_status_t aStatus, int aNumProperties,
   284                           bt_property_t *aProperties)
   285 {
   286   MOZ_ASSERT(!NS_IsMainThread());
   288   BluetoothValue propertyValue;
   289   InfallibleTArray<BluetoothNamedValue> props;
   291   for (int i = 0; i < aNumProperties; i++) {
   292     bt_property_t p = aProperties[i];
   294     if (p.type == BT_PROPERTY_BDADDR) {
   295       BdAddressTypeToString((bt_bdaddr_t*)p.val, sAdapterBdAddress);
   296       propertyValue = sAdapterBdAddress;
   297       BT_APPEND_NAMED_VALUE(props, "Address", propertyValue);
   298     } else if (p.type == BT_PROPERTY_BDNAME) {
   299       // Construct nsCString here because Bd name returned from bluedroid
   300       // is missing a null terminated character after SetProperty.
   301       propertyValue = sAdapterBdName = NS_ConvertUTF8toUTF16(
   302         nsCString((char*)p.val, p.len));
   303       BT_APPEND_NAMED_VALUE(props, "Name", propertyValue);
   304     } else if (p.type == BT_PROPERTY_ADAPTER_SCAN_MODE) {
   305       bt_scan_mode_t newMode = *(bt_scan_mode_t*)p.val;
   307       if (newMode == BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
   308         propertyValue = sAdapterDiscoverable = true;
   309       } else {
   310         propertyValue = sAdapterDiscoverable = false;
   311       }
   313       BT_APPEND_NAMED_VALUE(props, "Discoverable", propertyValue);
   314     } else if (p.type == BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT) {
   315       propertyValue = sAdapterDiscoverableTimeout = *(uint32_t*)p.val;
   316       BT_APPEND_NAMED_VALUE(props, "DiscoverableTimeout", propertyValue);
   317     } else if (p.type == BT_PROPERTY_ADAPTER_BONDED_DEVICES) {
   318       // We have to cache addresses of bonded devices. Unlike BlueZ,
   319       // bluedroid would not send an another BT_PROPERTY_ADAPTER_BONDED_DEVICES
   320       // event after bond completed
   321       bt_bdaddr_t* deviceBdAddressTypes = (bt_bdaddr_t*)p.val;
   322       int numOfAddresses = p.len / BLUETOOTH_ADDRESS_BYTES;
   323       BT_LOGD("Adapter property: BONDED_DEVICES. Count: %d", numOfAddresses);
   325       // Whenever reloading paired devices, force refresh
   326       sAdapterBondedAddressArray.Clear();
   328       for (int index = 0; index < numOfAddresses; index++) {
   329         nsAutoString deviceBdAddress;
   330         BdAddressTypeToString(deviceBdAddressTypes + index, deviceBdAddress);
   331         sAdapterBondedAddressArray.AppendElement(deviceBdAddress);
   332       }
   334       propertyValue = sAdapterBondedAddressArray;
   335       BT_APPEND_NAMED_VALUE(props, "Devices", propertyValue);
   336     } else if (p.type == BT_PROPERTY_UUIDS) {
   337       //FIXME: This will be implemented in the later patchset
   338       continue;
   339     } else {
   340       BT_LOGD("Unhandled adapter property type: %d", p.type);
   341       continue;
   342     }
   343   }
   345   NS_ENSURE_TRUE_VOID(props.Length() > 0);
   347   BluetoothValue value(props);
   348   BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
   349                          NS_LITERAL_STRING(KEY_ADAPTER), value);
   350   nsRefPtr<DistributeBluetoothSignalTask>
   351     t = new DistributeBluetoothSignalTask(signal);
   352   if (NS_FAILED(NS_DispatchToMainThread(t))) {
   353     BT_WARNING("Failed to dispatch to main thread!");
   354   }
   356   // bluedroid BTU task was stored in the task queue, see GKI_send_msg
   357   if (!sSetPropertyRunnableArray.IsEmpty()) {
   358     DispatchBluetoothReply(sSetPropertyRunnableArray[0], BluetoothValue(true),
   359                            EmptyString());
   360     sSetPropertyRunnableArray.RemoveElementAt(0);
   361   }
   362 }
   364 /**
   365  * RemoteDevicePropertiesCallback will be called, as the following conditions:
   366  * 1. When BT is turning on, bluedroid automatically execute this callback
   367  * 2. When get_remote_device_properties()
   368  */
   369 static void
   370 RemoteDevicePropertiesCallback(bt_status_t aStatus, bt_bdaddr_t *aBdAddress,
   371                                int aNumProperties, bt_property_t *aProperties)
   372 {
   373   MOZ_ASSERT(!NS_IsMainThread());
   375   if (sRequestedDeviceCountArray.IsEmpty()) {
   376     MOZ_ASSERT(sGetDeviceRunnableArray.IsEmpty());
   377     return;
   378   }
   380   sRequestedDeviceCountArray[0]--;
   382   InfallibleTArray<BluetoothNamedValue> props;
   384   nsString remoteDeviceBdAddress;
   385   BdAddressTypeToString(aBdAddress, remoteDeviceBdAddress);
   386   BT_APPEND_NAMED_VALUE(props, "Address", remoteDeviceBdAddress);
   388   for (int i = 0; i < aNumProperties; ++i) {
   389     bt_property_t p = aProperties[i];
   391     if (p.type == BT_PROPERTY_BDNAME) {
   392       BluetoothValue propertyValue = NS_ConvertUTF8toUTF16((char*)p.val);
   393       BT_APPEND_NAMED_VALUE(props, "Name", propertyValue);
   394     } else if (p.type == BT_PROPERTY_CLASS_OF_DEVICE) {
   395       uint32_t cod = *(uint32_t*)p.val;
   396       BT_APPEND_NAMED_VALUE(props, "Class", cod);
   398       nsString icon;
   399       ClassToIcon(cod, icon);
   400       BT_APPEND_NAMED_VALUE(props, "Icon", icon);
   401     } else {
   402       BT_LOGD("Other non-handled device properties. Type: %d", p.type);
   403     }
   404   }
   406   // Update to registered BluetoothDevice objects
   407   BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
   408                          remoteDeviceBdAddress, props);
   409   nsRefPtr<DistributeBluetoothSignalTask>
   410     t = new DistributeBluetoothSignalTask(signal);
   411   if (NS_FAILED(NS_DispatchToMainThread(t))) {
   412     BT_WARNING("Failed to dispatch to main thread!");
   413   }
   415   // Use address as the index
   416   sRemoteDevicesPack.AppendElement(
   417     BluetoothNamedValue(remoteDeviceBdAddress, props));
   419   if (sRequestedDeviceCountArray[0] == 0) {
   420     MOZ_ASSERT(!sGetDeviceRunnableArray.IsEmpty());
   422     if (sGetDeviceRunnableArray.IsEmpty()) {
   423       BT_LOGR("No runnable to return");
   424       return;
   425     }
   427     DispatchBluetoothReply(sGetDeviceRunnableArray[0],
   428                            sRemoteDevicesPack, EmptyString());
   430     // After firing it, clean up cache
   431     sRemoteDevicesPack.Clear();
   433     sRequestedDeviceCountArray.RemoveElementAt(0);
   434     sGetDeviceRunnableArray.RemoveElementAt(0);
   435   }
   436 }
   438 static void
   439 DeviceFoundCallback(int aNumProperties, bt_property_t *aProperties)
   440 {
   441   MOZ_ASSERT(!NS_IsMainThread());
   443   BluetoothValue propertyValue;
   444   InfallibleTArray<BluetoothNamedValue> propertiesArray;
   446   for (int i = 0; i < aNumProperties; i++) {
   447     bt_property_t p = aProperties[i];
   449     if (p.type == BT_PROPERTY_BDADDR) {
   450       nsString remoteDeviceBdAddress;
   451       BdAddressTypeToString((bt_bdaddr_t*)p.val, remoteDeviceBdAddress);
   452       propertyValue = remoteDeviceBdAddress;
   454       BT_APPEND_NAMED_VALUE(propertiesArray, "Address", propertyValue);
   455     } else if (p.type == BT_PROPERTY_BDNAME) {
   456       propertyValue = NS_ConvertUTF8toUTF16((char*)p.val);
   457       BT_APPEND_NAMED_VALUE(propertiesArray, "Name", propertyValue);
   458     } else if (p.type == BT_PROPERTY_CLASS_OF_DEVICE) {
   459       uint32_t cod = *(uint32_t*)p.val;
   460       propertyValue = cod;
   461       BT_APPEND_NAMED_VALUE(propertiesArray, "Class", propertyValue);
   463       nsString icon;
   464       ClassToIcon(cod, icon);
   465       propertyValue = icon;
   466       BT_APPEND_NAMED_VALUE(propertiesArray, "Icon", propertyValue);
   467     } else {
   468       BT_LOGD("Not handled remote device property: %d", p.type);
   469     }
   470   }
   472   BluetoothValue value = propertiesArray;
   473   BluetoothSignal signal(NS_LITERAL_STRING("DeviceFound"),
   474                          NS_LITERAL_STRING(KEY_ADAPTER), value);
   475   nsRefPtr<DistributeBluetoothSignalTask>
   476     t = new DistributeBluetoothSignalTask(signal);
   477   if (NS_FAILED(NS_DispatchToMainThread(t))) {
   478     BT_WARNING("Failed to dispatch to main thread!");
   479   }
   480 }
   482 static void
   483 DiscoveryStateChangedCallback(bt_discovery_state_t aState)
   484 {
   485   MOZ_ASSERT(!NS_IsMainThread());
   487   if (!sChangeDiscoveryRunnableArray.IsEmpty()) {
   488     BluetoothValue values(true);
   489     DispatchBluetoothReply(sChangeDiscoveryRunnableArray[0],
   490                            values, EmptyString());
   492     sChangeDiscoveryRunnableArray.RemoveElementAt(0);
   493   }
   494 }
   496 static void
   497 PinRequestCallback(bt_bdaddr_t* aRemoteBdAddress,
   498                    bt_bdname_t* aRemoteBdName, uint32_t aRemoteClass)
   499 {
   500   MOZ_ASSERT(!NS_IsMainThread());
   502   InfallibleTArray<BluetoothNamedValue> propertiesArray;
   503   nsAutoString remoteAddress;
   504   BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
   506   BT_APPEND_NAMED_VALUE(propertiesArray, "address", remoteAddress);
   507   BT_APPEND_NAMED_VALUE(propertiesArray, "method",
   508                         NS_LITERAL_STRING("pincode"));
   509   BT_APPEND_NAMED_VALUE(propertiesArray, "name",
   510                         NS_ConvertUTF8toUTF16(
   511                           (const char*)aRemoteBdName->name));
   513   BluetoothValue value = propertiesArray;
   514   BluetoothSignal signal(NS_LITERAL_STRING("RequestPinCode"),
   515                          NS_LITERAL_STRING(KEY_LOCAL_AGENT), value);
   516   nsRefPtr<DistributeBluetoothSignalTask>
   517     t = new DistributeBluetoothSignalTask(signal);
   518   if (NS_FAILED(NS_DispatchToMainThread(t))) {
   519     BT_WARNING("Failed to dispatch to main thread!");
   520   }
   521 }
   523 static void
   524 SspRequestCallback(bt_bdaddr_t* aRemoteBdAddress, bt_bdname_t* aRemoteBdName,
   525                    uint32_t aRemoteClass, bt_ssp_variant_t aPairingVariant,
   526                    uint32_t aPasskey)
   527 {
   528   MOZ_ASSERT(!NS_IsMainThread());
   530   InfallibleTArray<BluetoothNamedValue> propertiesArray;
   531   nsAutoString remoteAddress;
   532   BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
   534   BT_APPEND_NAMED_VALUE(propertiesArray, "address", remoteAddress);
   535   BT_APPEND_NAMED_VALUE(propertiesArray, "method",
   536                         NS_LITERAL_STRING("confirmation"));
   537   BT_APPEND_NAMED_VALUE(propertiesArray, "name",
   538                         NS_ConvertUTF8toUTF16(
   539                           (const char*)aRemoteBdName->name));
   540   BT_APPEND_NAMED_VALUE(propertiesArray, "passkey", aPasskey);
   542   BluetoothValue value = propertiesArray;
   543   BluetoothSignal signal(NS_LITERAL_STRING("RequestConfirmation"),
   544                          NS_LITERAL_STRING(KEY_LOCAL_AGENT), value);
   545   nsRefPtr<DistributeBluetoothSignalTask>
   546     t = new DistributeBluetoothSignalTask(signal);
   547   if (NS_FAILED(NS_DispatchToMainThread(t))) {
   548     BT_WARNING("Failed to dispatch to main thread!");
   549   }
   550 }
   552 static void
   553 BondStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
   554                          bt_bond_state_t aState)
   555 {
   556   MOZ_ASSERT(!NS_IsMainThread());
   558   nsAutoString remoteAddress;
   559   BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
   561   // We don't need to handle bonding state
   562   NS_ENSURE_TRUE_VOID(aState != BT_BOND_STATE_BONDING);
   563   NS_ENSURE_FALSE_VOID(aState == BT_BOND_STATE_BONDED &&
   564                        sAdapterBondedAddressArray.Contains(remoteAddress));
   565   bool bonded;
   566   if (aState == BT_BOND_STATE_NONE) {
   567     bonded = false;
   568     sAdapterBondedAddressArray.RemoveElement(remoteAddress);
   569   } else if (aState == BT_BOND_STATE_BONDED) {
   570     bonded = true;
   571     sAdapterBondedAddressArray.AppendElement(remoteAddress);
   572   }
   574   // Update bonded address list to BluetoothAdapter
   575   InfallibleTArray<BluetoothNamedValue> propertiesChangeArray;
   576   BT_APPEND_NAMED_VALUE(propertiesChangeArray, "Devices",
   577                         sAdapterBondedAddressArray);
   579   BluetoothValue value(propertiesChangeArray);
   580   BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
   581                          NS_LITERAL_STRING(KEY_ADAPTER),
   582                          BluetoothValue(propertiesChangeArray));
   583   NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
   585   // Update bonding status to gaia
   586   InfallibleTArray<BluetoothNamedValue> propertiesArray;
   587   BT_APPEND_NAMED_VALUE(propertiesArray, "address", remoteAddress);
   588   BT_APPEND_NAMED_VALUE(propertiesArray, "status", bonded);
   590   BluetoothSignal newSignal(NS_LITERAL_STRING(PAIRED_STATUS_CHANGED_ID),
   591                             NS_LITERAL_STRING(KEY_ADAPTER),
   592                             BluetoothValue(propertiesArray));
   593   NS_DispatchToMainThread(new DistributeBluetoothSignalTask(newSignal));
   595   if (bonded && !sBondingRunnableArray.IsEmpty()) {
   596     DispatchBluetoothReply(sBondingRunnableArray[0],
   597                            BluetoothValue(true), EmptyString());
   599     sBondingRunnableArray.RemoveElementAt(0);
   600   } else if (!bonded && !sUnbondingRunnableArray.IsEmpty()) {
   601     DispatchBluetoothReply(sUnbondingRunnableArray[0],
   602                            BluetoothValue(true), EmptyString());
   604     sUnbondingRunnableArray.RemoveElementAt(0);
   605   }
   606 }
   608 static void
   609 AclStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
   610                         bt_acl_state_t aState)
   611 {
   612   //FIXME: This will be implemented in the later patchset
   613 }
   615 static void
   616 CallbackThreadEvent(bt_cb_thread_evt evt)
   617 {
   618   //FIXME: This will be implemented in the later patchset
   619 }
   621 bt_callbacks_t sBluetoothCallbacks =
   622 {
   623   sizeof(sBluetoothCallbacks),
   624   AdapterStateChangeCallback,
   625   AdapterPropertiesCallback,
   626   RemoteDevicePropertiesCallback,
   627   DeviceFoundCallback,
   628   DiscoveryStateChangedCallback,
   629   PinRequestCallback,
   630   SspRequestCallback,
   631   BondStateChangedCallback,
   632   AclStateChangedCallback,
   633   CallbackThreadEvent
   634 };
   636 /**
   637  *  Static functions
   638  */
   639 static bool
   640 EnsureBluetoothHalLoad()
   641 {
   642   hw_module_t* module;
   643   hw_device_t* device;
   644   int err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
   645   if (err != 0) {
   646     BT_LOGR("Error: %s", strerror(err));
   647     return false;
   648   }
   649   module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
   650   sBtDevice = (bluetooth_device_t *)device;
   651   sBtInterface = sBtDevice->get_bluetooth_interface();
   653   int ret = sBtInterface->init(&sBluetoothCallbacks);
   654   if (ret != BT_STATUS_SUCCESS) {
   655     BT_LOGR("Error while setting the callbacks");
   656     sBtInterface = nullptr;
   657   }
   659   return true;
   660 }
   662 static nsresult
   663 StartStopGonkBluetooth(bool aShouldEnable)
   664 {
   665   MOZ_ASSERT(NS_IsMainThread());
   666   NS_ENSURE_TRUE(sBtInterface, NS_ERROR_FAILURE);
   668   if (sIsBtEnabled == aShouldEnable) {
   669     // Keep current enable status
   670     nsRefPtr<nsRunnable> runnable =
   671       new BluetoothService::ToggleBtAck(sIsBtEnabled);
   672     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
   673       BT_WARNING("Failed to dispatch to main thread!");
   674     }
   675     return NS_OK;
   676   }
   678   int ret = aShouldEnable ? sBtInterface->enable() : sBtInterface->disable();
   679   NS_ENSURE_TRUE(ret == BT_STATUS_SUCCESS, NS_ERROR_FAILURE);
   681   return NS_OK;
   682 }
   684 static void
   685 ReplyStatusError(BluetoothReplyRunnable* aBluetoothReplyRunnable,
   686                  int aStatusCode, const nsAString& aCustomMsg)
   687 {
   688   MOZ_ASSERT(aBluetoothReplyRunnable, "Reply runnable is nullptr");
   690   BT_LOGR("error code(%d)", aStatusCode);
   692   nsAutoString replyError;
   693   replyError.Assign(aCustomMsg);
   695   if (aStatusCode == BT_STATUS_BUSY) {
   696     replyError.AppendLiteral(":BT_STATUS_BUSY");
   697   } else if (aStatusCode == BT_STATUS_NOT_READY) {
   698     replyError.AppendLiteral(":BT_STATUS_NOT_READY");
   699   } else if (aStatusCode == BT_STATUS_DONE) {
   700     replyError.AppendLiteral(":BT_STATUS_DONE");
   701   } else if (aStatusCode == BT_STATUS_AUTH_FAILURE) {
   702     replyError.AppendLiteral(":BT_STATUS_AUTH_FAILURE");
   703   } else if (aStatusCode == BT_STATUS_RMT_DEV_DOWN) {
   704     replyError.AppendLiteral(":BT_STATUS_RMT_DEV_DOWN");
   705   } else if (aStatusCode == BT_STATUS_FAIL) {
   706     replyError.AppendLiteral(":BT_STATUS_FAIL");
   707   }
   709   DispatchBluetoothReply(aBluetoothReplyRunnable, BluetoothValue(true),
   710                          replyError);
   711 }
   713 /**
   714  *  Member functions
   715  */
   716 BluetoothServiceBluedroid::BluetoothServiceBluedroid()
   717 {
   718   if (!EnsureBluetoothHalLoad()) {
   719     BT_LOGR("Error! Failed to load bluedroid library.");
   720     return;
   721   }
   723   // Register all the bluedroid callbacks before enable() get called
   724   // It is required to register a2dp callbacks before a2dp media task starts up.
   725   BluetoothHfpManager::Get();
   726   BluetoothA2dpManager::Get();
   727 }
   729 BluetoothServiceBluedroid::~BluetoothServiceBluedroid()
   730 {
   731 }
   733 nsresult
   734 BluetoothServiceBluedroid::StartInternal()
   735 {
   736   MOZ_ASSERT(NS_IsMainThread());
   738   nsresult ret = StartStopGonkBluetooth(true);
   739   if (NS_FAILED(ret)) {
   740     nsRefPtr<nsRunnable> runnable =
   741       new BluetoothService::ToggleBtAck(false);
   742     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
   743       BT_WARNING("Failed to dispatch to main thread!");
   744     }
   745     BT_LOGR("Error");
   746   }
   748   return ret;
   749 }
   751 nsresult
   752 BluetoothServiceBluedroid::StopInternal()
   753 {
   754   MOZ_ASSERT(NS_IsMainThread());
   756   nsresult ret = StartStopGonkBluetooth(false);
   757   if (NS_FAILED(ret)) {
   758     nsRefPtr<nsRunnable> runnable =
   759       new BluetoothService::ToggleBtAck(true);
   760     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
   761       BT_WARNING("Failed to dispatch to main thread!");
   762     }
   763     BT_LOGR("Error");
   764   }
   766   return ret;
   767 }
   769 nsresult
   770 BluetoothServiceBluedroid::GetDefaultAdapterPathInternal(
   771   BluetoothReplyRunnable* aRunnable)
   772 {
   773   MOZ_ASSERT(NS_IsMainThread());
   775   nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
   777   BluetoothValue v = InfallibleTArray<BluetoothNamedValue>();
   779   BT_APPEND_NAMED_VALUE(v.get_ArrayOfBluetoothNamedValue(),
   780                         "Address", sAdapterBdAddress);
   782   BT_APPEND_NAMED_VALUE(v.get_ArrayOfBluetoothNamedValue(),
   783                         "Name", sAdapterBdName);
   785   BT_APPEND_NAMED_VALUE(v.get_ArrayOfBluetoothNamedValue(),
   786                         "Discoverable", sAdapterDiscoverable);
   788   BT_APPEND_NAMED_VALUE(v.get_ArrayOfBluetoothNamedValue(),
   789                         "DiscoverableTimeout", sAdapterDiscoverableTimeout);
   791   BT_APPEND_NAMED_VALUE(v.get_ArrayOfBluetoothNamedValue(),
   792                         "Devices", sAdapterBondedAddressArray);
   794   nsAutoString replyError;
   795   DispatchBluetoothReply(runnable.get(), v, replyError);
   797   unused << runnable.forget(); // picked up in DispatchBluetoothReply
   799   return NS_OK;
   800 }
   802 nsresult
   803 BluetoothServiceBluedroid::GetConnectedDevicePropertiesInternal(
   804   uint16_t aServiceUuid, BluetoothReplyRunnable* aRunnable)
   805 {
   806   MOZ_ASSERT(NS_IsMainThread());
   808   if (!IsReady()) {
   809     NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
   810     DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
   811     return NS_OK;
   812   }
   814   BluetoothProfileManagerBase* profile =
   815     BluetoothUuidHelper::GetBluetoothProfileManager(aServiceUuid);
   816   if (!profile) {
   817     InfallibleTArray<BluetoothNamedValue> emptyArr;
   818     DispatchBluetoothReply(aRunnable, emptyArr,
   819                            NS_LITERAL_STRING(ERR_UNKNOWN_PROFILE));
   820     return NS_OK;
   821   }
   823   nsTArray<nsString> deviceAddresses;
   824   if (profile->IsConnected()) {
   825     nsString address;
   826     profile->GetAddress(address);
   827     deviceAddresses.AppendElement(address);
   828   }
   830   int requestedDeviceCount = deviceAddresses.Length();
   831   if (requestedDeviceCount == 0) {
   832     InfallibleTArray<BluetoothNamedValue> emptyArr;
   833     DispatchBluetoothReply(aRunnable, emptyArr, EmptyString());
   834     return NS_OK;
   835   }
   837   for (int i = 0; i < requestedDeviceCount; i++) {
   838     // Retrieve all properties of devices
   839     bt_bdaddr_t addressType;
   840     StringToBdAddressType(deviceAddresses[i], &addressType);
   842     int ret = sBtInterface->get_remote_device_properties(&addressType);
   843     if (ret != BT_STATUS_SUCCESS) {
   844       DispatchBluetoothReply(aRunnable, BluetoothValue(true),
   845                              NS_LITERAL_STRING("GetConnectedDeviceFailed"));
   846       return NS_OK;
   847     }
   848   }
   850   sRequestedDeviceCountArray.AppendElement(requestedDeviceCount);
   851   sGetDeviceRunnableArray.AppendElement(aRunnable);
   853   return NS_OK;
   854 }
   856 nsresult
   857 BluetoothServiceBluedroid::GetPairedDevicePropertiesInternal(
   858   const nsTArray<nsString>& aDeviceAddress, BluetoothReplyRunnable* aRunnable)
   859 {
   860   MOZ_ASSERT(NS_IsMainThread());
   862   if (!IsReady()) {
   863     NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
   864     DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
   865     return NS_OK;
   866   }
   868   int requestedDeviceCount = aDeviceAddress.Length();
   869   if (requestedDeviceCount == 0) {
   870     InfallibleTArray<BluetoothNamedValue> emptyArr;
   871     DispatchBluetoothReply(aRunnable, BluetoothValue(emptyArr), EmptyString());
   872     return NS_OK;
   873   }
   875   for (int i = 0; i < requestedDeviceCount; i++) {
   876     // Retrieve all properties of devices
   877     bt_bdaddr_t addressType;
   878     StringToBdAddressType(aDeviceAddress[i], &addressType);
   879     int ret = sBtInterface->get_remote_device_properties(&addressType);
   880     if (ret != BT_STATUS_SUCCESS) {
   881       DispatchBluetoothReply(aRunnable, BluetoothValue(true),
   882                              NS_LITERAL_STRING("GetPairedDeviceFailed"));
   883       return NS_OK;
   884     }
   885   }
   887   sRequestedDeviceCountArray.AppendElement(requestedDeviceCount);
   888   sGetDeviceRunnableArray.AppendElement(aRunnable);
   890   return NS_OK;
   891 }
   893 nsresult
   894 BluetoothServiceBluedroid::StartDiscoveryInternal(
   895   BluetoothReplyRunnable* aRunnable)
   896 {
   897   MOZ_ASSERT(NS_IsMainThread());
   899   if (!IsReady()) {
   900     NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
   901     DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
   903     return NS_OK;
   904   }
   905   int ret = sBtInterface->start_discovery();
   906   if (ret != BT_STATUS_SUCCESS) {
   907     ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("StartDiscovery"));
   909     return NS_OK;
   910   }
   912   sChangeDiscoveryRunnableArray.AppendElement(aRunnable);
   913   return NS_OK;
   914 }
   916 nsresult
   917 BluetoothServiceBluedroid::StopDiscoveryInternal(
   918   BluetoothReplyRunnable* aRunnable)
   919 {
   920   MOZ_ASSERT(NS_IsMainThread());
   922   if (!IsReady()) {
   923     NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
   924     DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
   925     return NS_OK;
   926   }
   928   int ret = sBtInterface->cancel_discovery();
   929   if (ret != BT_STATUS_SUCCESS) {
   930     ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("StopDiscovery"));
   931     return NS_OK;
   932   }
   934   sChangeDiscoveryRunnableArray.AppendElement(aRunnable);
   936   return NS_OK;
   937 }
   939 nsresult
   940 BluetoothServiceBluedroid::SetProperty(BluetoothObjectType aType,
   941                                        const BluetoothNamedValue& aValue,
   942                                        BluetoothReplyRunnable* aRunnable)
   943 {
   944   MOZ_ASSERT(NS_IsMainThread());
   946   if (!IsReady()) {
   947     NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
   948     DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
   950     return NS_OK;
   951   }
   953   const nsString propName = aValue.name();
   954   bt_property_t prop;
   955   bt_scan_mode_t scanMode;
   956   nsCString str;
   958   // For Bluedroid, it's necessary to check property name for SetProperty
   959   if (propName.EqualsLiteral("Name")) {
   960     prop.type = BT_PROPERTY_BDNAME;
   961   } else if (propName.EqualsLiteral("Discoverable")) {
   962     prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
   963   } else if (propName.EqualsLiteral("DiscoverableTimeout")) {
   964     prop.type = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT;
   965   } else {
   966     BT_LOGR("Warning: Property type is not supported yet, type: %d", prop.type);
   967   }
   969   if (aValue.value().type() == BluetoothValue::Tuint32_t) {
   970     // Set discoverable timeout
   971     prop.val = (void*)aValue.value().get_uint32_t();
   972   } else if (aValue.value().type() == BluetoothValue::TnsString) {
   973     // Set name
   974     str = NS_ConvertUTF16toUTF8(aValue.value().get_nsString());
   975     const char* name = str.get();
   976     prop.val = (void*)name;
   977     prop.len = strlen(name);
   978   } else if (aValue.value().type() == BluetoothValue::Tbool) {
   979     scanMode = aValue.value().get_bool() ?
   980                  BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE :
   981                  BT_SCAN_MODE_CONNECTABLE;
   983     prop.val = (void*)&scanMode;
   984     prop.len = sizeof(scanMode);
   985   } else {
   986     BT_LOGR("SetProperty but the property cannot be recognized correctly.");
   987     return NS_OK;
   988   }
   990   sSetPropertyRunnableArray.AppendElement(aRunnable);
   992   int ret = sBtInterface->set_adapter_property(&prop);
   993   if (ret != BT_STATUS_SUCCESS) {
   994     ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("SetProperty"));
   995   }
   997   return NS_OK;
   998 }
  1000 nsresult
  1001 BluetoothServiceBluedroid::GetServiceChannel(
  1002   const nsAString& aDeviceAddress,
  1003   const nsAString& aServiceUuid,
  1004   BluetoothProfileManagerBase* aManager)
  1006   return NS_OK;
  1009 bool
  1010 BluetoothServiceBluedroid::UpdateSdpRecords(
  1011   const nsAString& aDeviceAddress,
  1012   BluetoothProfileManagerBase* aManager)
  1014   return true;
  1017 nsresult
  1018 BluetoothServiceBluedroid::CreatePairedDeviceInternal(
  1019   const nsAString& aDeviceAddress, int aTimeout,
  1020   BluetoothReplyRunnable* aRunnable)
  1022   MOZ_ASSERT(NS_IsMainThread());
  1024   if (!IsReady()) {
  1025     NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
  1026     DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
  1027     return NS_OK;
  1030   bt_bdaddr_t remoteAddress;
  1031   StringToBdAddressType(aDeviceAddress, &remoteAddress);
  1033   int ret = sBtInterface->create_bond(&remoteAddress);
  1034   if (ret != BT_STATUS_SUCCESS) {
  1035     ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("CreatedPairedDevice"));
  1036   } else {
  1037     sBondingRunnableArray.AppendElement(aRunnable);
  1040   return NS_OK;
  1043 nsresult
  1044 BluetoothServiceBluedroid::RemoveDeviceInternal(
  1045   const nsAString& aDeviceAddress, BluetoothReplyRunnable* aRunnable)
  1047   MOZ_ASSERT(NS_IsMainThread());
  1049   if (!IsReady()) {
  1050     NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
  1051     DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
  1052     return NS_OK;
  1055   bt_bdaddr_t remoteAddress;
  1056   StringToBdAddressType(aDeviceAddress, &remoteAddress);
  1058   int ret = sBtInterface->remove_bond(&remoteAddress);
  1059   if (ret != BT_STATUS_SUCCESS) {
  1060     ReplyStatusError(aRunnable, ret,
  1061                      NS_LITERAL_STRING("RemoveDevice"));
  1062   } else {
  1063     sUnbondingRunnableArray.AppendElement(aRunnable);
  1066   return NS_OK;
  1069 bool
  1070 BluetoothServiceBluedroid::SetPinCodeInternal(
  1071   const nsAString& aDeviceAddress, const nsAString& aPinCode,
  1072   BluetoothReplyRunnable* aRunnable)
  1074   MOZ_ASSERT(NS_IsMainThread());
  1076   if (!IsReady()) {
  1077     NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
  1078     DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
  1079     return false;
  1082   bt_bdaddr_t remoteAddress;
  1083   StringToBdAddressType(aDeviceAddress, &remoteAddress);
  1085   int ret = sBtInterface->pin_reply(
  1086       &remoteAddress, true, aPinCode.Length(),
  1087       (bt_pin_code_t*)NS_ConvertUTF16toUTF8(aPinCode).get());
  1089   if (ret != BT_STATUS_SUCCESS) {
  1090     ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("SetPinCode"));
  1091   } else {
  1092     DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
  1095   return true;
  1098 bool
  1099 BluetoothServiceBluedroid::SetPasskeyInternal(
  1100   const nsAString& aDeviceAddress, uint32_t aPasskey,
  1101   BluetoothReplyRunnable* aRunnable)
  1103   return true;
  1106 bool
  1107 BluetoothServiceBluedroid::SetPairingConfirmationInternal(
  1108   const nsAString& aDeviceAddress, bool aConfirm,
  1109   BluetoothReplyRunnable* aRunnable)
  1111   MOZ_ASSERT(NS_IsMainThread());
  1113   if (!IsReady()) {
  1114     NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
  1115     DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
  1116     return false;
  1119   bt_bdaddr_t remoteAddress;
  1120   StringToBdAddressType(aDeviceAddress, &remoteAddress);
  1122   int ret = sBtInterface->ssp_reply(&remoteAddress, (bt_ssp_variant_t)0,
  1123                                     aConfirm, 0);
  1124   if (ret != BT_STATUS_SUCCESS) {
  1125     ReplyStatusError(aRunnable, ret,
  1126                      NS_LITERAL_STRING("SetPairingConfirmation"));
  1127   } else {
  1128     DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
  1131   return true;
  1134 bool
  1135 BluetoothServiceBluedroid::SetAuthorizationInternal(
  1136   const nsAString& aDeviceAddress, bool aAllow,
  1137   BluetoothReplyRunnable* aRunnable)
  1139   return true;
  1142 nsresult
  1143 BluetoothServiceBluedroid::PrepareAdapterInternal()
  1145   return NS_OK;
  1148 static void
  1149 NextBluetoothProfileController()
  1151   MOZ_ASSERT(NS_IsMainThread());
  1153   // First, remove the task at the front which has been already done.
  1154   NS_ENSURE_FALSE_VOID(sControllerArray.IsEmpty());
  1155   sControllerArray.RemoveElementAt(0);
  1156   // Re-check if the task array is empty, if it's not, the next task will begin.
  1157   NS_ENSURE_FALSE_VOID(sControllerArray.IsEmpty());
  1158   sControllerArray[0]->StartSession();
  1161 static void
  1162 ConnectDisconnect(bool aConnect, const nsAString& aDeviceAddress,
  1163                   BluetoothReplyRunnable* aRunnable,
  1164                   uint16_t aServiceUuid, uint32_t aCod = 0)
  1166   MOZ_ASSERT(NS_IsMainThread());
  1167   MOZ_ASSERT(aRunnable);
  1169   BluetoothProfileController* controller =
  1170     new BluetoothProfileController(aConnect, aDeviceAddress, aRunnable,
  1171                                    NextBluetoothProfileController,
  1172                                    aServiceUuid, aCod);
  1173   sControllerArray.AppendElement(controller);
  1175   /**
  1176    * If the request is the first element of the quene, start from here. Note
  1177    * that other request is pushed into the quene and is popped out after the
  1178    * first one is completed. See NextBluetoothProfileController() for details.
  1179    */
  1180   if (sControllerArray.Length() == 1) {
  1181     sControllerArray[0]->StartSession();
  1185 const bt_interface_t*
  1186 BluetoothServiceBluedroid::GetBluetoothInterface()
  1188   return sBtInterface;
  1191 void
  1192 BluetoothServiceBluedroid::Connect(const nsAString& aDeviceAddress,
  1193                                    uint32_t aCod,
  1194                                    uint16_t aServiceUuid,
  1195                                    BluetoothReplyRunnable* aRunnable)
  1197   ConnectDisconnect(true, aDeviceAddress, aRunnable, aServiceUuid, aCod);
  1200 bool
  1201 BluetoothServiceBluedroid::IsConnected(uint16_t aProfileId)
  1203   return true;
  1206 void
  1207 BluetoothServiceBluedroid::Disconnect(
  1208   const nsAString& aDeviceAddress, uint16_t aServiceUuid,
  1209   BluetoothReplyRunnable* aRunnable)
  1211   ConnectDisconnect(false, aDeviceAddress, aRunnable, aServiceUuid);
  1214 void
  1215 BluetoothServiceBluedroid::SendFile(const nsAString& aDeviceAddress,
  1216                                     BlobParent* aBlobParent,
  1217                                     BlobChild* aBlobChild,
  1218                                     BluetoothReplyRunnable* aRunnable)
  1220   MOZ_ASSERT(NS_IsMainThread());
  1222   // Currently we only support one device sending one file at a time,
  1223   // so we don't need aDeviceAddress here because the target device
  1224   // has been determined when calling 'Connect()'. Nevertheless, keep
  1225   // it for future use.
  1226   BluetoothOppManager* opp = BluetoothOppManager::Get();
  1227   nsAutoString errorStr;
  1228   if (!opp || !opp->SendFile(aDeviceAddress, aBlobParent)) {
  1229     errorStr.AssignLiteral("Calling SendFile() failed");
  1232   DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
  1235 void
  1236 BluetoothServiceBluedroid::SendFile(const nsAString& aDeviceAddress,
  1237                                     nsIDOMBlob* aBlob,
  1238                                     BluetoothReplyRunnable* aRunnable)
  1240   MOZ_ASSERT(NS_IsMainThread());
  1242   // Currently we only support one device sending one file at a time,
  1243   // so we don't need aDeviceAddress here because the target device
  1244   // has been determined when calling 'Connect()'. Nevertheless, keep
  1245   // it for future use.
  1246   BluetoothOppManager* opp = BluetoothOppManager::Get();
  1247   nsAutoString errorStr;
  1248   if (!opp || !opp->SendFile(aDeviceAddress, aBlob)) {
  1249     errorStr.AssignLiteral("Calling SendFile() failed");
  1252   DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
  1255 void
  1256 BluetoothServiceBluedroid::StopSendingFile(const nsAString& aDeviceAddress,
  1257                                            BluetoothReplyRunnable* aRunnable)
  1259   MOZ_ASSERT(NS_IsMainThread());
  1261   // Currently we only support one device sending one file at a time,
  1262   // so we don't need aDeviceAddress here because the target device
  1263   // has been determined when calling 'Connect()'. Nevertheless, keep
  1264   // it for future use.
  1265   BluetoothOppManager* opp = BluetoothOppManager::Get();
  1266   nsAutoString errorStr;
  1267   if (!opp || !opp->StopSendingFile()) {
  1268     errorStr.AssignLiteral("Calling StopSendingFile() failed");
  1271   DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
  1274 void
  1275 BluetoothServiceBluedroid::ConfirmReceivingFile(
  1276   const nsAString& aDeviceAddress, bool aConfirm,
  1277   BluetoothReplyRunnable* aRunnable)
  1279   MOZ_ASSERT(NS_IsMainThread(), "Must be called from main thread!");
  1281   // Currently we only support one device sending one file at a time,
  1282   // so we don't need aDeviceAddress here because the target device
  1283   // has been determined when calling 'Connect()'. Nevertheless, keep
  1284   // it for future use.
  1285   BluetoothOppManager* opp = BluetoothOppManager::Get();
  1286   nsAutoString errorStr;
  1287   if (!opp || !opp->ConfirmReceivingFile(aConfirm)) {
  1288     errorStr.AssignLiteral("Calling ConfirmReceivingFile() failed");
  1291   DispatchBluetoothReply(aRunnable, BluetoothValue(true), errorStr);
  1294 void
  1295 BluetoothServiceBluedroid::ConnectSco(BluetoothReplyRunnable* aRunnable)
  1297   MOZ_ASSERT(NS_IsMainThread());
  1299   BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
  1300   if (!hfp || !hfp->ConnectSco()) {
  1301     NS_NAMED_LITERAL_STRING(replyError, "Calling ConnectSco() failed");
  1302     DispatchBluetoothReply(aRunnable, BluetoothValue(), replyError);
  1303     return;
  1306   DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
  1309 void
  1310 BluetoothServiceBluedroid::DisconnectSco(BluetoothReplyRunnable* aRunnable)
  1312   MOZ_ASSERT(NS_IsMainThread());
  1314   BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
  1315   if (!hfp || !hfp->DisconnectSco()) {
  1316     NS_NAMED_LITERAL_STRING(replyError, "Calling DisconnectSco() failed");
  1317     DispatchBluetoothReply(aRunnable, BluetoothValue(), replyError);
  1318     return;
  1321   DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
  1324 void
  1325 BluetoothServiceBluedroid::IsScoConnected(BluetoothReplyRunnable* aRunnable)
  1327   MOZ_ASSERT(NS_IsMainThread());
  1329   BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
  1330   if (!hfp) {
  1331     NS_NAMED_LITERAL_STRING(replyError, "Fail to get BluetoothHfpManager");
  1332     DispatchBluetoothReply(aRunnable, BluetoothValue(), replyError);
  1333     return;
  1336   DispatchBluetoothReply(aRunnable, hfp->IsScoConnected(), EmptyString());
  1339 void
  1340 BluetoothServiceBluedroid::SendMetaData(const nsAString& aTitle,
  1341                                         const nsAString& aArtist,
  1342                                         const nsAString& aAlbum,
  1343                                         int64_t aMediaNumber,
  1344                                         int64_t aTotalMediaCount,
  1345                                         int64_t aDuration,
  1346                                         BluetoothReplyRunnable* aRunnable)
  1348   BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
  1349   if (a2dp) {
  1350     a2dp->UpdateMetaData(aTitle, aArtist, aAlbum, aMediaNumber,
  1351                          aTotalMediaCount, aDuration);
  1353   DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
  1356 void
  1357 BluetoothServiceBluedroid::SendPlayStatus(
  1358   int64_t aDuration, int64_t aPosition,
  1359   const nsAString& aPlayStatus,
  1360   BluetoothReplyRunnable* aRunnable)
  1362   BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
  1363   if (a2dp) {
  1364     ControlPlayStatus playStatus =
  1365       PlayStatusStringToControlPlayStatus(aPlayStatus);
  1366     a2dp->UpdatePlayStatus(aDuration, aPosition, playStatus);
  1368   DispatchBluetoothReply(aRunnable, BluetoothValue(true), EmptyString());
  1371 void
  1372 BluetoothServiceBluedroid::UpdatePlayStatus(
  1373   uint32_t aDuration, uint32_t aPosition, ControlPlayStatus aPlayStatus)
  1375   // We don't need this function for bluedroid.
  1376   // In bluez, it only calls dbus api
  1377   // But it does not update BluetoothA2dpManager member fields
  1378   MOZ_ASSERT(false);
  1381 nsresult
  1382 BluetoothServiceBluedroid::SendSinkMessage(const nsAString& aDeviceAddresses,
  1383                                            const nsAString& aMessage)
  1385   return NS_OK;
  1388 nsresult
  1389 BluetoothServiceBluedroid::SendInputMessage(const nsAString& aDeviceAddresses,
  1390                                             const nsAString& aMessage)
  1392   return NS_OK;
  1395 void
  1396 BluetoothServiceBluedroid::AnswerWaitingCall(BluetoothReplyRunnable* aRunnable)
  1400 void
  1401 BluetoothServiceBluedroid::IgnoreWaitingCall(BluetoothReplyRunnable* aRunnable)
  1405 void
  1406 BluetoothServiceBluedroid::ToggleCalls(BluetoothReplyRunnable* aRunnable)

mercurial