private async void OnBtConnectionStateChangedObservers(Earbuds sendor, BluetoothDevice bluetoothDevice, BluetoothConnectionStatus connectionStatus)
        {
            if (sendor != null)
            {
                bool result;
                result = await sendor.ConnectSpp();

                Log.D($"PairWithMac(): Request to connect Spp with {LocalBtAddress}, result = {result}");

                // FIXME: Retry if failed to connect A2DP over SPP
                for (int i = 0; i < 10; ++i)
                {
                    result = await sendor.SppConnectA2DP(LocalBtAddress);

                    Log.D($"PairWithMac(): Request to connect A2DP with {LocalBtAddress}, try={i}, result = {result}");
                    if (result)
                    {
                        break;
                    }
                }

                sendor.DisconnectSpp();
                Log.D($"PairWithMac(): Request to Disconnect SPP with {LocalBtAddress}");

                sendor.BtConnectionStateChangedObservers -= OnBtConnectionStateChangedObservers;
                sendor.DisableSppConnection();
            }
        }
        private async void OnBleAdvertisementUpdated(BleAdvertisementWatcher sender, DeviceWatchEvent eventCode, BLEAdvertisementInfo bleAdvertisementInfo)
        {
            DeviceInformation btDeviceInformation = await BluetoothDevices.CreateDeviceInformation(bleAdvertisementInfo.ToBtAddressString(), AddressType.Bluetooth);

            DeviceInformation bleDeviceInformation = await BluetoothDevices.CreateDeviceInformation(bleAdvertisementInfo.ToBtAddressString(), AddressType.BLE);

            if (!App.sUserManager.IsSingnIn())
            {
                // FIXME: SERVICE CODE to configuration
                if (bleAdvertisementInfo.Advertisement.ManufacturerData[0].Data.Length > 5)
                {
                    // ignore, because it has user Key.
                    Log.D(string.Format($"Other User's Device Found: {bleAdvertisementInfo.Advertisement.ManufacturerData[0].Data}"));
                    return;
                }
            }

            if (eventCode == DeviceWatchEvent.Added)
            {
                Log.D(string.Format($"New BLE Advertisement Found: {bleAdvertisementInfo.ToBtAddressString()}"));

                AddNearByEarbuds(bleDeviceInformation.Id);
                AddNearByBtDevice(bleDeviceInformation.Id, btDeviceInformation.Name);
            }
            else if (eventCode == DeviceWatchEvent.Removed)
            {
                Log.D(string.Format($"BLE Advertisement Removed: {bleAdvertisementInfo.ToBtAddressString()}"));

                Earbuds removeEarBuds = RemoveNearByEarbuds(bleDeviceInformation.Id);
                if (removeEarBuds != null)
                {
                    RemoveNearByBtDevice(bleDeviceInformation.Id, btDeviceInformation.Name);
                }
            }
        }
        public EarbudsMenuItem(DeviceInformation deviceInformation, SystrayApplicationServiceConnection sysAppConnection) : base(deviceInformation.Name)
        {
            this.Earbuds = new Earbuds(deviceInformation);

            SysAppConnection = sysAppConnection;

            ConnectMenu    = new MenuItem("Connect A2DP", ConnectClicked);
            DisconnectMenu = new MenuItem("Disconnect A2DP", DisconnectClicked);
            UnpairMenu     = new MenuItem("Unpair", UnpaireClicked);

            MenuItems.AddRange(new MenuItem[] { ConnectMenu, DisconnectMenu, UnpairMenu });

            Log = SystrayApplicationContext.Log;
        }
        private async void DisconnectA2DP(string deviceId)
        {
            Earbuds targetEarbuds = GetNaerByEarbirds(deviceId);

            if (targetEarbuds != null && targetEarbuds.BleConnected)
            {
                bool result = await targetEarbuds.DisconnectA2DP(LocalBtAddress);

                Log.D($"DisconnectA2DP with {targetEarbuds.BtID}, result={result}");
            }
            else
            {
                // FIXME: Support SPP?
            }
        }
        public async void PairWithMac(string deviceId)
        {
            Earbuds targetEarbuds = GetNaerByEarbirds(deviceId);

            try
            {
                // FIXME: Need to make the device TRUSTED?
                // await targetEarbuds.SetTrusted(LocalBtAddress, true);
                // Log.D($"PairWithMac(): Request to be Trusted, result = {result}");

                // FIXME: Need to make the device DISCOVERABLE?
                // result = await targetEarbuds.SetDiscoverable(true);
                // Log.D($"PairWithMac(): Request to be Discoverable, result = {result}");

                if (targetEarbuds != null)
                {
                    targetEarbuds.BtConnectionStateChangedObservers += OnBtConnectionStateChangedObservers;
                    targetEarbuds.EnableSppConnection();
                }

                if (PairingManager.PairingSupported)
                {
                    Log.D($"PairWithMac(): Request to Pair via Pairing Manager with {deviceId}");
                    PairingManager.Send($"pair/unknown/{deviceId}");

                    // FIXME: Handle Failure Case
                }
                else
                {
                    Log.D($"PairWithMac(): Request to Pair via Windows API with {deviceId}");
                    DeviceInformation devInfo = await DeviceInformation.CreateFromIdAsync(deviceId);

                    bool result = await DevicePairer.PairDevice(new Device(devInfo), "0000");

                    Log.D($"PairWithMac(): Request to Pair, result = {result}");
                    if (result == false)
                    {
                        targetEarbuds.BtConnectionStateChangedObservers -= OnBtConnectionStateChangedObservers;
                        targetEarbuds.DisableSppConnection();
                    }
                }
            }
            catch (Exception ex)
            {
                Log.E($"PairWithMac(): Exception, message={ex.Message}");
            }
            return;
        }
        private Earbuds RemoveNearByEarbuds(string deviceId)
        {
            Earbuds foundEarbuds = GetNaerByEarbirds(deviceId);

            if (foundEarbuds == null)
            {
                return(null);
            }

            lock (NearbyEarbudsList)
            {
                NearbyEarbudsList.Remove(foundEarbuds);
            }

            foundEarbuds.DisableGattConnection();
            foundEarbuds.Stop();

            return(foundEarbuds);
        }
        private async void AddPairedBtDevice(DeviceInformation deviceInformation)
        {
            DeviceInformation found = GetPairedBtDevice(deviceInformation);

            if (found != null)
            {
                return;
            }

            lock (PairedDeviceList)
            {
                PairedDeviceList.Add(deviceInformation);
            }

            Earbuds earbuds = GetNaerByEarbirds(deviceInformation.Id);

            if (earbuds != null)
            {
                earbuds.EnableGattConnection();
            }
            else
            {
                var BtDevice = await BluetoothDevice.FromIdAsync(deviceInformation.Id);

                if (BtDevice != null)
                {
                    if (BtDevice.ConnectionStatus == BluetoothConnectionStatus.Connected)
                    {
                        string bleDeviceID = BluetoothDevices.ConvertDeviceIdType(deviceInformation.Id, AddressType.BLE);
                        AddNearByEarbuds(bleDeviceID);
                        Log.D($"\tAlready Connected Device Found: Add it to NearByEarbuds List");
                        AddNearByBtDevice(bleDeviceID, deviceInformation.Name);
                    }
                    BtDevice.Dispose();
                }
            }

            return;
        }
        private DeviceInformation RemovePairedBtDevice(DeviceInformation deviceInformation)
        {
            DeviceInformation found = GetPairedBtDevice(deviceInformation);

            if (found == null)
            {
                return(null);
            }

            lock (PairedDeviceList)
            {
                PairedDeviceList.Remove(found);
            }

            Earbuds earbuds = GetNaerByEarbirds(deviceInformation.Id);

            if (earbuds != null)
            {
                earbuds.DisableGattConnection();
            }

            return(found);
        }
        private async void AddNearByEarbuds(string deviceId)
        {
            Earbuds foundEarbuds = GetNaerByEarbirds(deviceId);

            if (foundEarbuds != null)
            {
                return;
            }

            Earbuds newEarbuds = new Earbuds(deviceId);
            bool    result     = await newEarbuds.Start();

            Log.D($"Create New Earbuds, result={result}");

            lock (NearbyEarbudsList)
            {
                NearbyEarbudsList.Add(newEarbuds);
            }

            if (GetPairedBtDevice(deviceId) != null)
            {
                newEarbuds.EnableGattConnection();
            }
        }
 //////////////////////////////////////////////////////////////////////////
 // Bluetooth LE Event Handlers
 private void BleConnectionStatusChanged(Earbuds sener, BluetoothLEDevice bleDevice, BluetoothConnectionStatus connectionStatus)
 {
     Log.D($"BleConnectionStatusChanged(DeviceID:{bleDevice.DeviceId}\nStatus:{connectionStatus})");
     UpdateMenu();
 }
 private void BtNameChanged(Earbuds sener, BluetoothDevice btDevice, string name)
 {
     Text = name;
 }
 //////////////////////////////////////////////////////////////////////////
 // Bluetooth Event Handlers
 private void BtConnectionStatusChanged(Earbuds sener, BluetoothDevice btDevice, BluetoothConnectionStatus connectionStatus)
 {
     UpdateMenu();
 }