This is the fix for StartDiscovery/Connect/Disconnect/StartDiscovery.

PiperOrigin-RevId: 424866263
diff --git a/cpp/platform/impl/windows/bluetooth_classic_medium.cc b/cpp/platform/impl/windows/bluetooth_classic_medium.cc
index 4f8a7db..f1f781e 100644
--- a/cpp/platform/impl/windows/bluetooth_classic_medium.cc
+++ b/cpp/platform/impl/windows/bluetooth_classic_medium.cc
@@ -97,9 +97,13 @@
 
 void BluetoothClassicMedium::InitializeDeviceWatcher() {
   // create watcher
+  const winrt::param::iterable<winrt::hstring> RequestedProperties =
+      winrt::single_threaded_vector<winrt::hstring>(
+          {winrt::to_hstring("System.Devices.Aep.IsPresent")});
+
   device_watcher_ = DeviceInformation::CreateWatcher(
       BLUETOOTH_SELECTOR,                           // aqsFilter
-      nullptr,                                      // additionalProperties
+      RequestedProperties,                          // additionalProperties
       DeviceInformationKind::AssociationEndpoint);  // kind
 
   //  An app must subscribe to all of the added, removed, and updated events to
@@ -177,8 +181,6 @@
     return nullptr;
   }
 
-  device_watcher_.Stop();
-
   EnterCriticalSection(&critical_section_);
 
   std::unique_ptr<BluetoothSocket> rfcommSocket =
@@ -190,7 +192,7 @@
 
   try {
     rfcommSocket->Connect(requestedService.ConnectionHostName(),
-                               requestedService.ConnectionServiceName());
+                          requestedService.ConnectionServiceName());
   } catch (std::exception exception) {
     // We will log and eat the exception since the caller
     // expects nullptr if it fails
@@ -320,6 +322,8 @@
 
 bool BluetoothClassicMedium::StartScanning() {
   if (!IsWatcherStarted()) {
+    discovered_devices_by_id_.clear();
+
     // The Start method can only be called when the DeviceWatcher is in the
     // Created, Stopped or Aborted state.
     auto status = device_watcher_.Status();
@@ -360,32 +364,37 @@
 
     // Create an iterator for the internal list
     std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>>::const_iterator
-        it = devices_by_id_.find(deviceInfo.Id());
+        it = discovered_devices_by_id_.find(deviceInfo.Id());
 
     // Add to our internal list if necessary
-    if (it == devices_by_id_.end()) {
-      // Create a bluetooth device out of this id
-      winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync(
-          deviceInfo.Id())
-          .Completed(
-              [this, deviceInfo, wbd = std::move(windowsBluetoothDevice)](
-                  auto&& async,
-                  winrt::Windows::Foundation::AsyncStatus status) {
-                EnterCriticalSection(&critical_section_);
-
-                std::unique_ptr<BluetoothDevice> bluetoothDevice =
-                    std::make_unique<BluetoothDevice>(async.get());
-
-                devices_by_id_[deviceInfo.Id()] = std::move(bluetoothDevice);
-
-                if (discovery_callback_.device_discovered_cb != nullptr) {
-                  discovery_callback_.device_discovered_cb(
-                      *devices_by_id_[deviceInfo.Id()]);
-                }
-
-                LeaveCriticalSection(&critical_section_);
-              });
+    if (it != discovered_devices_by_id_.end()) {
+      // We're already tracking this one
+      return winrt::fire_and_forget();
     }
+
+    // Create a bluetooth device out of this id
+    winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync(
+        deviceInfo.Id())
+        .Completed([this, deviceInfo](
+                       winrt::Windows::Foundation::IAsyncOperation<
+                           winrt::Windows::Devices::Bluetooth::BluetoothDevice>
+                           bluetoothDevice,
+                       winrt::Windows::Foundation::AsyncStatus status) {
+          EnterCriticalSection(&critical_section_);
+
+          std::unique_ptr<BluetoothDevice> bluetoothDeviceP =
+              std::make_unique<BluetoothDevice>(bluetoothDevice.get());
+
+          discovered_devices_by_id_[deviceInfo.Id()] =
+              std::move(bluetoothDeviceP);
+
+          if (discovery_callback_.device_discovered_cb != nullptr) {
+            discovery_callback_.device_discovered_cb(
+                *discovered_devices_by_id_[deviceInfo.Id()]);
+          }
+
+          LeaveCriticalSection(&critical_section_);
+        });
   }
 
   return winrt::fire_and_forget();
@@ -393,10 +402,30 @@
 
 winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
     DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) {
-  if (IsWatcherStarted()) {
-    // TODO(jfcarroll): Check for device name change
+  EnterCriticalSection(&critical_section_);
+
+  if (!IsWatcherStarted()) {
+    // Spurious call, watcher has stopped or wasn't started
+    LeaveCriticalSection(&critical_section_);
+    return winrt::fire_and_forget();
   }
 
+  auto it = discovered_devices_by_id_.find(deviceInfoUpdate.Id());
+
+  if (it == discovered_devices_by_id_.end()) {
+    LeaveCriticalSection(&critical_section_);
+    // Not tracking this device
+    return winrt::fire_and_forget();
+  }
+
+  if (deviceInfoUpdate.Properties().HasKey(
+          winrt::to_hstring("System.ItemNameDisplay"))) {
+    discovery_callback_.device_name_changed_cb(
+        *discovered_devices_by_id_[deviceInfoUpdate.Id()]);
+  }
+
+  LeaveCriticalSection(&critical_section_);
+
   return winrt::fire_and_forget();
 }
 
@@ -404,14 +433,17 @@
     DeviceWatcher sender, DeviceInformationUpdate deviceInfo) {
   EnterCriticalSection(&critical_section_);
 
-  if (IsWatcherStarted()) {
-    if (discovery_callback_.device_lost_cb != nullptr) {
-      discovery_callback_.device_lost_cb(*devices_by_id_[deviceInfo.Id()]);
-    }
-
-    devices_by_id_.erase(deviceInfo.Id());
+  if (!IsWatcherStarted()) {
+    return winrt::fire_and_forget();
   }
 
+  if (discovery_callback_.device_lost_cb != nullptr) {
+    discovery_callback_.device_lost_cb(
+        *discovered_devices_by_id_[deviceInfo.Id()]);
+  }
+
+  discovered_devices_by_id_.erase(deviceInfo.Id());
+
   LeaveCriticalSection(&critical_section_);
 
   return winrt::fire_and_forget();
diff --git a/cpp/platform/impl/windows/bluetooth_classic_medium.h b/cpp/platform/impl/windows/bluetooth_classic_medium.h
index a5d9692..2d05ef1 100644
--- a/cpp/platform/impl/windows/bluetooth_classic_medium.h
+++ b/cpp/platform/impl/windows/bluetooth_classic_medium.h
@@ -173,7 +173,8 @@
 
   // hstring is the only type of string winrt understands.
   // https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/hstring
-  std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>> devices_by_id_;
+  std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>>
+      discovered_devices_by_id_;
 
   // CRITICAL_SECTION is a lightweight synchronization mechanism
   // https://docs.microsoft.com/en-us/windows/win32/sync/critical-section-objects
diff --git a/cpp/platform/impl/windows/bluetooth_classic_socket.cc b/cpp/platform/impl/windows/bluetooth_classic_socket.cc
index 3ce04b3..cda204e 100644
--- a/cpp/platform/impl/windows/bluetooth_classic_socket.cc
+++ b/cpp/platform/impl/windows/bluetooth_classic_socket.cc
@@ -23,10 +23,6 @@
 
 BluetoothSocket::BluetoothSocket(StreamSocket streamSocket)
     : windows_socket_(streamSocket) {
-  bluetooth_device_ = std::make_unique<BluetoothDevice>(
-      winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromHostNameAsync(
-          windows_socket_.Information().RemoteHostName())
-          .get());
   input_stream_ =
       std::make_unique<BluetoothInputStream>(windows_socket_.InputStream());
   output_stream_ =