Call PlatformMgr::InitChipStack from the device controller (#1500)

diff --git a/config/standalone/standalone-chip.mk b/config/standalone/standalone-chip.mk
index 17daab7..0677c9e 100644
--- a/config/standalone/standalone-chip.mk
+++ b/config/standalone/standalone-chip.mk
@@ -138,6 +138,7 @@
     -lDeviceLayer \
     -lInetLayer \
     -lnlfaultinjection \
+    -lSupportLayer \
     -lSystemLayer
 
 STD_LIBS += $(shell pkg-config --libs openssl)
@@ -158,6 +159,7 @@
     $(CHIP_OUTPUT_DIR)/lib/libDeviceLayer.a \
     $(CHIP_OUTPUT_DIR)/lib/libInetLayer.a \
     $(CHIP_OUTPUT_DIR)/lib/libnlfaultinjection.a \
+    $(CHIP_OUTPUT_DIR)/lib/libSupportLayer.a \
     $(CHIP_OUTPUT_DIR)/lib/libSystemLayer.a
 
 
diff --git a/configure.ac b/configure.ac
index c2f3c01..ea1417b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2476,6 +2476,7 @@
   PThreads link libraries                          : ${PTHREAD_LIBS:--}
   IniPP compile flags                              : ${INIPP_CPPFLAGS:--}
   GIO compile flags                                : ${GIO_CFLAGS:--}
+  GIO link flags                                   : ${GIO_LIBS:--}
   C Preprocessor                                   : ${CPP}
   C Compiler                                       : ${CC}
   C++ Preprocessor                                 : ${CXXCPP}
diff --git a/examples/chip-tool/main.cpp b/examples/chip-tool/main.cpp
index 0453d4b..cdeea11 100644
--- a/examples/chip-tool/main.cpp
+++ b/examples/chip-tool/main.cpp
@@ -257,8 +257,6 @@
         controller->SendMessage(NULL, buffer);
         printf("Msg sent to server at %s:%d\n", host_ip_str, port);
 
-        controller->ServiceEvents();
-
         sleep(SEND_DELAY);
     }
 }
@@ -301,7 +299,6 @@
 #endif
 
     controller->SendMessage(NULL, buffer);
-    controller->ServiceEvents();
 }
 
 // ================================================================================
@@ -325,6 +322,9 @@
     err               = controller->Init(kLocalDeviceId);
     VerifyOrExit(err == CHIP_NO_ERROR, fprintf(stderr, "Failed to initialize the device controller"));
 
+    err = controller->ServiceEvents();
+    SuccessOrExit(err);
+
     err = controller->ConnectDevice(kRemoteDeviceId, host_addr, NULL, EchoKeyExchange, EchoResponse, ReceiveError, port);
     VerifyOrExit(err == CHIP_NO_ERROR, fprintf(stderr, "Failed to connect to the device"));
 
@@ -335,6 +335,7 @@
     else
     {
         DoOnOff(controller, command, commandArgs.endpointId);
+        controller->ServiceEventSignal();
     }
 
 exit:
diff --git a/src/ble/BUILD.gn b/src/ble/BUILD.gn
index 9a716f5..5df3596 100644
--- a/src/ble/BUILD.gn
+++ b/src/ble/BUILD.gn
@@ -14,14 +14,12 @@
 
 import("//build_overrides/chip.gni")
 
+import("${chip_root}/src/platform/device.gni")
 import("ble.gni")
 
 declare_args() {
   # Extra header to include in BleConfig.h for project.
   ble_project_config_include = ""
-
-  # Extra header to include in BleConfig.h for platform.
-  ble_platform_config_include = ""
 }
 
 config("ble_config") {
diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp
index 5458c77..503de71 100644
--- a/src/controller/CHIPDeviceController.cpp
+++ b/src/controller/CHIPDeviceController.cpp
@@ -33,6 +33,8 @@
 
 #include <core/CHIPCore.h>
 #include <core/CHIPEncoding.h>
+#include <platform/PlatformManager.h>
+#include <platform/internal/CHIPDeviceLayerInternal.h>
 #include <support/Base64.h>
 #include <support/CodeUtils.h>
 #include <support/ErrorStr.h>
@@ -70,23 +72,7 @@
 
     VerifyOrExit(mState == kState_NotInitialized, err = CHIP_ERROR_INCORRECT_STATE);
 
-    mSystemLayer = new System::Layer();
-    mInetLayer   = new Inet::InetLayer();
-
-    // Initialize the CHIP System Layer.
-    err = mSystemLayer->Init(NULL);
-    if (err != CHIP_SYSTEM_NO_ERROR)
-    {
-        ChipLogError(Controller, "SystemLayer initialization failed: %s", ErrorStr(err));
-    }
-    SuccessOrExit(err);
-
-    // Initialize the CHIP Inet layer.
-    err = mInetLayer->Init(*mSystemLayer, NULL);
-    if (err != INET_NO_ERROR)
-    {
-        ChipLogError(Controller, "InetLayer initialization failed: %s", ErrorStr(err));
-    }
+    err = DeviceLayer::PlatformMgr().InitChipStack();
     SuccessOrExit(err);
 
     mState         = kState_Initialized;
@@ -98,25 +84,20 @@
 
 CHIP_ERROR ChipDeviceController::Shutdown()
 {
-    if (mState != kState_Initialized)
-    {
-        return CHIP_ERROR_INCORRECT_STATE;
-    }
-
     CHIP_ERROR err = CHIP_NO_ERROR;
-    mState         = kState_NotInitialized;
+
+    VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE);
+
+    mState = kState_NotInitialized;
+
+    err = DeviceLayer::PlatformMgr().Shutdown();
+    SuccessOrExit(err);
 
     if (mSessionManager != NULL)
     {
         delete mSessionManager;
         mSessionManager = NULL;
     }
-    mSystemLayer->Shutdown();
-    mInetLayer->Shutdown();
-    delete mSystemLayer;
-    delete mInetLayer;
-    mSystemLayer = NULL;
-    mInetLayer   = NULL;
 
     mConState = kConnectionState_NotConnected;
     memset(&mOnComplete, 0, sizeof(mOnComplete));
@@ -125,6 +106,7 @@
     mMessageNumber   = 0;
     mRemoteDeviceId.ClearValue();
 
+exit:
     return err;
 }
 
@@ -147,8 +129,8 @@
 
     mSessionManager = new SecureSessionMgr<Transport::UDP>();
 
-    err = mSessionManager->Init(mLocalDeviceId, mSystemLayer,
-                                Transport::UdpListenParameters(mInetLayer).SetAddressType(deviceAddr.Type()));
+    err = mSessionManager->Init(mLocalDeviceId, &DeviceLayer::SystemLayer,
+                                Transport::UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(deviceAddr.Type()));
     SuccessOrExit(err);
 
     mSessionManager->SetDelegate(this);
@@ -252,87 +234,33 @@
     return err;
 }
 
-CHIP_ERROR ChipDeviceController::GetLayers(Layer ** systemLayer, InetLayer ** inetLayer)
+CHIP_ERROR ChipDeviceController::ServiceEvents()
 {
-    if (mState != kState_Initialized)
-    {
-        return CHIP_ERROR_INCORRECT_STATE;
-    }
-    if (systemLayer != NULL)
-    {
-        *systemLayer = mSystemLayer;
-    }
-    if (inetLayer != NULL)
-    {
-        *inetLayer = mInetLayer;
-    }
+    CHIP_ERROR err = CHIP_NO_ERROR;
 
-    return CHIP_NO_ERROR;
+    VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE);
+
+    err = DeviceLayer::PlatformMgr().StartEventLoopTask();
+    SuccessOrExit(err);
+
+exit:
+    return err;
 }
 
-void ChipDeviceController::ServiceEvents()
+CHIP_ERROR ChipDeviceController::ServiceEventSignal()
 {
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    VerifyOrExit(mState == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE);
+
 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
-    if (mState != kState_Initialized)
-    {
-        return;
-    }
-
-    // Set the select timeout to 100ms
-    struct timeval aSleepTime;
-    aSleepTime.tv_sec  = 0;
-    aSleepTime.tv_usec = 100 * 1000;
-
-#if !__ZEPHYR__
-    static bool printed = false;
-
-    if (!printed)
-    {
-        {
-            ChipLogProgress(Controller, "CHIP node ready to service events; PID: %d; PPID: %d\n", getpid(), getppid());
-            printed = true;
-        }
-    }
-#endif // !__ZEPHYR__
-    fd_set readFDs, writeFDs, exceptFDs;
-    int numFDs = 0;
-
-    FD_ZERO(&readFDs);
-    FD_ZERO(&writeFDs);
-    FD_ZERO(&exceptFDs);
-
-    if (mSystemLayer->State() == System::kLayerState_Initialized)
-    {
-        mSystemLayer->PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, aSleepTime);
-    }
-
-#if CHIP_SYSTEM_CONFIG_USE_SOCKETS
-    if (mInetLayer->State == Inet::InetLayer::kState_Initialized)
-    {
-        mInetLayer->PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, aSleepTime);
-    }
-#endif
-
-    int selectRes = select(numFDs, &readFDs, &writeFDs, &exceptFDs, &aSleepTime);
-    if (selectRes < 0)
-    {
-        ChipLogError(Controller, "select failed: %s\n", ErrorStr(System::MapErrorPOSIX(errno)));
-        return;
-    }
-
-    if (mSystemLayer->State() == System::kLayerState_Initialized)
-    {
-        mSystemLayer->HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
-    }
-
-#if CHIP_SYSTEM_CONFIG_USE_SOCKETS
-    if (mInetLayer->State == Inet::InetLayer::kState_Initialized)
-    {
-        mInetLayer->HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
-    }
-#endif
-
+    DeviceLayer::SystemLayer.WakeSelect();
+#else
+    err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
+
+exit:
+    return err;
 }
 
 void ChipDeviceController::ClearRequestState()
diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h
index 55e8c03..2940261 100644
--- a/src/controller/CHIPDeviceController.h
+++ b/src/controller/CHIPDeviceController.h
@@ -142,21 +142,18 @@
     // ----- IO -----
     /**
      * @brief
-     *   Allow the CHIP Stack to process any pending events
-     *   This can be called in an event handler loop to tigger callbacks within the CHIP stack
-     *   Note - Some platforms might need to implement their own event handler
+     * Start the event loop task within the CHIP stack
+     * @return CHIP_ERROR   The return status
      */
-    void ServiceEvents();
+    CHIP_ERROR ServiceEvents();
 
     /**
      * @brief
-     *   Get pointers to the Layers ownerd by the controller
-     *
-     * @param[out] systemLayer   A pointer to the SystemLayer object
-     * @param[out] inetLayer     A pointer to the InetLayer object
-     * @return CHIP_ERROR   Indicates whether the layers were populated correctly
+     *   Allow the CHIP Stack to process any pending events
+     *   This can be called in an event handler loop to tigger callbacks within the CHIP stack
+     * @return CHIP_ERROR   The return status
      */
-    CHIP_ERROR GetLayers(Layer ** systemLayer, InetLayer ** inetLayer);
+    CHIP_ERROR ServiceEventSignal();
 
     virtual void OnMessageReceived(const MessageHeader & header, Transport::PeerConnectionState * state,
                                    System::PacketBuffer * msgBuf, SecureSessionMgrBase * mgr);
@@ -177,9 +174,6 @@
         kConnectionState_SecureConnected = 2,
     };
 
-    System::Layer * mSystemLayer;
-    Inet::InetLayer * mInetLayer;
-
     SecureSessionMgr<Transport::UDP> * mSessionManager;
 
     ConnectionState mConState;
diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm
index 339b471..924ac7d 100644
--- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm
+++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm
@@ -204,8 +204,9 @@
     }
 
     // Start the IO pump
-    [self _serviceEvents];
-
+    dispatch_async(_chipSelectQueue, ^() {
+        self.cppController->ServiceEvents();
+    });
     return YES;
 }
 
@@ -331,31 +332,6 @@
     return isConnected ? YES : NO;
 }
 
-// TODO kill this with fire (NW might implicitly replace this?)
-- (void)_serviceEvents
-{
-    __weak typeof(self) weakSelf = self;
-    dispatch_async(self.chipSelectQueue, ^() {
-        typeof(self) strongSelf = weakSelf;
-        if (!strongSelf) {
-            return;
-        }
-
-        [self.lock lock];
-
-        if (!self.cppController->IsConnected()) {
-            [self.lock unlock];
-            // cancel the loop, it'll restart the next time a connection is established
-            return;
-        }
-
-        self.cppController->ServiceEvents();
-        [self.lock unlock];
-
-        [self _serviceEvents];
-    });
-}
-
 - (void)registerCallbacks:appCallbackQueue onMessage:(ControllerOnMessageBlock)onMessage onError:(ControllerOnErrorBlock)onError
 {
     self.appCallbackQueue = appCallbackQueue;
diff --git a/src/inet/BUILD.gn b/src/inet/BUILD.gn
index ba7e4ac..88a5465 100644
--- a/src/inet/BUILD.gn
+++ b/src/inet/BUILD.gn
@@ -17,15 +17,13 @@
 import("//build_overrides/nlfaultinjection.gni")
 import("//build_overrides/nlio.gni")
 
+import("${chip_root}/src/platform/device.gni")
 import("${chip_root}/gn/chip/tests.gni")
 import("inet.gni")
 
 declare_args() {
   # Extra header to include in SystemConfig.h for project.
   inet_project_config_include = ""
-
-  # Extra header to include in SystemConfig.h for platform.
-  inet_platform_config_include = ""
 }
 
 config("inet_config") {
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index eed6946..7e45929 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -70,6 +70,12 @@
     $(SOCKETS_CPPFLAGS)                                       \
     $(NULL)
 
+if CHIP_DEVICE_LAYER_TARGET_LINUX
+libCHIP_a_CPPFLAGS                                         += \
+    $(GIO_CFLAGS)                                             \
+    $(NULL)
+endif
+
 libCHIP_a_SOURCES                   = $(CHIP_BUILD_SYSTEM_LAYER_SOURCE_FILES)
 libCHIP_a_SOURCES                  += $(CHIP_BUILD_INET_LAYER_SOURCE_FILES)
 libCHIP_a_SOURCES                  += $(CHIP_BUILD_CORE_LAYER_SOURCE_FILES)
diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn
index cca15ad..42ccc30 100644
--- a/src/platform/BUILD.gn
+++ b/src/platform/BUILD.gn
@@ -21,9 +21,6 @@
   declare_args() {
     # Extra header to include in CHIPDeviceConfig.h for project.
     chip_device_project_config_include = ""
-
-    # Extra header to include in CHIPDeviceConfig.h for platform.
-    chip_device_platform_config_include = ""
   }
 
   config("platform_config") {
@@ -104,6 +101,7 @@
 
     public_deps = [
       "${chip_root}/src/ble",
+      "${chip_root}/src/inet",
       "${chip_root}/src/lib/core:chip_config_header",
       "${chip_root}/src/lib/support",
       "${nlio_root}:nlio",
diff --git a/src/platform/Linux/args.gni b/src/platform/Linux/args.gni
index 0cbe8df..27a4670 100644
--- a/src/platform/Linux/args.gni
+++ b/src/platform/Linux/args.gni
@@ -13,9 +13,3 @@
 # limitations under the License.
 
 device_platform = "linux"
-
-ble_platform_config_include = "<platform/Linux/BlePlatformConfig.h>"
-chip_device_platform_config_include = "<platform/Linux/CHIPDevicePlatformConfig.h>"
-chip_platform_config_include = "<platform/Linux/CHIPPlatformConfig.h>"
-inet_platform_config_include = "<platform/Linux/InetPlatformConfig.h>"
-system_platform_config_include = "<platform/Linux/SystemPlatformConfig.h>"
diff --git a/src/platform/device.gni b/src/platform/device.gni
index d4b4652..2bdf268 100644
--- a/src/platform/device.gni
+++ b/src/platform/device.gni
@@ -12,20 +12,37 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("//build_overrides/chip.gni")
+
 declare_args() {
   # Device platform layer: freertos, nrf5, none.
-  device_platform = ""
+  device_platform = "auto"
 
   # Enable openthread support.
   chip_enable_openthread = false
 }
 
-if (device_platform == "") {
-  if (current_os != "freertos") {
+if (device_platform == "auto") {
+  if (current_os == "linux") {
+    device_platform = "linux"
+  } else {
     device_platform = "none"
   }
 }
 
+device_layer = "none"
+if (device_platform == "linux") {
+  device_layer = "Linux"
+} else if (device_platform == "nrf5") {
+  device_layer = "nRF5"
+}
+
+ble_platform_config_include = "<platform/" + device_layer + "/BlePlatformConfig.h>"
+chip_device_platform_config_include = "<platform/" + device_layer + "/CHIPDevicePlatformConfig.h>"
+chip_platform_config_include = "<platform/" + device_layer + "/CHIPPlatformConfig.h>"
+inet_platform_config_include = "<platform/" + device_layer + "/InetPlatformConfig.h>"
+system_platform_config_include = "<platform/" + device_layer + "/SystemPlatformConfig.h>"
+
 assert((current_os != "freertos" && device_platform == "none") ||
            device_platform == "nrf5" || device_platform == "linux",
        "Please select a valid value for device_platform")
diff --git a/src/platform/nRF5/args.gni b/src/platform/nRF5/args.gni
index bde932e..39af51d 100644
--- a/src/platform/nRF5/args.gni
+++ b/src/platform/nRF5/args.gni
@@ -23,10 +23,3 @@
 inet_config_enable_dns_resolver = false
 
 chip_build_tests = false
-
-ble_platform_config_include = "<platform/nRF5/BlePlatformConfig.h>"
-chip_device_platform_config_include =
-    "<platform/nRF5/CHIPDevicePlatformConfig.h>"
-chip_platform_config_include = "<platform/nRF5/CHIPPlatformConfig.h>"
-inet_platform_config_include = "<platform/nRF5/InetPlatformConfig.h>"
-system_platform_config_include = "<platform/nRF5/SystemPlatformConfig.h>"
diff --git a/src/system/BUILD.gn b/src/system/BUILD.gn
index 68fdbb0..a47b4a3 100644
--- a/src/system/BUILD.gn
+++ b/src/system/BUILD.gn
@@ -16,6 +16,7 @@
 import("//build_overrides/nlassert.gni")
 import("//build_overrides/nlfaultinjection.gni")
 
+import("${chip_root}/src/platform/device.gni")
 import("${chip_root}/gn/chip/tests.gni")
 import("system.gni")
 
@@ -24,16 +25,9 @@
   # TODO - This should probably be in src/core but src/system also uses it.
   chip_project_config_include = "<CHIPProjectConfig.h>"
 
-  # Extra header to include in CHIPConfig.h for platform.
-  # TODO - This should probably be in src/core but src/system also uses it.
-  chip_platform_config_include = ""
-
   # Extra header to include in SystemConfig.h for project.
   system_project_config_include = "<SystemProjectConfig.h>"
 
-  # Extra header to include in SystemConfig.h for platform.
-  system_platform_config_include = ""
-
   # Extra include dirs for project configs.
   project_config_include_dirs = []
 }