diff --git a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp index 47b4caa0f75..296d6486f7f 100644 --- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp +++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp @@ -40,7 +40,6 @@ } \ } while(0) -#define MAX_UUID_SIZE 16 // Audio: Major service class = 0x100 (Bit 21 is set) #define SET_AUDIO_BIT(cod) (cod |= 0x200000) // Rendering: Major service class = 0x20 (Bit 18 is set) @@ -50,12 +49,9 @@ using namespace mozilla; using namespace mozilla::ipc; USING_BLUETOOTH_NAMESPACE -// TODO: Non thread-safe static variables static nsString sAdapterBdAddress; static nsString sAdapterBdName; static InfallibleTArray sAdapterBondedAddressArray; - -// Static variables below should only be used on *main thread* static BluetoothInterface* sBtInterface; static nsTArray > sControllerArray; static InfallibleTArray sRemoteDevicesPack; @@ -64,41 +60,12 @@ static nsTArray > sSetPropertyRunnableArray; static nsTArray > sGetDeviceRunnableArray; static nsTArray > sBondingRunnableArray; static nsTArray > sUnbondingRunnableArray; - -// Static variables below should only be used on *callback thread* - - -// Atomic static variables -static Atomic sAdapterDiscoverable(false); -static Atomic sAdapterDiscoverableTimeout(0); +static bool sAdapterDiscoverable(false); +static uint32_t sAdapterDiscoverableTimeout(0); /** * Classes only used in this file */ -class DistributeBluetoothSignalTask MOZ_FINAL : public nsRunnable -{ -public: - DistributeBluetoothSignalTask(const BluetoothSignal& aSignal) : - mSignal(aSignal) - { - } - - NS_IMETHOD - Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - BluetoothService* bs = BluetoothService::Get(); - NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE); - - bs->DistributeSignal(mSignal); - - return NS_OK; - } - -private: - BluetoothSignal mSignal; -}; class SetupAfterEnabledTask MOZ_FINAL : public nsRunnable { @@ -326,509 +293,6 @@ PlayStatusStringToControlPlayStatus(const nsAString& aPlayStatus) return playStatus; } -/** - * Bluedroid HAL callback functions - * - * Several callbacks are dispatched to main thread to avoid racing issues. - */ -static void -AdapterStateChangeCallback(bt_state_t aStatus) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - BT_LOGR("BT_STATE: %d", aStatus); - - bool isBtEnabled = (aStatus == BT_STATE_ON); - - if (!isBtEnabled && - NS_FAILED(NS_DispatchToMainThread(new CleanupTask()))) { - BT_WARNING("Failed to dispatch to main thread!"); - return; - } - - nsRefPtr runnable = - new BluetoothService::ToggleBtAck(isBtEnabled); - if (NS_FAILED(NS_DispatchToMainThread(runnable))) { - BT_WARNING("Failed to dispatch to main thread!"); - return; - } - - if (isBtEnabled && - NS_FAILED(NS_DispatchToMainThread(new SetupAfterEnabledTask()))) { - BT_WARNING("Failed to dispatch to main thread!"); - return; - } -} - -class AdapterPropertiesCallbackTask MOZ_FINAL : public nsRunnable -{ -public: - NS_IMETHOD - Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - if (!sSetPropertyRunnableArray.IsEmpty()) { - DispatchBluetoothReply(sSetPropertyRunnableArray[0], - BluetoothValue(true), EmptyString()); - sSetPropertyRunnableArray.RemoveElementAt(0); - } - - return NS_OK; - } -}; - -/** - * AdapterPropertiesCallback will be called after enable() but before - * AdapterStateChangedCallback is called. At that moment, both - * BluetoothManager/BluetoothAdapter does not register observer yet. - */ -static void -AdapterPropertiesCallback(bt_status_t aStatus, int aNumProperties, - bt_property_t *aProperties) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - BluetoothValue propertyValue; - InfallibleTArray props; - - for (int i = 0; i < aNumProperties; i++) { - bt_property_t p; - // See Bug 989976, consider aProperties address is not aligned - memcpy(&p, &aProperties[i], sizeof(p)); - - if (p.type == BT_PROPERTY_BDADDR) { - BdAddressTypeToString((bt_bdaddr_t*)p.val, sAdapterBdAddress); - propertyValue = sAdapterBdAddress; - BT_APPEND_NAMED_VALUE(props, "Address", propertyValue); - } else if (p.type == BT_PROPERTY_BDNAME) { - // Construct nsCString here because Bd name returned from bluedroid - // is missing a null terminated character after SetProperty. - propertyValue = sAdapterBdName = NS_ConvertUTF8toUTF16( - nsCString((char*)p.val, p.len)); - BT_APPEND_NAMED_VALUE(props, "Name", propertyValue); - } else if (p.type == BT_PROPERTY_ADAPTER_SCAN_MODE) { - bt_scan_mode_t newMode = *(bt_scan_mode_t*)p.val; - - if (newMode == BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE) { - propertyValue = sAdapterDiscoverable = true; - } else { - propertyValue = sAdapterDiscoverable = false; - } - - BT_APPEND_NAMED_VALUE(props, "Discoverable", propertyValue); - } else if (p.type == BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT) { - propertyValue = sAdapterDiscoverableTimeout = *(uint32_t*)p.val; - BT_APPEND_NAMED_VALUE(props, "DiscoverableTimeout", propertyValue); - } else if (p.type == BT_PROPERTY_ADAPTER_BONDED_DEVICES) { - // We have to cache addresses of bonded devices. Unlike BlueZ, - // bluedroid would not send an another BT_PROPERTY_ADAPTER_BONDED_DEVICES - // event after bond completed - bt_bdaddr_t* deviceBdAddressTypes = (bt_bdaddr_t*)p.val; - int numOfAddresses = p.len / BLUETOOTH_ADDRESS_BYTES; - BT_LOGD("Adapter property: BONDED_DEVICES. Count: %d", numOfAddresses); - - // Whenever reloading paired devices, force refresh - sAdapterBondedAddressArray.Clear(); - - for (int index = 0; index < numOfAddresses; index++) { - nsAutoString deviceBdAddress; - BdAddressTypeToString(deviceBdAddressTypes + index, deviceBdAddress); - sAdapterBondedAddressArray.AppendElement(deviceBdAddress); - } - - propertyValue = sAdapterBondedAddressArray; - BT_APPEND_NAMED_VALUE(props, "Devices", propertyValue); - } else if (p.type == BT_PROPERTY_UUIDS) { - //FIXME: This will be implemented in the later patchset - continue; - } else { - BT_LOGD("Unhandled adapter property type: %d", p.type); - continue; - } - } - - NS_ENSURE_TRUE_VOID(props.Length() > 0); - - BluetoothValue value(props); - BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"), - NS_LITERAL_STRING(KEY_ADAPTER), value); - nsRefPtr - t = new DistributeBluetoothSignalTask(signal); - if (NS_FAILED(NS_DispatchToMainThread(t))) { - BT_WARNING("Failed to dispatch to main thread!"); - } - - // Redirect to main thread to avoid racing problem - NS_DispatchToMainThread(new AdapterPropertiesCallbackTask()); -} - -class RemoteDevicePropertiesCallbackTask : public nsRunnable -{ - const InfallibleTArray mProps; - nsString mRemoteDeviceBdAddress; -public: - RemoteDevicePropertiesCallbackTask( - const InfallibleTArray& aProps, - const nsAString& aRemoteDeviceBdAddress) - : mProps(aProps) - , mRemoteDeviceBdAddress(aRemoteDeviceBdAddress) - { } - - NS_IMETHOD - Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - if (sRequestedDeviceCountArray.IsEmpty()) { - // This is possible because the callback would be called after turning - // Bluetooth on. - return NS_OK; - } - - // Update to registered BluetoothDevice objects - BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"), - mRemoteDeviceBdAddress, mProps); - nsRefPtr - t = new DistributeBluetoothSignalTask(signal); - if (NS_FAILED(NS_DispatchToMainThread(t))) { - BT_WARNING("Failed to dispatch to main thread!"); - return NS_OK; - } - - // Use address as the index - sRemoteDevicesPack.AppendElement( - BluetoothNamedValue(mRemoteDeviceBdAddress, mProps)); - - if (--sRequestedDeviceCountArray[0] == 0) { - if (!sGetDeviceRunnableArray.IsEmpty()) { - DispatchBluetoothReply(sGetDeviceRunnableArray[0], - sRemoteDevicesPack, EmptyString()); - sGetDeviceRunnableArray.RemoveElementAt(0); - } - - sRequestedDeviceCountArray.RemoveElementAt(0); - sRemoteDevicesPack.Clear(); - } - - return NS_OK; - } -}; - -/** - * RemoteDevicePropertiesCallback will be called, as the following conditions: - * 1. When BT is turning on, bluedroid automatically execute this callback - * 2. When get_remote_device_properties() - */ -static void -RemoteDevicePropertiesCallback(bt_status_t aStatus, bt_bdaddr_t *aBdAddress, - int aNumProperties, bt_property_t *aProperties) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - InfallibleTArray props; - - nsString remoteDeviceBdAddress; - BdAddressTypeToString(aBdAddress, remoteDeviceBdAddress); - BT_APPEND_NAMED_VALUE(props, "Address", remoteDeviceBdAddress); - - bool isCodInvalid = false; - for (int i = 0; i < aNumProperties; ++i) { - bt_property_t p = aProperties[i]; - - if (p.type == BT_PROPERTY_BDNAME) { - BluetoothValue propertyValue = NS_ConvertUTF8toUTF16((char*)p.val); - BT_APPEND_NAMED_VALUE(props, "Name", propertyValue); - } else if (p.type == BT_PROPERTY_CLASS_OF_DEVICE) { - uint32_t cod = *(uint32_t*)p.val; - nsString icon; - ClassToIcon(cod, icon); - if (!icon.IsEmpty()) { - // Valid CoD - BT_APPEND_NAMED_VALUE(props, "Class", cod); - BT_APPEND_NAMED_VALUE(props, "Icon", icon); - } else { - // If Cod is invalid, fallback to check UUIDs. It usually happens due to - // NFC directly trigger pairing. bluedroid sends wrong CoD due to missing - // EIR query records. - isCodInvalid = true; - } - } else if (p.type == BT_PROPERTY_UUIDS) { - InfallibleTArray uuidsArray; - int uuidListLength = p.len / MAX_UUID_SIZE; - uint32_t cod = 0; - - for (int i = 0; i < uuidListLength; i++) { - uint16_t uuidServiceClass = UuidToServiceClassInt((bt_uuid_t*)(p.val + - (i * MAX_UUID_SIZE))); - BluetoothServiceClass serviceClass = BluetoothUuidHelper:: - GetBluetoothServiceClass(uuidServiceClass); - - // Get Uuid string from BluetoothServiceClass - nsString uuid; - BluetoothUuidHelper::GetString(serviceClass, uuid); - uuidsArray.AppendElement(uuid); - - // Restore CoD value - if (isCodInvalid) { - if (serviceClass == BluetoothServiceClass::HANDSFREE || - serviceClass == BluetoothServiceClass::HEADSET) { - BT_LOGD("Restore Class Of Device to Audio bit"); - SET_AUDIO_BIT(cod); - } else if (serviceClass == BluetoothServiceClass::A2DP_SINK) { - BT_LOGD("Restore Class of Device to Rendering bit"); - SET_RENDERING_BIT(cod); - } - } - } - - if (isCodInvalid) { - BT_APPEND_NAMED_VALUE(props, "Class", cod); - // 'audio-card' refers to 'Audio' device - BT_APPEND_NAMED_VALUE(props, "Icon", NS_LITERAL_STRING("audio-card")); - } - BT_APPEND_NAMED_VALUE(props, "UUIDS", uuidsArray); - } else { - BT_LOGD("Other non-handled device properties. Type: %d", p.type); - } - } - - // Redirect to main thread to avoid racing problem - NS_DispatchToMainThread( - new RemoteDevicePropertiesCallbackTask(props, remoteDeviceBdAddress)); -} - -static void -DeviceFoundCallback(int aNumProperties, bt_property_t *aProperties) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - BluetoothValue propertyValue; - InfallibleTArray propertiesArray; - - for (int i = 0; i < aNumProperties; i++) { - bt_property_t p = aProperties[i]; - - if (p.type == BT_PROPERTY_BDADDR) { - nsString remoteDeviceBdAddress; - BdAddressTypeToString((bt_bdaddr_t*)p.val, remoteDeviceBdAddress); - propertyValue = remoteDeviceBdAddress; - - BT_APPEND_NAMED_VALUE(propertiesArray, "Address", propertyValue); - } else if (p.type == BT_PROPERTY_BDNAME) { - propertyValue = NS_ConvertUTF8toUTF16((char*)p.val); - BT_APPEND_NAMED_VALUE(propertiesArray, "Name", propertyValue); - } else if (p.type == BT_PROPERTY_CLASS_OF_DEVICE) { - uint32_t cod = *(uint32_t*)p.val; - propertyValue = cod; - BT_APPEND_NAMED_VALUE(propertiesArray, "Class", propertyValue); - - nsString icon; - ClassToIcon(cod, icon); - propertyValue = icon; - BT_APPEND_NAMED_VALUE(propertiesArray, "Icon", propertyValue); - } else { - BT_LOGD("Not handled remote device property: %d", p.type); - } - } - - BluetoothValue value = propertiesArray; - BluetoothSignal signal(NS_LITERAL_STRING("DeviceFound"), - NS_LITERAL_STRING(KEY_ADAPTER), value); - nsRefPtr - t = new DistributeBluetoothSignalTask(signal); - if (NS_FAILED(NS_DispatchToMainThread(t))) { - BT_WARNING("Failed to dispatch to main thread!"); - } -} - -static void -DiscoveryStateChangedCallback(bt_discovery_state_t aState) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - bool isDiscovering = (aState == BT_DISCOVERY_STARTED); - BluetoothSignal signal(NS_LITERAL_STRING(DISCOVERY_STATE_CHANGED_ID), - NS_LITERAL_STRING(KEY_ADAPTER), isDiscovering); - - nsRefPtr t = - new DistributeBluetoothSignalTask(signal); - if (NS_FAILED(NS_DispatchToMainThread(t))) { - BT_WARNING("Failed to dispatch to main thread!"); - } -} - -static void -PinRequestCallback(bt_bdaddr_t* aRemoteBdAddress, - bt_bdname_t* aRemoteBdName, uint32_t aRemoteClass) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - InfallibleTArray propertiesArray; - nsAutoString remoteAddress; - BdAddressTypeToString(aRemoteBdAddress, remoteAddress); - - BT_APPEND_NAMED_VALUE(propertiesArray, "address", remoteAddress); - BT_APPEND_NAMED_VALUE(propertiesArray, "method", - NS_LITERAL_STRING("pincode")); - BT_APPEND_NAMED_VALUE(propertiesArray, "name", - NS_ConvertUTF8toUTF16( - (const char*)aRemoteBdName->name)); - - BluetoothValue value = propertiesArray; - BluetoothSignal signal(NS_LITERAL_STRING("RequestPinCode"), - NS_LITERAL_STRING(KEY_LOCAL_AGENT), value); - nsRefPtr - t = new DistributeBluetoothSignalTask(signal); - if (NS_FAILED(NS_DispatchToMainThread(t))) { - BT_WARNING("Failed to dispatch to main thread!"); - } -} - -static void -SspRequestCallback(bt_bdaddr_t* aRemoteBdAddress, bt_bdname_t* aRemoteBdName, - uint32_t aRemoteClass, bt_ssp_variant_t aPairingVariant, - uint32_t aPasskey) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - InfallibleTArray propertiesArray; - nsAutoString remoteAddress; - BdAddressTypeToString(aRemoteBdAddress, remoteAddress); - - BT_APPEND_NAMED_VALUE(propertiesArray, "address", remoteAddress); - BT_APPEND_NAMED_VALUE(propertiesArray, "method", - NS_LITERAL_STRING("confirmation")); - BT_APPEND_NAMED_VALUE(propertiesArray, "name", - NS_ConvertUTF8toUTF16( - (const char*)aRemoteBdName->name)); - BT_APPEND_NAMED_VALUE(propertiesArray, "passkey", aPasskey); - - BluetoothValue value = propertiesArray; - BluetoothSignal signal(NS_LITERAL_STRING("RequestConfirmation"), - NS_LITERAL_STRING(KEY_LOCAL_AGENT), value); - nsRefPtr - t = new DistributeBluetoothSignalTask(signal); - if (NS_FAILED(NS_DispatchToMainThread(t))) { - BT_WARNING("Failed to dispatch to main thread!"); - } -} - -class BondStateChangedCallbackTask : public nsRunnable -{ - nsString mRemoteDeviceBdAddress; - bool mBonded; -public: - BondStateChangedCallbackTask(const nsAString& aRemoteDeviceBdAddress, - bool aBonded) - : mRemoteDeviceBdAddress(aRemoteDeviceBdAddress) - , mBonded(aBonded) - { } - - NS_IMETHOD - Run() - { - MOZ_ASSERT(NS_IsMainThread()); - - if (mBonded && !sBondingRunnableArray.IsEmpty()) { - DispatchBluetoothReply(sBondingRunnableArray[0], - BluetoothValue(true), EmptyString()); - - sBondingRunnableArray.RemoveElementAt(0); - } else if (!mBonded && !sUnbondingRunnableArray.IsEmpty()) { - DispatchBluetoothReply(sUnbondingRunnableArray[0], - BluetoothValue(true), EmptyString()); - - sUnbondingRunnableArray.RemoveElementAt(0); - } - - // Update bonding status to gaia - InfallibleTArray propertiesArray; - BT_APPEND_NAMED_VALUE(propertiesArray, "address", mRemoteDeviceBdAddress); - BT_APPEND_NAMED_VALUE(propertiesArray, "status", mBonded); - - BluetoothSignal signal(NS_LITERAL_STRING(PAIRED_STATUS_CHANGED_ID), - NS_LITERAL_STRING(KEY_ADAPTER), - BluetoothValue(propertiesArray)); - NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal)); - - return NS_OK; - } -}; - -static void -BondStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress, - bt_bond_state_t aState) -{ - MOZ_ASSERT(!NS_IsMainThread()); - - if (aState == BT_BOND_STATE_BONDING) { - // No need to handle bonding state - return; - } - - nsAutoString remoteBdAddress; - BdAddressTypeToString(aRemoteBdAddress, remoteBdAddress); - - if (aState == BT_BOND_STATE_BONDED && - sAdapterBondedAddressArray.Contains(remoteBdAddress)) { - // See bug 940271 for more details about this case. - return; - } - - bool bonded; - if (aState == BT_BOND_STATE_NONE) { - bonded = false; - sAdapterBondedAddressArray.RemoveElement(remoteBdAddress); - } else if (aState == BT_BOND_STATE_BONDED) { - bonded = true; - sAdapterBondedAddressArray.AppendElement(remoteBdAddress); - } - - // Update bonded address list to BluetoothAdapter - InfallibleTArray propertiesChangeArray; - BT_APPEND_NAMED_VALUE(propertiesChangeArray, "Devices", - sAdapterBondedAddressArray); - - BluetoothValue value(propertiesChangeArray); - BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"), - NS_LITERAL_STRING(KEY_ADAPTER), - BluetoothValue(propertiesChangeArray)); - NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal)); - - // Redirect to main thread to avoid racing problem - NS_DispatchToMainThread( - new BondStateChangedCallbackTask(remoteBdAddress, bonded)); -} - -static void -AclStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress, - bt_acl_state_t aState) -{ - //FIXME: This will be implemented in the later patchset -} - -static void -CallbackThreadEvent(bt_cb_thread_evt evt) -{ - //FIXME: This will be implemented in the later patchset -} - -bt_callbacks_t sBluetoothCallbacks = -{ - sizeof(sBluetoothCallbacks), - AdapterStateChangeCallback, - AdapterPropertiesCallback, - RemoteDevicePropertiesCallback, - DeviceFoundCallback, - DiscoveryStateChangedCallback, - PinRequestCallback, - SspRequestCallback, - BondStateChangedCallback, - AclStateChangedCallback, - CallbackThreadEvent -}; - /** * Static functions */ diff --git a/dom/bluetooth/bluedroid/BluetoothUtils.cpp b/dom/bluetooth/bluedroid/BluetoothUtils.cpp index 3e038cc51d3..c89efef54f8 100644 --- a/dom/bluetooth/bluedroid/BluetoothUtils.cpp +++ b/dom/bluetooth/bluedroid/BluetoothUtils.cpp @@ -23,19 +23,6 @@ BEGIN_BLUETOOTH_NAMESPACE -void -StringToBdAddressType(const nsAString& aBdAddress, - bt_bdaddr_t *aRetBdAddressType) -{ - NS_ConvertUTF16toUTF8 bdAddressUTF8(aBdAddress); - const char* str = bdAddressUTF8.get(); - - for (int i = 0; i < 6; i++) { - aRetBdAddressType->address[i] = (uint8_t) strtoul(str, (char **)&str, 16); - str++; - } -} - void BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress) { @@ -49,15 +36,6 @@ BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress) aRetBdAddress = NS_ConvertUTF8toUTF16(bdstr); } -uint16_t -UuidToServiceClassInt(bt_uuid_t* p_uuid) -{ - // extract short UUID 0000xxxx-0000-1000-8000-00805f9b34fb - uint16_t shortUuid; - memcpy(&shortUuid, &(p_uuid->uu[2]), sizeof(uint16_t)); - return ntohs(shortUuid); -} - uint16_t UuidToServiceClassInt(const BluetoothUuid& mUuid) { diff --git a/dom/bluetooth/bluedroid/BluetoothUtils.h b/dom/bluetooth/bluedroid/BluetoothUtils.h index 45265c50544..4cf0c470cb1 100644 --- a/dom/bluetooth/bluedroid/BluetoothUtils.h +++ b/dom/bluetooth/bluedroid/BluetoothUtils.h @@ -18,17 +18,10 @@ class BluetoothNamedValue; class BluetoothValue; class BluetoothReplyRunnable; -void -StringToBdAddressType(const nsAString& aBdAddress, - bt_bdaddr_t *aRetBdAddressType); - void BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress); -uint16_t -UuidToServiceClassInt(bt_uuid_t* p_uuid); - uint16_t UuidToServiceClassInt(const BluetoothUuid& mUuid);