Darwin: Move preWarmCommissioningSession to MTRDeviceControllerFactory (#33184)

* Darwin: Move preWarmCommissioningSession to MTRDeviceControllerFactory

This makes it possible to start pre-warming before a MTRDeviceController has
been created, since doing that requires the client to have obtained various
configuration details.

* Apply suggestions from code review

Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>

* Tweaks from review

* restyle

---------

Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.h b/src/darwin/Framework/CHIP/MTRDeviceController.h
index 2662d4b..112bd34 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceController.h
+++ b/src/darwin/Framework/CHIP/MTRDeviceController.h
@@ -178,16 +178,8 @@
                                                         error:(NSError * __autoreleasing *)error
     MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4));
 
-/**
- * Optionally pre-warm the controller for setting up a commissioning session.
- * This may be called before setupCommissioningSessionWithPayload if it's known
- * that a commissioning attempt will soon take place but the commissioning
- * payload is not known yet.
- *
- * For example this may do a BLE scan in advance so results are ready earlier
- * once the discriminator is known.
- */
-- (void)preWarmCommissioningSession MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4));
+- (void)preWarmCommissioningSession MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))
+    MTR_NEWLY_DEPRECATED("-[MTRDeviceControllerFactory preWarmCommissioningSession]");
 
 /**
  * Set the Delegate for the device controller  as well as the Queue on which the Delegate callbacks will be triggered
diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm
index ec327a0..94d9882 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceController.mm
+++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm
@@ -86,7 +86,6 @@
 static NSString * const kErrorPartialDacVerifierInit = @"Init failure while creating a partial DAC verifier";
 static NSString * const kErrorPairDevice = @"Failure while pairing the device";
 static NSString * const kErrorStopPairing = @"Failure while trying to stop the pairing process";
-static NSString * const kErrorPreWarmCommissioning = @"Failure while trying to pre-warm the commissioning process";
 static NSString * const kErrorOpenPairingWindow = @"Open Pairing Window failed";
 static NSString * const kErrorNotRunning = @"Controller is not running. Call startup first.";
 static NSString * const kErrorSetupCodeGen = @"Generating Manual Pairing Code failed";
@@ -896,15 +895,7 @@
 
 - (void)preWarmCommissioningSession
 {
-    auto block = ^{
-        auto errorCode = chip::DeviceLayer::PlatformMgrImpl().PrepareCommissioning();
-        MATTER_LOG_METRIC(kMetricPreWarmCommissioning, errorCode);
-
-        // The checkForError is just so it logs
-        [MTRDeviceController checkForError:errorCode logMsg:kErrorPreWarmCommissioning error:nil];
-    };
-
-    [self syncRunOnWorkQueue:block error:nil];
+    [_factory preWarmCommissioningSession];
 }
 
 - (MTRBaseDevice *)deviceBeingCommissionedWithNodeID:(NSNumber *)nodeID error:(NSError * __autoreleasing *)error
diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h
index 62080b3..5965d8b 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h
+++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h
@@ -177,6 +177,18 @@
 - (MTRDeviceController * _Nullable)createControllerOnNewFabric:(MTRDeviceControllerStartupParams *)startupParams
                                                          error:(NSError * __autoreleasing *)error;
 
+/**
+ * If possible, pre-warm the Matter stack for setting up a commissioning session.
+ *
+ * This may be called before -[MTRDeviceController setupCommissioningSessionWithPayload:]
+ * if it is known that a commissioning attempt will soon take place, but the commissioning
+ * payload is not known yet.
+ *
+ * The controller factory must be running for pre-warming to take place.  Pre-warming can take place
+ * before any controllers are started.
+ */
+- (void)preWarmCommissioningSession MTR_NEWLY_AVAILABLE;
+
 @end
 
 /**
diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm
index 25939d6..c7d69d2 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm
+++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm
@@ -34,6 +34,7 @@
 #import "MTRFabricInfo_Internal.h"
 #import "MTRFramework.h"
 #import "MTRLogging_Internal.h"
+#import "MTRMetricKeys.h"
 #import "MTRMetricsCollector.h"
 #import "MTROTAProviderDelegateBridge.h"
 #import "MTROperationalBrowser.h"
@@ -66,6 +67,7 @@
 
 using namespace chip;
 using namespace chip::Controller;
+using namespace chip::Tracing::DarwinFramework;
 
 static bool sExitHandlerRegistered = false;
 static void ShutdownOnExit()
@@ -83,6 +85,11 @@
 @end
 
 MTR_DIRECT_MEMBERS
+@interface MTRDeviceControllerFactory ()
+- (void)preWarmCommissioningSessionDone;
+@end
+
+MTR_DIRECT_MEMBERS
 @implementation MTRDeviceControllerFactory {
     dispatch_queue_t _chipWorkQueue;
     DeviceControllerFactory * _controllerFactory;
@@ -163,6 +170,13 @@
     // in an atomic way that endpoint IDs are unique.
     NSMutableArray<MTRServerEndpoint *> * _serverEndpoints;
     os_unfair_lock _serverEndpointsLock; // Protects access to _serverEndpoints.
+
+    class final : public DeviceLayer::BleScannerDelegate {
+        void OnBleScanStopped() override
+        {
+            [MTRDeviceControllerFactory.sharedInstance preWarmCommissioningSessionDone];
+        }
+    } _preWarmingDelegate;
 }
 
 + (void)initialize
@@ -742,6 +756,32 @@
                                   error:error];
 }
 
+- (void)preWarmCommissioningSession
+{
+    dispatch_async(_chipWorkQueue, ^{
+        CHIP_ERROR err = CHIP_ERROR_INCORRECT_STATE;
+        if (!self->_running) {
+            MTR_LOG_ERROR("Can't pre-warm, Matter controller factory is not running");
+        } else {
+            MTR_LOG_DEFAULT("Pre-warming commissioning session");
+            self->_controllerFactory->EnsureAndRetainSystemState();
+            err = DeviceLayer::PlatformMgrImpl().StartBleScan(&self->_preWarmingDelegate, DeviceLayer::BleScanMode::kPreWarm);
+            if (err != CHIP_NO_ERROR) {
+                MTR_LOG_ERROR("Pre-warming failed: %" CHIP_ERROR_FORMAT, err.Format());
+                self->_controllerFactory->ReleaseSystemState();
+            }
+        }
+        MATTER_LOG_METRIC(kMetricPreWarmCommissioning, err);
+    });
+}
+
+- (void)preWarmCommissioningSessionDone
+{
+    assertChipStackLockedByCurrentThread();
+    MTR_LOG_DEFAULT("Pre-warming done");
+    self->_controllerFactory->ReleaseSystemState();
+}
+
 // Finds a fabric that matches the given params, if one exists.
 //
 // Returns NO on failure, YES on success.  If YES is returned, the
diff --git a/src/platform/Darwin/BLEManagerImpl.cpp b/src/platform/Darwin/BLEManagerImpl.cpp
index c0af6cc..8ff634c 100644
--- a/src/platform/Darwin/BLEManagerImpl.cpp
+++ b/src/platform/Darwin/BLEManagerImpl.cpp
@@ -87,24 +87,18 @@
     }
 }
 
-CHIP_ERROR BLEManagerImpl::StartScan(BleScannerDelegate * delegate)
+CHIP_ERROR BLEManagerImpl::StartScan(BleScannerDelegate * delegate, BleScanMode mode)
 {
-    if (mConnectionDelegate)
-    {
-        static_cast<BleConnectionDelegateImpl *>(mConnectionDelegate)->StartScan(delegate);
-        return CHIP_NO_ERROR;
-    }
-    return CHIP_ERROR_INCORRECT_STATE;
+    VerifyOrReturnError(mConnectionDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE);
+    static_cast<BleConnectionDelegateImpl *>(mConnectionDelegate)->StartScan(delegate, mode);
+    return CHIP_NO_ERROR;
 }
 
 CHIP_ERROR BLEManagerImpl::StopScan()
 {
-    if (mConnectionDelegate)
-    {
-        static_cast<BleConnectionDelegateImpl *>(mConnectionDelegate)->StopScan();
-        return CHIP_NO_ERROR;
-    }
-    return CHIP_ERROR_INCORRECT_STATE;
+    VerifyOrReturnError(mConnectionDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE);
+    static_cast<BleConnectionDelegateImpl *>(mConnectionDelegate)->StopScan();
+    return CHIP_NO_ERROR;
 }
 
 bool BLEManagerImpl::_IsAdvertisingEnabled()
diff --git a/src/platform/Darwin/BLEManagerImpl.h b/src/platform/Darwin/BLEManagerImpl.h
index 72856ff..194dadb 100644
--- a/src/platform/Darwin/BLEManagerImpl.h
+++ b/src/platform/Darwin/BLEManagerImpl.h
@@ -25,14 +25,12 @@
 
 #include <lib/core/Global.h>
 #include <lib/support/CodeUtils.h>
+#include <platform/Darwin/BleScannerDelegate.h>
 
 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
 
 namespace chip {
 namespace DeviceLayer {
-
-class BleScannerDelegate;
-
 namespace Internal {
 
 using namespace chip::Ble;
@@ -48,7 +46,7 @@
 
 public:
     CHIP_ERROR ConfigureBle(uint32_t aNodeId, bool aIsCentral) { return CHIP_NO_ERROR; }
-    CHIP_ERROR StartScan(BleScannerDelegate * delegate = nullptr);
+    CHIP_ERROR StartScan(BleScannerDelegate * delegate, BleScanMode mode = BleScanMode::kDefault);
     CHIP_ERROR StopScan();
 
 private:
diff --git a/src/platform/Darwin/BleConnectionDelegate.h b/src/platform/Darwin/BleConnectionDelegate.h
index 1441f60..585624a 100644
--- a/src/platform/Darwin/BleConnectionDelegate.h
+++ b/src/platform/Darwin/BleConnectionDelegate.h
@@ -18,6 +18,7 @@
 #pragma once
 
 #include <ble/Ble.h>
+#include <platform/Darwin/BleScannerDelegate.h>
 
 namespace chip {
 namespace DeviceLayer {
@@ -26,11 +27,12 @@
 class BleConnectionDelegateImpl : public Ble::BleConnectionDelegate
 {
 public:
-    void StartScan(BleScannerDelegate * delegate = nullptr);
+    void StartScan(BleScannerDelegate * delegate, BleScanMode mode = BleScanMode::kDefault);
     void StopScan();
-    virtual void NewConnection(Ble::BleLayer * bleLayer, void * appState, const SetupDiscriminator & connDiscriminator);
-    virtual void NewConnection(Ble::BleLayer * bleLayer, void * appState, BLE_CONNECTION_OBJECT connObj);
-    virtual CHIP_ERROR CancelConnection();
+
+    void NewConnection(Ble::BleLayer * bleLayer, void * appState, const SetupDiscriminator & connDiscriminator) override;
+    void NewConnection(Ble::BleLayer * bleLayer, void * appState, BLE_CONNECTION_OBJECT connObj) override;
+    CHIP_ERROR CancelConnection() override;
 
 private:
     CHIP_ERROR DoCancel();
diff --git a/src/platform/Darwin/BleConnectionDelegateImpl.mm b/src/platform/Darwin/BleConnectionDelegateImpl.mm
index b325d07..5eb1c4a 100644
--- a/src/platform/Darwin/BleConnectionDelegateImpl.mm
+++ b/src/platform/Darwin/BleConnectionDelegateImpl.mm
@@ -38,18 +38,19 @@
 #import "UUIDHelper.h"
 
 using namespace chip::Ble;
+using namespace chip::DeviceLayer;
 using namespace chip::Tracing::DarwinPlatform;
 
 constexpr uint64_t kScanningWithDiscriminatorTimeoutInSeconds = 60;
-constexpr uint64_t kScanningWithoutDelegateTimeoutInSeconds = 120;
+constexpr uint64_t kPreWarmScanTimeoutInSeconds = 120;
 constexpr uint64_t kCachePeripheralTimeoutInSeconds
     = static_cast<uint64_t>(CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX / 1000.0 * 8.0 * 0.625);
 constexpr char kBleWorkQueueName[] = "org.csa-iot.matter.framework.ble.workqueue";
 
 typedef NS_ENUM(uint8_t, BleConnectionMode) {
     kUndefined = 0,
-    kScanningWithoutDelegate,
     kScanning,
+    kScanningWithTimeout,
     kConnecting,
 };
 
@@ -72,16 +73,14 @@
 @property (unsafe_unretained, nonatomic) chip::Ble::BleLayer * mBleLayer;
 
 - (id)initWithQueue:(dispatch_queue_t)queue;
-- (id)initWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate queue:(dispatch_queue_t)queue;
+- (id)initWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate prewarm:(bool)prewarm queue:(dispatch_queue_t)queue;
 - (id)initWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator queue:(dispatch_queue_t)queue;
 - (void)setBleLayer:(chip::Ble::BleLayer *)bleLayer;
 - (void)start;
 - (void)stop;
-- (void)updateWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate;
+- (void)updateWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate prewarm:(bool)prewarm;
 - (void)updateWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator;
 - (void)updateWithPeripheral:(CBPeripheral *)peripheral;
-- (BOOL)isScanningWithoutDelegate;
-- (BOOL)isScanning;
 - (BOOL)isConnecting;
 - (void)addPeripheralToCache:(CBPeripheral *)peripheral data:(NSData *)data;
 - (void)removePeripheralFromCache:(CBPeripheral *)peripheral;
@@ -162,26 +161,40 @@
             });
         }
 
-        void BleConnectionDelegateImpl::StartScan(BleScannerDelegate * delegate)
+        void BleConnectionDelegateImpl::StartScan(BleScannerDelegate * delegate, BleScanMode mode)
         {
             assertChipStackLockedByCurrentThread();
 
-            ChipLogProgress(Ble, "ConnectionDelegate StartScan%s", (delegate ? " with delegate" : ""));
+            bool prewarm = (mode == BleScanMode::kPreWarm);
+            ChipLogProgress(Ble, "ConnectionDelegate StartScan (%s)", (prewarm ? "pre-warm" : "default"));
 
             if (!bleWorkQueue) {
                 bleWorkQueue = dispatch_queue_create(kBleWorkQueueName, DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
             }
 
             dispatch_async(bleWorkQueue, ^{
+                // Pre-warming is best-effort, don't cancel an ongoing scan or connection attempt
+                if (prewarm && ble) {
+                    // TODO: Once we get rid of the separate BLE queue we can just return CHIP_ERROR_BUSY.
+                    // That will also allow these cases to be distinguished in our metric.
+                    ChipLogProgress(Ble, "Not starting pre-warm scan, an operation is already in progress");
+                    if (delegate) {
+                        dispatch_async(PlatformMgrImpl().GetWorkQueue(), ^{
+                            delegate->OnBleScanStopped();
+                        });
+                    }
+                    return;
+                }
+
                 // If the previous connection delegate was not a try to connect to something, just reuse it instead of
                 // creating a brand new connection but update the discriminator and the ble layer members.
                 if (ble and ![ble isConnecting]) {
-                    [ble updateWithDelegate:delegate];
+                    [ble updateWithDelegate:delegate prewarm:prewarm];
                     return;
                 }
 
                 [ble stop];
-                ble = [[BleConnection alloc] initWithDelegate:delegate queue:bleWorkQueue];
+                ble = [[BleConnection alloc] initWithDelegate:delegate prewarm:prewarm queue:bleWorkQueue];
                 // Do _not_ set onConnectionComplete and onConnectionError
                 // here.  The connection callbacks we have expect an appState
                 // that we do not have here, and in any case connection
@@ -245,14 +258,16 @@
     return self;
 }
 
-- (id)initWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate queue:(dispatch_queue_t)queue
+- (id)initWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate prewarm:(bool)prewarm queue:(dispatch_queue_t)queue
 {
     self = [self initWithQueue:queue];
     if (self) {
         _scannerDelegate = delegate;
-        _currentMode = (delegate == nullptr) ? kScanningWithoutDelegate : kScanning;
-        if (_currentMode == kScanningWithoutDelegate) {
-            [self setupTimer:kScanningWithoutDelegateTimeoutInSeconds];
+        if (prewarm) {
+            _currentMode = kScanningWithTimeout;
+            [self setupTimer:kPreWarmScanTimeoutInSeconds];
+        } else {
+            _currentMode = kScanning;
         }
     }
 
@@ -271,16 +286,6 @@
     return self;
 }
 
-- (BOOL)isScanningWithoutDelegate
-{
-    return _currentMode == kScanningWithoutDelegate;
-}
-
-- (BOOL)isScanning
-{
-    return _currentMode == kScanning;
-}
-
 - (BOOL)isConnecting
 {
     return _currentMode == kConnecting;
@@ -592,7 +597,7 @@
 
 - (void)stop
 {
-    _scannerDelegate = nil;
+    [self detachScannerDelegate];
     _found = false;
     [self stopScanning];
     [self removePeripheralsFromCache];
@@ -669,31 +674,46 @@
     [_centralManager connectPeripheral:peripheral options:nil];
 }
 
-- (void)updateWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate
+- (void)detachScannerDelegate
 {
-    _scannerDelegate = delegate;
-    _currentMode = (delegate == nullptr) ? kScanningWithoutDelegate : kScanning;
+    auto * existingDelegate = _scannerDelegate;
+    if (existingDelegate) {
+        _scannerDelegate = nullptr;
+        dispatch_async(_chipWorkQueue, ^{
+            existingDelegate->OnBleScanStopped();
+        });
+    }
+}
 
-    if (_currentMode == kScanning) {
-        [self clearTimer];
+- (void)updateWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate prewarm:(bool)prewarm
+{
+    [self detachScannerDelegate];
 
+    if (delegate) {
         for (CBPeripheral * cachedPeripheral in _cachedPeripherals) {
             NSData * serviceData = _cachedPeripherals[cachedPeripheral][@"data"];
             dispatch_async(_chipWorkQueue, ^{
                 ChipBLEDeviceIdentificationInfo info;
                 memcpy(&info, [serviceData bytes], sizeof(info));
-                _scannerDelegate->OnBleScanAdd((__bridge void *) cachedPeripheral, info);
+                delegate->OnBleScanAdd((__bridge void *) cachedPeripheral, info);
             });
         }
+        _scannerDelegate = delegate;
+    }
+
+    if (prewarm) {
+        _currentMode = kScanningWithTimeout;
+        [self setupTimer:kPreWarmScanTimeoutInSeconds];
     } else {
-        [self setupTimer:kScanningWithoutDelegateTimeoutInSeconds];
+        _currentMode = kScanning;
+        [self clearTimer];
     }
 }
 
 - (void)updateWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator
 {
+    [self detachScannerDelegate];
     _deviceDiscriminator = deviceDiscriminator;
-    _scannerDelegate = nil;
     _currentMode = kConnecting;
 
     CBPeripheral * peripheral = nil;
@@ -722,7 +742,7 @@
 
 - (void)updateWithPeripheral:(CBPeripheral *)peripheral
 {
-    _scannerDelegate = nil;
+    [self detachScannerDelegate];
     _currentMode = kConnecting;
 
     MATTER_LOG_METRIC_BEGIN(kMetricBLEDiscoveredMatchingPeripheral);
diff --git a/src/platform/Darwin/BleScannerDelegate.h b/src/platform/Darwin/BleScannerDelegate.h
index 9c96445..177bf25 100644
--- a/src/platform/Darwin/BleScannerDelegate.h
+++ b/src/platform/Darwin/BleScannerDelegate.h
@@ -24,16 +24,29 @@
 namespace chip {
 namespace DeviceLayer {
 
+enum class BleScanMode
+{
+    /// Scan continues until stopped.
+    /// Replaces existing BLE operation.
+    kDefault = 0,
+    /// Scan stops automatically after some time.
+    /// Does not replace an existing BLE operation.
+    kPreWarm,
+};
+
 class DLL_EXPORT BleScannerDelegate
 {
 public:
     virtual ~BleScannerDelegate() {}
 
     // Called when a scan result is available.
-    virtual void OnBleScanAdd(BLE_CONNECTION_OBJECT connObj, const Ble::ChipBLEDeviceIdentificationInfo & info) = 0;
+    virtual void OnBleScanAdd(BLE_CONNECTION_OBJECT connObj, const Ble::ChipBLEDeviceIdentificationInfo & info) {}
 
     // Called when a scan result is not available anymore.
-    virtual void OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) = 0;
+    virtual void OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) {}
+
+    // Called when the scan has been stopped
+    virtual void OnBleScanStopped() {}
 };
 
 } // namespace DeviceLayer
diff --git a/src/platform/Darwin/PlatformManagerImpl.cpp b/src/platform/Darwin/PlatformManagerImpl.cpp
index b7dc8b6..d1dc530 100644
--- a/src/platform/Darwin/PlatformManagerImpl.cpp
+++ b/src/platform/Darwin/PlatformManagerImpl.cpp
@@ -156,28 +156,24 @@
     return dispatch_get_specific(this) == this;
 }
 
-CHIP_ERROR PlatformManagerImpl::StartBleScan(BleScannerDelegate * delegate)
+CHIP_ERROR PlatformManagerImpl::StartBleScan(BleScannerDelegate * delegate, BleScanMode mode)
 {
 #if CONFIG_NETWORK_LAYER_BLE
-    ReturnErrorOnFailureWithMetric(kMetricBLEScan, Internal::BLEMgrImpl().StartScan(delegate));
-#endif // CONFIG_NETWORK_LAYER_BLE
+    ReturnErrorOnFailureWithMetric(kMetricBLEScan, Internal::BLEMgrImpl().StartScan(delegate, mode));
     return CHIP_NO_ERROR;
+#else
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // CONFIG_NETWORK_LAYER_BLE
 }
 
 CHIP_ERROR PlatformManagerImpl::StopBleScan()
 {
 #if CONFIG_NETWORK_LAYER_BLE
     ReturnErrorOnFailureWithMetric(kMetricBLEScan, Internal::BLEMgrImpl().StopScan());
-#endif // CONFIG_NETWORK_LAYER_BLE
     return CHIP_NO_ERROR;
-}
-
-CHIP_ERROR PlatformManagerImpl::PrepareCommissioning()
-{
-#if CONFIG_NETWORK_LAYER_BLE
-    ReturnErrorOnFailureWithMetric(kMetricBLEStartPreWarmScan, Internal::BLEMgrImpl().StartScan());
+#else
+    return CHIP_ERROR_NOT_IMPLEMENTED;
 #endif // CONFIG_NETWORK_LAYER_BLE
-    return CHIP_NO_ERROR;
 }
 
 } // namespace DeviceLayer
diff --git a/src/platform/Darwin/PlatformManagerImpl.h b/src/platform/Darwin/PlatformManagerImpl.h
index 12b515a..ba37bad 100644
--- a/src/platform/Darwin/PlatformManagerImpl.h
+++ b/src/platform/Darwin/PlatformManagerImpl.h
@@ -24,6 +24,7 @@
 #pragma once
 
 #include <lib/core/Global.h>
+#include <platform/Darwin/BleScannerDelegate.h>
 #include <platform/internal/GenericPlatformManagerImpl.h>
 
 #include <atomic>
@@ -49,9 +50,8 @@
     dispatch_queue_t GetWorkQueue() { return mWorkQueue; }
     bool IsWorkQueueCurrentQueue() const;
 
-    CHIP_ERROR StartBleScan(BleScannerDelegate * delegate = nullptr);
+    CHIP_ERROR StartBleScan(BleScannerDelegate * delegate, BleScanMode mode = BleScanMode::kDefault);
     CHIP_ERROR StopBleScan();
-    CHIP_ERROR PrepareCommissioning();
 
     System::Clock::Timestamp GetStartTime() { return mStartTime; }