Bug 1015819 - Part 2: [bluez] Restore CoD value based on SDP records. r=echou, f=btian, a=2.0+
authorShawn Huang <shuang@mozilla.com>
Tue, 24 Jun 2014 02:36:00 -0400
changeset 207340 cf58e8801181f2907ce7e45c74356bab0d245432
parent 207339 444dc23190f4d0bfdcdf69378531dcb1abb22569
child 207341 1b0b34e40c0de4e7ca25b13a402763b29f0e6ec9
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechou, 2
bugs1015819
milestone32.0a2
Bug 1015819 - Part 2: [bluez] Restore CoD value based on SDP records. r=echou, f=btian, a=2.0+
dom/bluetooth/bluez/BluetoothDBusService.cpp
--- a/dom/bluetooth/bluez/BluetoothDBusService.cpp
+++ b/dom/bluetooth/bluez/BluetoothDBusService.cpp
@@ -83,19 +83,22 @@ USING_BLUETOOTH_NAMESPACE
 #define ERR_AVRCP_IS_DISCONNECTED     "AvrcpIsDisconnected"
 
 /**
  * To not lock Bluetooth switch button on Settings UI because of any accident,
  * we will force disabling Bluetooth 5 seconds after the user requesting to
  * turn off Bluetooth.
  */
 #define TIMEOUT_FORCE_TO_DISABLE_BT 5
-
 #define BT_LAZY_THREAD_TIMEOUT_MS 3000
 
+// Set Class of Device value bit
+#define SET_AUDIO_BIT(cod) (cod |= 0x200000)
+#define SET_RENDERING_BIT(cod) (cod |= 0x40000)
+
 #ifdef MOZ_WIDGET_GONK
 class Bluedroid
 {
   struct ScopedDlHandleTraits
   {
     typedef void* type;
     static void* empty()
     {
@@ -816,25 +819,27 @@ SinkDisconnectCallback(DBusMessage* aMsg
 }
 
 static bool
 HasAudioService(uint32_t aCodValue)
 {
   return ((aCodValue & 0x200000) == 0x200000);
 }
 
-static bool
-ContainsIcon(const InfallibleTArray<BluetoothNamedValue>& aProperties)
+static int
+FindProperty(const InfallibleTArray<BluetoothNamedValue>& aProperties,
+             const char* aPropertyType)
 {
-  for (uint8_t i = 0; i < aProperties.Length(); i++) {
-    if (aProperties[i].name().EqualsLiteral("Icon")) {
-      return true;
+  for (int i = 0; i < aProperties.Length(); ++i) {
+    if (aProperties[i].name().EqualsASCII(aPropertyType)) {
+      return i;
     }
   }
-  return false;
+
+  return -1;
 }
 
 static bool
 GetProperty(DBusMessageIter aIter, const Properties* aPropertyTypes,
             int aPropertyTypeLen, int* aPropIndex,
             InfallibleTArray<BluetoothNamedValue>& aProperties)
 {
   /**
@@ -1761,17 +1766,17 @@ EventFilter(DBusConnection* aConn, DBusM
       // have all of the information to correctly build the device.
       nsAutoString address = NS_ConvertUTF8toUTF16(addr);
       properties.AppendElement(
         BluetoothNamedValue(NS_LITERAL_STRING("Address"), address));
       properties.AppendElement(
         BluetoothNamedValue(NS_LITERAL_STRING("Path"),
                             GetObjectPathFromAddress(signalPath, address)));
 
-      if (!ContainsIcon(properties)) {
+      if (FindProperty(properties, "Icon") < 0) {
         for (uint32_t i = 0; i < properties.Length(); i++) {
           // It is possible that property Icon missed due to CoD of major
           // class is TOY but service class is "Audio", we need to assign
           // Icon as audio-card. This is for PTS test TC_AG_COD_BV_02_I.
           // As HFP specification defined that
           // service class is "Audio" can be considered as HFP AG.
           if (properties[i].name().EqualsLiteral("Class")) {
             if (HasAudioService(properties[i].value().get_uint32_t())) {
@@ -2683,30 +2688,64 @@ public:
     devicePropertiesArray.AppendElement(
       BluetoothNamedValue(NS_LITERAL_STRING("Path"), mObjectPath));
 
     // It is possible that property Icon missed due to CoD of major
     // class is TOY but service class is "Audio", we need to assign
     // Icon as audio-card. This is for PTS test TC_AG_COD_BV_02_I.
     // As HFP specification defined that
     // service class is "Audio" can be considered as HFP AG.
-    if (!ContainsIcon(devicePropertiesArray)) {
+    if (FindProperty(devicePropertiesArray, "Icon") < 0) {
       for (uint32_t j = 0; j < devicePropertiesArray.Length(); ++j) {
         BluetoothNamedValue& deviceProperty = devicePropertiesArray[j];
         if (deviceProperty.name().EqualsLiteral("Class")) {
           if (HasAudioService(deviceProperty.value().get_uint32_t())) {
             devicePropertiesArray.AppendElement(
               BluetoothNamedValue(NS_LITERAL_STRING("Icon"),
                                   NS_LITERAL_STRING("audio-card")));
           }
           break;
         }
       }
     }
 
+    // Check whether the properties array contains CoD. If it doesn't, fallback to restore
+    // CoD value. This usually happens due to NFC directly triggers pairing that
+    // makes bluez not update CoD value.
+    if (FindProperty(devicePropertiesArray, "Class") < 0) {
+      uint32_t cod = 0;
+      int uuidIndex = FindProperty(devicePropertiesArray, "UUIDs");
+      if (uuidIndex >= 0) {
+        BluetoothNamedValue& deviceProperty = devicePropertiesArray[uuidIndex];
+        const InfallibleTArray<nsString>& uuids =
+          deviceProperty.value().get_ArrayOfnsString();
+
+        for (uint32_t i = 0; i < uuids.Length(); ++i) {
+          BluetoothServiceClass serviceClass =
+            BluetoothUuidHelper::GetBluetoothServiceClass(uuids[i]);
+          if (serviceClass == BluetoothServiceClass::HANDSFREE ||
+              serviceClass == BluetoothServiceClass::HEADSET) {
+            BT_LOGD("Restore CoD value, set Audio bit");
+            SET_AUDIO_BIT(cod);
+          } else if (serviceClass == BluetoothServiceClass::A2DP_SINK) {
+            BT_LOGD("Restore CoD value, set A2DP_SINK bit");
+            SET_RENDERING_BIT(cod);
+          }
+        }
+
+        // Add both CoD and Icon information anyway, 'audio-card' refers to
+        // 'Audio' device.
+        devicePropertiesArray.AppendElement(
+          BluetoothNamedValue(NS_LITERAL_STRING("Class"), cod));
+        devicePropertiesArray.AppendElement(
+          BluetoothNamedValue(NS_LITERAL_STRING("Icon"),
+            NS_LITERAL_STRING("audio-card")));
+      }
+    }
+
     if (mFilterFunc(deviceProperties)) {
       mValues.get_ArrayOfBluetoothNamedValue().AppendElement(
         BluetoothNamedValue(mDeviceAddresses[i], deviceProperties));
     }
 
     ProcessRemainingDeviceAddresses();
   }