none
[UWP]CPU Spike in System Services When Handling GATT Characteristic Notifications with UWP Background Task RRS feed

  • Question

  • When using a UWP background task to handle GATT characteristic notifications (registered for two characteristics), and the remote device triggers GATT notifications on one characteristic, CPU usage of the "Service Host: Local System (Network Restricted)" containing the "Device Association Service" can spike, sometimes greater than 80%, often causing the overall system CPU usage to reach 99% usage. In addition, "Bluetooth Support Service" and "Remote Procedure Call" appear near the top of the list. When the remote device triggers a large number of GATT notifications, CPU usage can remain at >80% for several minutes, consuming large amounts of power.

    I believe this is a bug in the Bluetooth APIs. If not, how can I prevent this from happening? Thanks!

    (This is a variation on feedback I submitted in Feedback Hub (https://aka.ms/AA5sce1), but I wasn't sure if that was the right place to submit to.)


    Thursday, August 8, 2019 3:09 AM

All replies

  • Hi,

    After testing, UWP does not take up more than 20% of CPU when processing Bluetooth GATT.

    Can you provide a minimally run code, which may be due to other problems?

    Best regards.

    Thursday, August 8, 2019 7:24 AM
  • Thank you for replying. Here is a minimal example that causes the Device Association Service to remain at 60-80% CPU for several minutes.

    Add the following to MainPage.xaml:

    <Button x:Name="start" Content="Choose device..." Margin="30,30,0,0" VerticalAlignment="Top" Height="32" Width="141" Click="Button_Click"/>

    The contents of MainPage.xaml.vb:

    Imports Windows.Devices.Bluetooth
    Imports Windows.Devices.Bluetooth.GenericAttributeProfile
    Imports Windows.Devices.Enumeration
    Imports Windows.ApplicationModel.Background
    Imports Windows.Foundation
    Public NotInheritable Class MainPage
        Inherits Page
        Public gattnstrg As GattCharacteristicNotificationTrigger
        Public gattnsbt As BackgroundTaskBuilder = New BackgroundTaskBuilder()
        Private Async Sub Button_Click(sender As Object, e As RoutedEventArgs)
            Debug.WriteLine("Button Click")
            'Unregister existing background tasks
            Dim bgtasks = BackgroundTaskRegistration.AllTasks
            For Each bgtask In bgtasks
                If bgtask.Value.Name = "btbg" Then
                    bgtask.Value.Unregister(True)
                End If
            Next
            Debug.WriteLine("Background Tasks Unregistered")
            Dim dp = New DevicePicker()
            'dp.Filter.SupportedDeviceSelectors.Add(BluetoothLEDevice.GetDeviceSelector())
            dp.Filter.SupportedDeviceSelectors.Add(BluetoothLEDevice.GetDeviceSelectorFromPairingState(False))
            dp.Filter.SupportedDeviceSelectors.Add(BluetoothLEDevice.GetDeviceSelectorFromPairingState(True))
            Dim mydev As DeviceInformation = Await dp.PickSingleDeviceAsync(New Windows.Foundation.Rect())
            Debug.WriteLine("Picked device")
            If mydev IsNot Nothing Then
                're-pair:
                Debug.WriteLine(mydev.Kind.ToString())
                'Debug.WriteLine("Paired")
                'If Not mydev.Pairing.ProtectionLevel = DevicePairingProtectionLevel.EncryptionAndAuthentication Then
                'Await mydev.Pairing.UnpairAsync()
                Await mydev.Pairing.PairAsync(DevicePairingProtectionLevel.EncryptionAndAuthentication)
                'End If
                Debug.WriteLine("Initiating service discovery...")
                Dim mydevice As BluetoothLEDevice = Await BluetoothLEDevice.FromIdAsync(mydev.Id)
                'Await mydevice.RequestAccessAsync()
                Dim services = Await mydevice.GetGattServicesAsync()
                For Each serv In services.Services
                    If serv.Uuid.ToString() = "7905F431-B5CE-4E99-A40F-4B1E122D00D0".ToLower() Then
                        Dim characteristics = Await serv.GetCharacteristicsAsync()
                        For Each charac In characteristics.Characteristics
                            If charac.Uuid.ToString() = "9FBF120D-6301-42D9-8C58-25E699A21DBD".ToLower() Then
                                'Consider checking for success
                                'Set security level somehow!!! https://stackoverflow.com/a/24067078/
                                'Try
                                Await charac.WriteClientCharacteristicConfigurationDescriptorAsync(
            GattClientCharacteristicConfigurationDescriptorValue.Notify)
                                'Catch
                                'TODO: somehow trigger re-pair if exception thrown and authentication needed for characteristic
                                'End Try
                                gattnstrg = New GattCharacteristicNotificationTrigger(charac)
                                gattnsbt.SetTrigger(gattnstrg)
                                gattnsbt.Name = "btbg"
                                Await BackgroundExecutionManager.RequestAccessAsync()
                                gattnsbt.Register()
                            End If
                        Next
                    End If
                Next
                Debug.WriteLine("Discovery complete")
            End If
        End Sub
    End Class

    Add the following to App.xaml.vb:

        Protected Overrides Sub OnBackgroundActivated(e As BackgroundActivatedEventArgs)
            'Dim taskInstance As IBackgroundTaskInstance = e.TaskInstance
            Debug.WriteLine("Background Task Launched: " + e.TaskInstance.Task.Name)
            If e.TaskInstance.Task.Name = "btbg" Then
                Tasks.BackgroundClassNC.Run(e.TaskInstance)
            End If
        End Sub

    The contents of BackgroundModule.vb:

    Imports Windows.ApplicationModel.Background
    Imports Windows.Devices.Bluetooth.Background
    Imports Windows.Security.Cryptography
    Namespace Global.Tasks
        Public NotInheritable Class BackgroundClassNC
            Public Shared Async Sub Run(taskInstance As IBackgroundTaskInstance)
                Debug.WriteLine("Background " & taskInstance.Task.Name & " Starting...")
                Dim deferral = taskInstance.GetDeferral()
                Dim args As GattCharacteristicNotificationTriggerDetails = taskInstance.TriggerDetails
                If args.Characteristic.Uuid.ToString() = "9FBF120D-6301-42D9-8C58-25E699A21DBD".ToLower() Then
                    Debug.WriteLine("Notification!")
                End If
                deferral.Complete()
            End Sub
        End Class
    End Namespace

    I have been testing by pairing with my iPhone SE, running iOS 12.1.4. Opening to the Bluetooth Settings does not advertise the device as a Bluetooth LE device (only as a Bluetooth classic device), so an app such as "nRF Connect" is needed in order to advertise support for any Bluetooth LE service (doesn't matter which one) and pair the device with Windows as a Bluetooth LE device (rather than a Bluetooth classic device). I find that pairing the device through Windows Settings works best.


    • Edited by tech234a Friday, August 9, 2019 5:15 AM Formatting
    Friday, August 9, 2019 5:13 AM
  • Hi,

    I am sorry to be late.

    I am applying for the help of an engineer to help you solve the problem through the code you provided.

    I will post to you any new progress.

    Best regards.


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, August 13, 2019 5:45 AM