void CompositableParentManager::SendPendingAsyncMessges() { if (mPendingAsyncMessage.empty()) { return; } // Some type of AsyncParentMessageData message could have // one file descriptor (e.g. OpDeliverFence). // A number of file descriptors per gecko ipc message have a limitation // on OS_POSIX (MACOSX or LINUX). #if defined(OS_POSIX) static const uint32_t kMaxMessageNumber = FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE; #else // default number that works everywhere else static const uint32_t kMaxMessageNumber = 250; #endif InfallibleTArray<AsyncParentMessageData> messages; messages.SetCapacity(mPendingAsyncMessage.size()); for (size_t i = 0; i < mPendingAsyncMessage.size(); i++) { messages.AppendElement(mPendingAsyncMessage[i]); // Limit maximum number of messages. if (messages.Length() >= kMaxMessageNumber) { SendAsyncMessage(messages); // Initialize Messages. messages.Clear(); } } if (messages.Length() > 0) { SendAsyncMessage(messages); } mPendingAsyncMessage.clear(); }
/** * AdapterPropertiesNotification will be called after enable() but * before AdapterStateChangeNotification is called. At that moment, * BluetoothManager and BluetoothAdapter, do not register observer * yet. */ void BluetoothServiceBluedroid::AdapterPropertiesNotification( BluetoothStatus aStatus, int aNumProperties, const BluetoothProperty* aProperties) { MOZ_ASSERT(NS_IsMainThread()); InfallibleTArray<BluetoothNamedValue> propertiesArray; for (int i = 0; i < aNumProperties; i++) { const BluetoothProperty& p = aProperties[i]; if (p.mType == PROPERTY_BDADDR) { sAdapterBdAddress = p.mString; BT_APPEND_NAMED_VALUE(propertiesArray, "Address", sAdapterBdAddress); } else if (p.mType == PROPERTY_BDNAME) { sAdapterBdName = p.mString; BT_APPEND_NAMED_VALUE(propertiesArray, "Name", sAdapterBdName); } else if (p.mType == PROPERTY_ADAPTER_SCAN_MODE) { sAdapterDiscoverable = (p.mScanMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE); BT_APPEND_NAMED_VALUE(propertiesArray, "Discoverable", sAdapterDiscoverable); } else if (p.mType == PROPERTY_ADAPTER_BONDED_DEVICES) { // We have to cache addresses of bonded devices. Unlike BlueZ, // Bluedroid would not send another PROPERTY_ADAPTER_BONDED_DEVICES // event after bond completed. BT_LOGD("Adapter property: BONDED_DEVICES. Count: %d", p.mStringArray.Length()); // Whenever reloading paired devices, force refresh sAdapterBondedAddressArray.Clear(); sAdapterBondedAddressArray.AppendElements(p.mStringArray); BT_APPEND_NAMED_VALUE(propertiesArray, "PairedDevices", sAdapterBondedAddressArray); } else if (p.mType == PROPERTY_UNKNOWN) { /* Bug 1065999: working around unknown properties */ } else { BT_LOGD("Unhandled adapter property type: %d", p.mType); continue; } } NS_ENSURE_TRUE_VOID(propertiesArray.Length() > 0); DistributeSignal(NS_LITERAL_STRING("PropertyChanged"), NS_LITERAL_STRING(KEY_ADAPTER), BluetoothValue(propertiesArray)); // Send reply for SetProperty if (!sSetPropertyRunnableArray.IsEmpty()) { DispatchReplySuccess(sSetPropertyRunnableArray[0]); sSetPropertyRunnableArray.RemoveElementAt(0); } }
void OnError(BluetoothStatus aStatus) override { MOZ_ASSERT(NS_IsMainThread()); BT_WARNING("GetRemoteDeviceProperties(%s) failed: %d", NS_ConvertUTF16toUTF8(mDeviceAddress).get(), aStatus); /* dispatch result after final pending operation */ if (--sRequestedDeviceCountArray[0] == 0) { if (!sGetDeviceRunnableArray.IsEmpty()) { DispatchReplyError(sGetDeviceRunnableArray[0], NS_LITERAL_STRING("GetRemoteDeviceProperties failed")); sGetDeviceRunnableArray.RemoveElementAt(0); } sRequestedDeviceCountArray.RemoveElementAt(0); sRemoteDevicesPack.Clear(); } }
/** * 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()); if (sRequestedDeviceCountArray.IsEmpty()) { MOZ_ASSERT(sGetDeviceRunnableArray.IsEmpty()); return; } sRequestedDeviceCountArray[0]--; InfallibleTArray<BluetoothNamedValue> props; nsString remoteDeviceBdAddress; BdAddressTypeToString(aBdAddress, remoteDeviceBdAddress); props.AppendElement( BluetoothNamedValue(NS_LITERAL_STRING("Address"), remoteDeviceBdAddress)); 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); props.AppendElement( BluetoothNamedValue(NS_LITERAL_STRING("Name"), propertyValue)); } else if (p.type == BT_PROPERTY_CLASS_OF_DEVICE) { uint32_t cod = *(uint32_t*)p.val; props.AppendElement( BluetoothNamedValue(NS_LITERAL_STRING("Class"), BluetoothValue(cod))); nsString icon; ClassToIcon(cod, icon); props.AppendElement( BluetoothNamedValue(NS_LITERAL_STRING("Icon"), BluetoothValue(icon))); } else { BT_LOGD("Other non-handled device properties. Type: %d", p.type); } } // Update to registered BluetoothDevice objects BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"), remoteDeviceBdAddress, props); nsRefPtr<DistributeBluetoothSignalTask> t = new DistributeBluetoothSignalTask(signal); if (NS_FAILED(NS_DispatchToMainThread(t))) { BT_WARNING("Failed to dispatch to main thread!"); } // Use address as the index sRemoteDevicesPack.AppendElement( BluetoothNamedValue(remoteDeviceBdAddress, props)); if (sRequestedDeviceCountArray[0] == 0) { MOZ_ASSERT(!sGetDeviceRunnableArray.IsEmpty()); if (sGetDeviceRunnableArray.IsEmpty()) { BT_LOGR("No runnable to return"); return; } DispatchBluetoothReply(sGetDeviceRunnableArray[0], sRemoteDevicesPack, EmptyString()); // After firing it, clean up cache sRemoteDevicesPack.Clear(); sRequestedDeviceCountArray.RemoveElementAt(0); sGetDeviceRunnableArray.RemoveElementAt(0); } }
/** * AdapterPropertiesCallback will be called after enable() but before * AdapterStateChangeCallback sIsBtEnabled get updated. 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<BluetoothNamedValue> props; for (int i = 0; i < aNumProperties; i++) { bt_property_t p = aProperties[i]; if (p.type == BT_PROPERTY_BDADDR) { BdAddressTypeToString((bt_bdaddr_t*)p.val, sAdapterBdAddress); propertyValue = sAdapterBdAddress; props.AppendElement( BluetoothNamedValue(NS_LITERAL_STRING("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)); props.AppendElement( BluetoothNamedValue(NS_LITERAL_STRING("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; } props.AppendElement( BluetoothNamedValue(NS_LITERAL_STRING("Discoverable"), propertyValue)); } else if (p.type == BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT) { propertyValue = sAdapterDiscoverableTimeout = *(uint32_t*)p.val; props.AppendElement( BluetoothNamedValue(NS_LITERAL_STRING("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; props.AppendElement( BluetoothNamedValue(NS_LITERAL_STRING("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<DistributeBluetoothSignalTask> t = new DistributeBluetoothSignalTask(signal); if (NS_FAILED(NS_DispatchToMainThread(t))) { BT_WARNING("Failed to dispatch to main thread!"); } // bluedroid BTU task was stored in the task queue, see GKI_send_msg if (!sSetPropertyRunnableArray.IsEmpty()) { DispatchBluetoothReply(sSetPropertyRunnableArray[0], BluetoothValue(true), EmptyString()); sSetPropertyRunnableArray.RemoveElementAt(0); } }
/** * RemoteDevicePropertiesNotification will be called * * (1) automatically by Bluedroid when BT is turning on, * (2) as result of GetRemoteDeviceProperties, or * (3) as result of GetRemoteServices. */ void BluetoothServiceBluedroid::RemoteDevicePropertiesNotification( BluetoothStatus aStatus, const nsAString& aBdAddr, int aNumProperties, const BluetoothProperty* aProperties) { MOZ_ASSERT(NS_IsMainThread()); InfallibleTArray<BluetoothNamedValue> propertiesArray; BT_APPEND_NAMED_VALUE(propertiesArray, "Address", nsString(aBdAddr)); for (int i = 0; i < aNumProperties; ++i) { const BluetoothProperty& p = aProperties[i]; if (p.mType == PROPERTY_BDNAME) { BT_APPEND_NAMED_VALUE(propertiesArray, "Name", p.mString); } else if (p.mType == PROPERTY_CLASS_OF_DEVICE) { uint32_t cod = p.mUint32; BT_APPEND_NAMED_VALUE(propertiesArray, "Cod", cod); } else if (p.mType == PROPERTY_UUIDS) { nsTArray<nsString> uuids; // Construct a sorted uuid set for (uint32_t index = 0; index < p.mUuidArray.Length(); ++index) { nsAutoString uuid; UuidToString(p.mUuidArray[index], uuid); if (!uuids.Contains(uuid)) { // filter out duplicate uuids uuids.InsertElementSorted(uuid); } } BT_APPEND_NAMED_VALUE(propertiesArray, "UUIDs", uuids); } else if (p.mType == PROPERTY_TYPE_OF_DEVICE) { BT_APPEND_NAMED_VALUE(propertiesArray, "Type", static_cast<uint32_t>(p.mTypeOfDevice)); } else if (p.mType == PROPERTY_UNKNOWN) { /* Bug 1065999: working around unknown properties */ } else { BT_LOGD("Other non-handled device properties. Type: %d", p.mType); } } // The order of operations below is // // (1) modify global state (i.e., the variables starting with 's'), // (2) distribute the signal, and finally // (3) send any pending Bluetooth replies. // // |DispatchReplySuccess| creates its own internal runnable, which is // always run after we completed the current method. This means that we // can exchange |DispatchReplySuccess| with other operations without // changing the order of (1,2) and (3). // Update to registered BluetoothDevice objects BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"), nsString(aBdAddr), propertiesArray); // FetchUuids task if (!sFetchUuidsRunnableArray.IsEmpty()) { // propertiesArray contains Address and Uuids only DispatchReplySuccess(sFetchUuidsRunnableArray[0], propertiesArray[1].value()); /* Uuids */ sFetchUuidsRunnableArray.RemoveElementAt(0); DistributeSignal(signal); return; } // GetDevices task if (sRequestedDeviceCountArray.IsEmpty()) { // This is possible because the callback would be called after turning // Bluetooth on. DistributeSignal(signal); return; } // Use address as the index sRemoteDevicesPack.AppendElement( BluetoothNamedValue(nsString(aBdAddr), propertiesArray)); if (--sRequestedDeviceCountArray[0] == 0) { if (!sGetDeviceRunnableArray.IsEmpty()) { DispatchReplySuccess(sGetDeviceRunnableArray[0], sRemoteDevicesPack); sGetDeviceRunnableArray.RemoveElementAt(0); } sRequestedDeviceCountArray.RemoveElementAt(0); sRemoteDevicesPack.Clear(); } DistributeSignal(signal); }