Allow creating Darwin controllers via alloc/initWithParameters. (#29025)

* Allow creating Darwin controllers via alloc/initWithParameters.

* Address review comment.
diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.h b/src/darwin/Framework/CHIP/MTRDeviceController.h
index d863679..3831a49 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceController.h
+++ b/src/darwin/Framework/CHIP/MTRDeviceController.h
@@ -23,6 +23,10 @@
 
 @class MTRBaseDevice;
 
+#if MTR_PER_CONTROLLER_STORAGE_ENABLED
+@class MTRDeviceControllerParameters;
+#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
+
 NS_ASSUME_NONNULL_BEGIN
 
 MTR_DEPRECATED("Please use MTRBaseDevice deviceWithNodeID", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4))
@@ -37,11 +41,27 @@
 @interface MTRDeviceController : NSObject
 
 /**
- * Controllers are created via the MTRDeviceControllerFactory object.
+ * Controllers are created via the MTRDeviceControllerFactory object or
+ * initialized via initWithParameters:error:.
  */
 - (instancetype)init NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
 
+#if MTR_PER_CONTROLLER_STORAGE_ENABLED
+/**
+ * Initialize a device controller with the provided parameters.  This will:
+ *
+ * 1) Auto-start the MTRDeviceControllerFactory in storage-per-controller mode
+ *    if it has not already been started.
+ * 2) Return nil or a running controller.
+ *
+ * Once this returns non-nil, it's the caller's resposibility to call shutdown
+ * on the controller to avoid leaking it.
+ */
+- (nullable instancetype)initWithParameters:(MTRDeviceControllerParameters *)parameters
+                                      error:(NSError * __autoreleasing *)error MTR_NEWLY_AVAILABLE;
+#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
+
 /**
  * If true, the controller has not been shut down yet.
  */
diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm
index 98d757d..ee0f8455 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceController.mm
+++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm
@@ -16,6 +16,12 @@
  */
 #import <Matter/MTRDefines.h>
 
+#if MTR_PER_CONTROLLER_STORAGE_ENABLED
+#import <Matter/MTRDeviceControllerParameters.h>
+#else
+#import "MTRDeviceControllerParameters_Wrapper.h"
+#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
+
 #import "MTRDeviceController_Internal.h"
 
 #import "MTRAttestationTrustStoreBridge.h"
@@ -119,6 +125,20 @@
 
 @implementation MTRDeviceController
 
+- (nullable instancetype)initWithParameters:(MTRDeviceControllerParameters *)parameters error:(NSError * __autoreleasing *)error
+{
+    __auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
+    if (!factory.isRunning) {
+        auto * params = [[MTRDeviceControllerFactoryParams alloc] initWithoutStorage];
+
+        if (![factory startControllerFactory:params error:error]) {
+            return nil;
+        }
+    }
+
+    return [factory initializeController:self withParameters:parameters error:error];
+}
+
 - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory
                           queue:(dispatch_queue_t)queue
                 storageDelegate:(id<MTRDeviceControllerStorageDelegate> _Nullable)storageDelegate
diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h
index 5cb4b7c..3dfb3ea 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h
+++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h
@@ -23,11 +23,6 @@
 #import <Foundation/Foundation.h>
 #import <Matter/MTRCertificates.h>
 #import <Matter/MTRDefines.h>
-#if MTR_PER_CONTROLLER_STORAGE_ENABLED
-#import <Matter/MTRDeviceControllerStartupParameters.h>
-#else
-@class MTRDeviceControllerStartupParameters;
-#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -42,6 +37,9 @@
 
 API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))
 @interface MTRDeviceControllerFactoryParams : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
+
 /*
  * Storage used to store persistent information for the fabrics the
  * controllers ends up interacting with.  This is only used if "initWithStorage"
@@ -98,15 +96,6 @@
  */
 - (instancetype)initWithStorage:(id<MTRStorage>)storage;
 
-#if MTR_PER_CONTROLLER_STORAGE_ENABLED
-/*
- * Initialize the device controller factory without storage.  In this mode,
- * device controllers will need to have per-controller storage provided to allow
- * storing controller-specific information.
- */
-- (instancetype)init MTR_NEWLY_AVAILABLE;
-#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
-
 @end
 
 API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))
@@ -188,20 +177,6 @@
 - (MTRDeviceController * _Nullable)createControllerOnNewFabric:(MTRDeviceControllerStartupParams *)startupParams
                                                          error:(NSError * __autoreleasing *)error;
 
-#if MTR_PER_CONTROLLER_STORAGE_ENABLED
-/**
- * Create an MTRDeviceController.  Returns nil on failure.
- *
- * This method will fail if there is already a controller running for the given
- * node identity.
- *
- * This method will fail if the controller factory was not initialized in
- * storage-per-controller mode.
- */
-- (MTRDeviceController * _Nullable)createController:(MTRDeviceControllerStartupParameters *)startupParameters
-                                              error:(NSError * __autoreleasing *)error MTR_NEWLY_AVAILABLE;
-#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
-
 @end
 
 MTR_DEPRECATED(
diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm
index 31b261a..2166082 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm
+++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm
@@ -17,6 +17,14 @@
 #import "MTRDeviceControllerFactory.h"
 #import "MTRDeviceControllerFactory_Internal.h"
 
+#import <Matter/MTRDefines.h>
+
+#if MTR_PER_CONTROLLER_STORAGE_ENABLED
+#import <Matter/MTRDeviceControllerParameters.h>
+#else
+#import "MTRDeviceControllerParameters_Wrapper.h"
+#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
+
 #import "MTRCertificates.h"
 #import "MTRControllerAccessControl.h"
 #import "MTRDemuxingStorage.h"
@@ -34,9 +42,6 @@
 #import "MTRPersistentStorageDelegateBridge.h"
 #import "MTRSessionResumptionStorageBridge.h"
 #import "NSDataSpanConversion.h"
-#if !MTR_PER_CONTROLLER_STORAGE_ENABLED
-#import "MTRDeviceControllerStartupParameters_Wrapper.h"
-#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
 
 #import <os/lock.h>
 
@@ -547,8 +552,12 @@
  * The fabricChecker block will run on the Matter queue, and is expected to
  * return nil if pre-startup fabric table checks fail, and set fabricError to
  * the right error value in that situation.
+ *
+ * The provided controller is expected to have just been allocated and to not be
+ * initialized yet.
  */
-- (MTRDeviceController * _Nullable)_startDeviceController:(id)startupParams
+- (MTRDeviceController * _Nullable)_startDeviceController:(MTRDeviceController *)controller
+                                            startupParams:(id)startupParams
                                             fabricChecker:(MTRDeviceControllerStartupParamsInternal * (^)(FabricTable * fabricTable,
                                                               MTRDeviceController * controller,
                                                               CHIP_ERROR & fabricError))fabricChecker
@@ -566,8 +575,8 @@
     NSUUID * uniqueIdentifier;
     id<MTROTAProviderDelegate> _Nullable otaProviderDelegate;
     dispatch_queue_t _Nullable otaProviderDelegateQueue;
-    if ([startupParams isKindOfClass:[MTRDeviceControllerStartupParameters class]]) {
-        MTRDeviceControllerStartupParameters * params = startupParams;
+    if ([startupParams isKindOfClass:[MTRDeviceControllerParameters class]]) {
+        MTRDeviceControllerParameters * params = startupParams;
         storageDelegate = params.storageDelegate;
         storageDelegateQueue = params.storageDelegateQueue;
         uniqueIdentifier = params.uniqueIdentifier;
@@ -608,20 +617,35 @@
         otaProviderDelegateQueue = self.otaProviderDelegateQueue;
     }
 
-    // Create the controller, so we start the event loop, since we plan to do
-    // our fabric table operations there.
-    auto * controller = [self _createController:storageDelegate
-                           storageDelegateQueue:storageDelegateQueue
-                            otaProviderDelegate:otaProviderDelegate
-                       otaProviderDelegateQueue:otaProviderDelegateQueue
-                               uniqueIdentifier:uniqueIdentifier];
+    controller = [controller initWithFactory:self
+                                       queue:_chipWorkQueue
+                             storageDelegate:storageDelegate
+                        storageDelegateQueue:storageDelegateQueue
+                         otaProviderDelegate:otaProviderDelegate
+                    otaProviderDelegateQueue:otaProviderDelegateQueue
+                            uniqueIdentifier:uniqueIdentifier];
     if (controller == nil) {
         if (error != nil) {
-            *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_NO_MEMORY];
+            *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_ARGUMENT];
         }
         return nil;
     }
 
+    if ([_controllers count] == 0) {
+        // Bringing up the first controller.  Start the event loop now.  If we
+        // fail to bring it up, its cleanup will stop the event loop again.
+        chip::DeviceLayer::PlatformMgrImpl().StartEventLoopTask();
+        dispatch_sync(_chipWorkQueue, ^{
+            self->_operationalBrowser = new MTROperationalBrowser(self, self->_chipWorkQueue);
+        });
+    }
+
+    // Add the controller to _controllers now, so if we fail partway through its
+    // startup we will still do the right cleanups.
+    os_unfair_lock_lock(&_controllersLock);
+    [_controllers addObject:controller];
+    os_unfair_lock_unlock(&_controllersLock);
+
     __block MTRDeviceControllerStartupParamsInternal * params = nil;
     __block CHIP_ERROR fabricError = CHIP_NO_ERROR;
 
@@ -716,7 +740,8 @@
         return nil;
     }
 
-    return [self _startDeviceController:startupParams
+    return [self _startDeviceController:[MTRDeviceController alloc]
+                          startupParams:startupParams
                           fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
                               FabricTable * fabricTable, MTRDeviceController * controller, CHIP_ERROR & fabricError) {
                               const FabricInfo * fabric = nullptr;
@@ -792,7 +817,8 @@
         return nil;
     }
 
-    return [self _startDeviceController:startupParams
+    return [self _startDeviceController:[MTRDeviceController alloc]
+                          startupParams:startupParams
                           fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
                               FabricTable * fabricTable, MTRDeviceController * controller, CHIP_ERROR & fabricError) {
                               const FabricInfo * fabric = nullptr;
@@ -825,73 +851,6 @@
                                   error:error];
 }
 
-- (MTRDeviceController * _Nullable)createController:(MTRDeviceControllerStartupParameters *)startupParameters
-                                              error:(NSError * __autoreleasing *)error
-{
-    [self _assertCurrentQueueIsNotMatterQueue];
-
-    return [self _startDeviceController:startupParameters
-                          fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
-                              FabricTable * fabricTable, MTRDeviceController * controller, CHIP_ERROR & fabricError) {
-                              auto advertiseOperational = self.advertiseOperational && startupParameters.shouldAdvertiseOperational;
-                              auto * params =
-                                  [[MTRDeviceControllerStartupParamsInternal alloc] initForNewController:controller
-                                                                                             fabricTable:fabricTable
-                                                                                                keystore:self->_keystore
-                                                                                    advertiseOperational:advertiseOperational
-                                                                                                  params:startupParameters
-                                                                                                   error:fabricError];
-                              if (params != nil) {
-                                  if (params.productAttestationAuthorityCertificates == nil) {
-                                      params.productAttestationAuthorityCertificates = self.productAttestationAuthorityCertificates;
-                                  }
-                                  if (params.certificationDeclarationCertificates == nil) {
-                                      params.certificationDeclarationCertificates = self.certificationDeclarationCertificates;
-                                  }
-                              }
-                              return params;
-                          }
-                                  error:error];
-}
-
-- (MTRDeviceController * _Nullable)_createController:(id<MTRDeviceControllerStorageDelegate> _Nullable)storageDelegate
-                                storageDelegateQueue:(dispatch_queue_t _Nullable)storageDelegateQueue
-                                 otaProviderDelegate:(id<MTROTAProviderDelegate> _Nullable)otaProviderDelegate
-                            otaProviderDelegateQueue:(dispatch_queue_t _Nullable)otaProviderDelegateQueue
-                                    uniqueIdentifier:(NSUUID *)uniqueIdentifier
-{
-    [self _assertCurrentQueueIsNotMatterQueue];
-
-    MTRDeviceController * controller = [[MTRDeviceController alloc] initWithFactory:self
-                                                                              queue:_chipWorkQueue
-                                                                    storageDelegate:storageDelegate
-                                                               storageDelegateQueue:storageDelegateQueue
-                                                                otaProviderDelegate:otaProviderDelegate
-                                                           otaProviderDelegateQueue:otaProviderDelegateQueue
-                                                                   uniqueIdentifier:uniqueIdentifier];
-    if (controller == nil) {
-        MTR_LOG_ERROR("Failed to init controller");
-        return nil;
-    }
-
-    if ([_controllers count] == 0) {
-        // Bringing up the first controller.  Start the event loop now.  If we
-        // fail to bring it up, its cleanup will stop the event loop again.
-        chip::DeviceLayer::PlatformMgrImpl().StartEventLoopTask();
-        dispatch_sync(_chipWorkQueue, ^{
-            self->_operationalBrowser = new MTROperationalBrowser(self, self->_chipWorkQueue);
-        });
-    }
-
-    // Add the controller to _controllers now, so if we fail partway through its
-    // startup we will still do the right cleanups.
-    os_unfair_lock_lock(&_controllersLock);
-    [_controllers addObject:controller];
-    os_unfair_lock_unlock(&_controllersLock);
-
-    return controller;
-}
-
 // Finds a fabric that matches the given params, if one exists.
 //
 // Returns NO on failure, YES on success.  If YES is returned, the
@@ -1126,6 +1085,37 @@
     }
 }
 
+- (MTRDeviceController * _Nullable)initializeController:(MTRDeviceController *)controller
+                                         withParameters:(MTRDeviceControllerParameters *)parameters
+                                                  error:(NSError * __autoreleasing *)error
+{
+    [self _assertCurrentQueueIsNotMatterQueue];
+
+    return [self _startDeviceController:controller
+                          startupParams:parameters
+                          fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
+                              FabricTable * fabricTable, MTRDeviceController * controller, CHIP_ERROR & fabricError) {
+                              auto advertiseOperational = self.advertiseOperational && parameters.shouldAdvertiseOperational;
+                              auto * params =
+                                  [[MTRDeviceControllerStartupParamsInternal alloc] initForNewController:controller
+                                                                                             fabricTable:fabricTable
+                                                                                                keystore:self->_keystore
+                                                                                    advertiseOperational:advertiseOperational
+                                                                                                  params:parameters
+                                                                                                   error:fabricError];
+                              if (params != nil) {
+                                  if (params.productAttestationAuthorityCertificates == nil) {
+                                      params.productAttestationAuthorityCertificates = self.productAttestationAuthorityCertificates;
+                                  }
+                                  if (params.certificationDeclarationCertificates == nil) {
+                                      params.certificationDeclarationCertificates = self.certificationDeclarationCertificates;
+                                  }
+                              }
+                              return params;
+                          }
+                                  error:error];
+}
+
 - (PersistentStorageDelegate *)storageDelegate
 {
     return _persistentStorageDelegate;
@@ -1176,7 +1166,7 @@
     return self;
 }
 
-- (instancetype)init
+- (instancetype)initWithoutStorage
 {
     if (!(self = [super init])) {
         return nil;
@@ -1191,7 +1181,7 @@
     _productAttestationAuthorityCertificates = nil;
     _certificationDeclarationCertificates = nil;
     _port = nil;
-    _shouldStartServer = NO;
+    _shouldStartServer = YES;
 
     return self;
 }
diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h
index 9717f50..72827d1 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h
+++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory_Internal.h
@@ -20,6 +20,14 @@
  */
 
 #import <Foundation/Foundation.h>
+#import <Matter/MTRDefines.h>
+#import <Matter/MTRDeviceController.h>
+
+#if MTR_PER_CONTROLLER_STORAGE_ENABLED
+#import <Matter/MTRDeviceControllerParameters.h>
+#else
+#import "MTRDeviceControllerParameters_Wrapper.h"
+#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
 
 #import "MTRDeviceControllerFactory.h"
 
@@ -67,9 +75,25 @@
  */
 - (void)operationalInstanceAdded:(chip::PeerId &)operationalID;
 
+/**
+ * Initialize an MTRDeviceController with the given parameters.
+ */
+- (nullable MTRDeviceController *)initializeController:(MTRDeviceController *)controller
+                                        withParameters:(MTRDeviceControllerParameters *)parameters
+                                                 error:(NSError * __autoreleasing *)error;
+
 @property (readonly) chip::PersistentStorageDelegate * storageDelegate;
 @property (readonly) chip::Credentials::GroupDataProvider * groupData;
 
 @end
 
+@interface MTRDeviceControllerFactoryParams ()
+/*
+ * Initialize the device controller factory without storage.  In this mode,
+ * device controllers will need to have per-controller storage provided to allow
+ * storing controller-specific information.
+ */
+- (instancetype)initWithoutStorage;
+@end
+
 NS_ASSUME_NONNULL_END
diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParameters.h b/src/darwin/Framework/CHIP/MTRDeviceControllerParameters.h
similarity index 96%
rename from src/darwin/Framework/CHIP/MTRDeviceControllerStartupParameters.h
rename to src/darwin/Framework/CHIP/MTRDeviceControllerParameters.h
index 7b69f0f..bcbea79 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParameters.h
+++ b/src/darwin/Framework/CHIP/MTRDeviceControllerParameters.h
@@ -32,7 +32,7 @@
 MTR_HIDDEN
 #endif
 MTR_NEWLY_AVAILABLE
-@interface MTRDeviceControllerStartupParameters : NSObject
+@interface MTRDeviceControllerParameters : NSObject
 
 - (instancetype)init NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
@@ -81,7 +81,7 @@
 MTR_HIDDEN
 #endif
 MTR_NEWLY_AVAILABLE
-@interface MTRDeviceControllerExternalCertificateStartupParameters : MTRDeviceControllerStartupParameters
+@interface MTRDeviceControllerExternalCertificateParameters : MTRDeviceControllerParameters
 
 - (instancetype)init NS_UNAVAILABLE;
 + (instancetype)new NS_UNAVAILABLE;
diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParameters_Wrapper.h b/src/darwin/Framework/CHIP/MTRDeviceControllerParameters_Wrapper.h
similarity index 86%
rename from src/darwin/Framework/CHIP/MTRDeviceControllerStartupParameters_Wrapper.h
rename to src/darwin/Framework/CHIP/MTRDeviceControllerParameters_Wrapper.h
index 537958d..4f26e1a 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParameters_Wrapper.h
+++ b/src/darwin/Framework/CHIP/MTRDeviceControllerParameters_Wrapper.h
@@ -17,9 +17,9 @@
 #include <Matter/MTRDefines.h>
 
 #if MTR_PER_CONTROLLER_STORAGE_ENABLED
-#error Should be including Matter/MTRDeviceControllerStartupParameters.h
+#error Should be including Matter/MTRDeviceControllerParameters.h
 #endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
 
 #define MTR_INTERNAL_INCLUDE
-#import <Matter/MTRDeviceControllerStartupParameters.h>
+#import <Matter/MTRDeviceControllerParameters.h>
 #undef MTR_INTERNAL_INCLUDE
diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm
index 3da8a90..0c14065 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm
+++ b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm
@@ -144,15 +144,15 @@
     return self;
 }
 
-- (instancetype)initWithParameters:(MTRDeviceControllerStartupParameters *)params error:(CHIP_ERROR &)error
+- (instancetype)initWithParameters:(MTRDeviceControllerParameters *)params error:(CHIP_ERROR &)error
 {
     if (!(self = [super init])) {
         error = CHIP_ERROR_INCORRECT_STATE;
         return nil;
     }
 
-    if (![params isKindOfClass:[MTRDeviceControllerExternalCertificateStartupParameters class]]) {
-        MTR_LOG_ERROR("Unexpected subclass of MTRDeviceControllerStartupParameters");
+    if (![params isKindOfClass:[MTRDeviceControllerExternalCertificateParameters class]]) {
+        MTR_LOG_ERROR("Unexpected subclass of MTRDeviceControllerParameters");
         error = CHIP_ERROR_INVALID_ARGUMENT;
         return nil;
     }
@@ -251,7 +251,7 @@
 
 @end
 
-@implementation MTRDeviceControllerStartupParameters
+@implementation MTRDeviceControllerParameters
 - (instancetype)initWithStorageDelegate:(id<MTRDeviceControllerStorageDelegate>)storageDelegate
                    storageDelegateQueue:(dispatch_queue_t)storageDelegateQueue
                        uniqueIdentifier:(NSUUID *)uniqueIdentifier
@@ -301,7 +301,7 @@
 
 @end
 
-@implementation MTRDeviceControllerExternalCertificateStartupParameters
+@implementation MTRDeviceControllerExternalCertificateParameters
 - (instancetype)initWithStorageDelegate:(id<MTRDeviceControllerStorageDelegate>)storageDelegate
                    storageDelegateQueue:(dispatch_queue_t)storageDelegateQueue
                        uniqueIdentifier:(NSUUID *)uniqueIdentifier
@@ -542,7 +542,7 @@
                          fabricTable:(chip::FabricTable *)fabricTable
                             keystore:(chip::Crypto::OperationalKeystore *)keystore
                 advertiseOperational:(BOOL)advertiseOperational
-                              params:(MTRDeviceControllerStartupParameters *)params
+                              params:(MTRDeviceControllerParameters *)params
                                error:(CHIP_ERROR &)error
 {
     if (!(self = [super initWithParameters:params error:error])) {
diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams_Internal.h b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams_Internal.h
index 9d52067..2850fc7 100644
--- a/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams_Internal.h
+++ b/src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams_Internal.h
@@ -21,9 +21,9 @@
 #import <Matter/MTRDefines.h>
 #import <Matter/MTRDeviceController.h>
 #if MTR_PER_CONTROLLER_STORAGE_ENABLED
-#import <Matter/MTRDeviceControllerStartupParameters.h>
+#import <Matter/MTRDeviceControllerParameters.h>
 #else
-#import "MTRDeviceControllerStartupParameters_Wrapper.h"
+#import "MTRDeviceControllerParameters_Wrapper.h"
 #endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
 
 #include <crypto/CHIPCryptoPAL.h>
@@ -52,7 +52,7 @@
 - (instancetype)initWithParams:(MTRDeviceControllerStartupParams *)params;
 @end
 
-@interface MTRDeviceControllerStartupParameters ()
+@interface MTRDeviceControllerParameters ()
 
 - (instancetype)initWithStorageDelegate:(id<MTRDeviceControllerStorageDelegate>)storageDelegate
                    storageDelegateQueue:(dispatch_queue_t)storageDelegateQueue
@@ -64,7 +64,7 @@
                 intermediateCertificate:(MTRCertificateDERBytes _Nullable)intermediateCertificate
                         rootCertificate:(MTRCertificateDERBytes)rootCertificate;
 
-// When we have other subclasses of MTRDeviceControllerStartupParameters, we may
+// When we have other subclasses of MTRDeviceControllerParameters, we may
 // need to make more things nullable here and/or add more fields.  But for now
 // we know exactly what information we have.
 @property (nonatomic, copy, readonly) NSData * ipk;
@@ -157,7 +157,7 @@
                          fabricTable:(chip::FabricTable *)fabricTable
                             keystore:(chip::Crypto::OperationalKeystore *)keystore
                 advertiseOperational:(BOOL)advertiseOperational
-                              params:(MTRDeviceControllerStartupParameters *)params
+                              params:(MTRDeviceControllerParameters *)params
                                error:(CHIP_ERROR &)error;
 
 /**
diff --git a/src/darwin/Framework/CHIP/Matter.h b/src/darwin/Framework/CHIP/Matter.h
index 63c067f..2cf6242 100644
--- a/src/darwin/Framework/CHIP/Matter.h
+++ b/src/darwin/Framework/CHIP/Matter.h
@@ -42,7 +42,7 @@
 #import <Matter/MTRDeviceController.h>
 #import <Matter/MTRDeviceControllerDelegate.h>
 #import <Matter/MTRDeviceControllerFactory.h>
-#import <Matter/MTRDeviceControllerStartupParameters.h>
+#import <Matter/MTRDeviceControllerParameters.h>
 #import <Matter/MTRDeviceControllerStartupParams.h>
 #import <Matter/MTRDeviceControllerStorageDelegate.h>
 #import <Matter/MTRError.h>
diff --git a/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m b/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m
index 549d66e..b7fa9a1 100644
--- a/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m
+++ b/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m
@@ -133,8 +133,6 @@
     [self setContinueAfterFailure:NO];
 
     _storageQueue = dispatch_queue_create("test.storage.queue", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
-
-    [self startFactory];
 }
 
 - (void)tearDown
@@ -145,22 +143,6 @@
     [super tearDown];
 }
 
-- (void)startFactory
-{
-    __auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
-    XCTAssertNotNil(factory);
-
-    __auto_type * factoryParams = [[MTRDeviceControllerFactoryParams alloc] init];
-    factoryParams.shouldStartServer = YES;
-
-    NSError * error;
-    BOOL ok = [factory startControllerFactory:factoryParams error:&error];
-    XCTAssertNil(error);
-    XCTAssertTrue(ok);
-
-    XCTAssertTrue(factory.isRunning);
-}
-
 - (void)stopFactory
 {
     __auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
@@ -180,9 +162,6 @@
 {
     XCTAssertTrue(error != NULL);
 
-    __auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
-    XCTAssertNotNil(factory);
-
     // Specify a fixed issuerID, so we get the same cert if we use the same keys.
     __auto_type * root = [MTRCertificates createRootCertificate:rootKeys issuerID:@(1) fabricID:nil error:error];
     XCTAssertNil(*error);
@@ -198,21 +177,20 @@
     XCTAssertNil(*error);
     XCTAssertNotNil(operational);
 
-    __auto_type * params =
-        [[MTRDeviceControllerExternalCertificateStartupParameters alloc] initWithStorageDelegate:storage
-                                                                            storageDelegateQueue:_storageQueue
-                                                                                uniqueIdentifier:storage.controllerID
-                                                                                             ipk:rootKeys.ipk
-                                                                                        vendorID:@(kTestVendorId)
-                                                                              operationalKeypair:operationalKeys
-                                                                          operationalCertificate:operational
-                                                                         intermediateCertificate:nil
-                                                                                 rootCertificate:root];
+    __auto_type * params = [[MTRDeviceControllerExternalCertificateParameters alloc] initWithStorageDelegate:storage
+                                                                                        storageDelegateQueue:_storageQueue
+                                                                                            uniqueIdentifier:storage.controllerID
+                                                                                                         ipk:rootKeys.ipk
+                                                                                                    vendorID:@(kTestVendorId)
+                                                                                          operationalKeypair:operationalKeys
+                                                                                      operationalCertificate:operational
+                                                                                     intermediateCertificate:nil
+                                                                                             rootCertificate:root];
     XCTAssertNotNil(params);
 
     params.shouldAdvertiseOperational = advertiseOperational;
 
-    return [factory createController:params error:error];
+    return [[MTRDeviceController alloc] initWithParameters:params error:error];
 }
 
 - (void)test001_CheckAdvertisingAsExpected
diff --git a/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m b/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m
index f81cc23..8bbb529 100644
--- a/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m
+++ b/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m
@@ -30,7 +30,6 @@
 static const uint16_t kPairingTimeoutInSeconds = 10;
 static const uint16_t kTimeoutInSeconds = 3;
 static NSString * kOnboardingPayload = @"MT:-24J0AFN00KA0648G00";
-static const uint16_t kLocalPort = 5541;
 static const uint16_t kTestVendorId = 0xFFF1u;
 
 @interface MTRPerControllerStorageTestsControllerDelegate : NSObject <MTRDeviceControllerDelegate>
@@ -194,8 +193,6 @@
     [self setContinueAfterFailure:NO];
 
     _storageQueue = dispatch_queue_create("test.storage.queue", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL);
-
-    [self startFactory];
 }
 
 - (void)tearDown
@@ -206,20 +203,6 @@
     [super tearDown];
 }
 
-- (void)startFactory
-{
-    __auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
-    XCTAssertNotNil(factory);
-
-    __auto_type * factoryParams = [[MTRDeviceControllerFactoryParams alloc] init];
-    factoryParams.port = @(kLocalPort);
-
-    NSError * error;
-    BOOL ok = [factory startControllerFactory:factoryParams error:&error];
-    XCTAssertNil(error);
-    XCTAssertTrue(ok);
-}
-
 - (void)stopFactory
 {
     __auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
@@ -262,9 +245,6 @@
 {
     XCTAssertTrue(error != NULL);
 
-    __auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
-    XCTAssertNotNil(factory);
-
     // Specify a fixed issuerID, so we get the same cert if we use the same keys.
     __auto_type * root = [MTRCertificates createRootCertificate:rootKeys issuerID:@(1) fabricID:nil error:error];
     XCTAssertNil(*error);
@@ -280,16 +260,15 @@
     XCTAssertNil(*error);
     XCTAssertNotNil(operational);
 
-    __auto_type * params =
-        [[MTRDeviceControllerExternalCertificateStartupParameters alloc] initWithStorageDelegate:storage
-                                                                            storageDelegateQueue:_storageQueue
-                                                                                uniqueIdentifier:storage.controllerID
-                                                                                             ipk:rootKeys.ipk
-                                                                                        vendorID:@(kTestVendorId)
-                                                                              operationalKeypair:operationalKeys
-                                                                          operationalCertificate:operational
-                                                                         intermediateCertificate:nil
-                                                                                 rootCertificate:root];
+    __auto_type * params = [[MTRDeviceControllerExternalCertificateParameters alloc] initWithStorageDelegate:storage
+                                                                                        storageDelegateQueue:_storageQueue
+                                                                                            uniqueIdentifier:storage.controllerID
+                                                                                                         ipk:rootKeys.ipk
+                                                                                                    vendorID:@(kTestVendorId)
+                                                                                          operationalKeypair:operationalKeys
+                                                                                      operationalCertificate:operational
+                                                                                     intermediateCertificate:nil
+                                                                                             rootCertificate:root];
     XCTAssertNotNil(params);
 
     __auto_type * ourCertificateIssuer = [[MTRPerControllerStorageTestsCertificateIssuer alloc] initWithRootCertificate:root
@@ -304,7 +283,7 @@
 
     [params setOperationalCertificateIssuer:ourCertificateIssuer queue:dispatch_get_main_queue()];
 
-    return [factory createController:params error:error];
+    return [[MTRDeviceController alloc] initWithParameters:params error:error];
 }
 
 - (nullable MTRDeviceController *)startControllerWithRootKeys:(MTRTestKeys *)rootKeys
diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj
index a95c790..fc6fcc5 100644
--- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj
+++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj
@@ -159,7 +159,7 @@
 		51565CB12A7AD77600469F18 /* MTRDeviceControllerDataStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 51565CAF2A7AD77600469F18 /* MTRDeviceControllerDataStore.h */; };
 		51565CB22A7AD77600469F18 /* MTRDeviceControllerDataStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51565CB02A7AD77600469F18 /* MTRDeviceControllerDataStore.mm */; };
 		51565CB42A7AD78D00469F18 /* MTRDeviceControllerStorageDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 51565CB32A7AD78D00469F18 /* MTRDeviceControllerStorageDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		51565CB62A7B0D6600469F18 /* MTRDeviceControllerStartupParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 51565CB52A7B0D6600469F18 /* MTRDeviceControllerStartupParameters.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		51565CB62A7B0D6600469F18 /* MTRDeviceControllerParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 51565CB52A7B0D6600469F18 /* MTRDeviceControllerParameters.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		515C1C6F284F9FFB00A48F0C /* MTRFramework.mm in Sources */ = {isa = PBXBuildFile; fileRef = 515C1C6D284F9FFB00A48F0C /* MTRFramework.mm */; };
 		515C1C70284F9FFB00A48F0C /* MTRFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = 515C1C6E284F9FFB00A48F0C /* MTRFramework.h */; };
 		51669AF02913204400F4AA36 /* MTRBackwardsCompatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 51669AEF2913204400F4AA36 /* MTRBackwardsCompatTests.m */; };
@@ -474,7 +474,7 @@
 		51565CAF2A7AD77600469F18 /* MTRDeviceControllerDataStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRDeviceControllerDataStore.h; sourceTree = "<group>"; };
 		51565CB02A7AD77600469F18 /* MTRDeviceControllerDataStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRDeviceControllerDataStore.mm; sourceTree = "<group>"; };
 		51565CB32A7AD78D00469F18 /* MTRDeviceControllerStorageDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRDeviceControllerStorageDelegate.h; sourceTree = "<group>"; };
-		51565CB52A7B0D6600469F18 /* MTRDeviceControllerStartupParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRDeviceControllerStartupParameters.h; sourceTree = "<group>"; };
+		51565CB52A7B0D6600469F18 /* MTRDeviceControllerParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRDeviceControllerParameters.h; sourceTree = "<group>"; };
 		515C1C6D284F9FFB00A48F0C /* MTRFramework.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRFramework.mm; sourceTree = "<group>"; };
 		515C1C6E284F9FFB00A48F0C /* MTRFramework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRFramework.h; sourceTree = "<group>"; };
 		51669AEF2913204400F4AA36 /* MTRBackwardsCompatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTRBackwardsCompatTests.m; sourceTree = "<group>"; };
@@ -1083,7 +1083,7 @@
 				51E51FBC282AD37A00FC978D /* MTRDeviceControllerStartupParams.h */,
 				51E51FBD282AD37A00FC978D /* MTRDeviceControllerStartupParams_Internal.h */,
 				51E51FBE282AD37A00FC978D /* MTRDeviceControllerStartupParams.mm */,
-				51565CB52A7B0D6600469F18 /* MTRDeviceControllerStartupParameters.h */,
+				51565CB52A7B0D6600469F18 /* MTRDeviceControllerParameters.h */,
 				51565CB32A7AD78D00469F18 /* MTRDeviceControllerStorageDelegate.h */,
 				5A6FEC9427B5976200F25F42 /* MTRDeviceControllerXPCConnection.h */,
 				5A6FEC9527B5983000F25F42 /* MTRDeviceControllerXPCConnection.mm */,
@@ -1233,7 +1233,7 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				51565CB62A7B0D6600469F18 /* MTRDeviceControllerStartupParameters.h in Headers */,
+				51565CB62A7B0D6600469F18 /* MTRDeviceControllerParameters.h in Headers */,
 				51565CB42A7AD78D00469F18 /* MTRDeviceControllerStorageDelegate.h in Headers */,
 				510A07492A685D3900A9241C /* Matter.apinotes in Headers */,
 				51EF279F2A2A3EB100E33F75 /* MTRBackwardsCompatShims.h in Headers */,