[Telink] Implement OnSubscriptionRequested callback for SED examples (#26650)

* [Telink] Add OnSubscriptionRequested callback

* [Telink] Enable CHIP_ICD_SUBSCRIPTION_HANDLING for all SED devices

* [Telink] Move build ICDUtil into libCHIP & CHIP_ICD_SUBSCRIPTION_HANDLING default if PM

* Restyled by gn

* [Telink] Move ICDUtil.h include into cpp file

* Restyled by clang-format

* [Telink] Move ICDUtil.* to src/platform/telink

---------

Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/config/telink/chip-module/Kconfig b/config/telink/chip-module/Kconfig
index bce2583..4d4fb20 100644
--- a/config/telink/chip-module/Kconfig
+++ b/config/telink/chip-module/Kconfig
@@ -179,3 +179,23 @@
 config SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE
 	int
 	default 255 if SHELL_BACKEND_SERIAL
+
+config CHIP_ICD_SUBSCRIPTION_HANDLING
+	bool "Enables platform specific handling of ICD subscriptions"
+	default PM
+	help
+	  Enables platform specific implementation that handles ICD subscription requests
+	  and selects subscription report interval value considering maximum interval preferred
+	  by the publisher.
+
+config CHIP_MAX_PREFERRED_SUBSCRIPTION_REPORT_INTERVAL
+	int "Maximum preferred interval of sending subscription reports (s)"
+	default 60
+	help
+	  Provides maximum preferred interval to be used by a publisher for negotiation
+	  of the final maximum subscription report interval, after receiving a subscription
+	  request from the initiator. This value should be selected as a compromise between
+	  keeping the power consumption low due to not sending reports too often, and allowing
+	  the initiator device to detect the publisher absence reasonably fast due to not sending
+	  the reports too rarely. The current algorithm is to select bigger value from the one
+	  requested by the initiator and the one preferred by the publisher.
diff --git a/examples/platform/telink/common/src/AppTaskCommon.cpp b/examples/platform/telink/common/src/AppTaskCommon.cpp
index c6e455b..c49222d 100644
--- a/examples/platform/telink/common/src/AppTaskCommon.cpp
+++ b/examples/platform/telink/common/src/AppTaskCommon.cpp
@@ -33,6 +33,11 @@
 #include "OTAUtil.h"
 #endif
 
+#ifdef CONFIG_CHIP_ICD_SUBSCRIPTION_HANDLING
+#include "ICDUtil.h"
+#include <app/InteractionModelEngine.h>
+#endif
+
 LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
 
 namespace {
@@ -229,6 +234,10 @@
     emberAfEndpointEnableDisable(kNetworkCommissioningEndpointSecondary, false);
 #endif
 
+#ifdef CONFIG_CHIP_ICD_SUBSCRIPTION_HANDLING
+    chip::app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&GetICDUtil());
+#endif
+
     // Add CHIP event handler and start CHIP thread.
     // Note that all the initialization code should happen prior to this point to avoid data races
     // between the main and the CHIP threads.
diff --git a/src/platform/telink/BUILD.gn b/src/platform/telink/BUILD.gn
index 0970bb6..00fe34e 100644
--- a/src/platform/telink/BUILD.gn
+++ b/src/platform/telink/BUILD.gn
@@ -43,6 +43,7 @@
     "ConfigurationManagerImpl.h",
     "ConnectivityManagerImpl.cpp",
     "ConnectivityManagerImpl.h",
+    "ICDUtil.cpp",
     "InetPlatformConfig.h",
     "KeyValueStoreManagerImpl.h",
     "PlatformManagerImpl.h",
@@ -57,6 +58,8 @@
 
   public_deps = [ "${chip_root}/src/platform:platform_base" ]
 
+  defines = [ "CHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER=<lib/address_resolve/AddressResolve_DefaultImpl.h>" ]
+
   if (chip_enable_factory_data) {
     sources += [
       "FactoryDataParser.c",
diff --git a/src/platform/telink/ICDUtil.cpp b/src/platform/telink/ICDUtil.cpp
new file mode 100644
index 0000000..fd2130c
--- /dev/null
+++ b/src/platform/telink/ICDUtil.cpp
@@ -0,0 +1,40 @@
+/*
+ *
+ *    Copyright (c) 2023 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "ICDUtil.h"
+
+ICDUtil ICDUtil::sICDUtil;
+
+CHIP_ERROR ICDUtil::OnSubscriptionRequested(chip::app::ReadHandler & aReadHandler, chip::Transport::SecureSession & aSecureSession)
+{
+    uint16_t agreedMaxInterval    = CONFIG_CHIP_MAX_PREFERRED_SUBSCRIPTION_REPORT_INTERVAL;
+    uint16_t requestedMinInterval = 0;
+    uint16_t requestedMaxInterval = 0;
+    aReadHandler.GetReportingIntervals(requestedMinInterval, requestedMaxInterval);
+
+    if (requestedMaxInterval > agreedMaxInterval)
+    {
+        agreedMaxInterval = requestedMaxInterval;
+    }
+    else if (agreedMaxInterval > kSubscriptionMaxIntervalPublisherLimit)
+    {
+        agreedMaxInterval = kSubscriptionMaxIntervalPublisherLimit;
+    }
+
+    return aReadHandler.SetReportingIntervals(agreedMaxInterval);
+}
diff --git a/src/platform/telink/ICDUtil.h b/src/platform/telink/ICDUtil.h
new file mode 100644
index 0000000..33db1e9
--- /dev/null
+++ b/src/platform/telink/ICDUtil.h
@@ -0,0 +1,33 @@
+/*
+ *
+ *    Copyright (c) 2023 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include <app/ReadHandler.h>
+
+class ICDUtil : public chip::app::ReadHandler::ApplicationCallback
+{
+    CHIP_ERROR OnSubscriptionRequested(chip::app::ReadHandler & aReadHandler,
+                                       chip::Transport::SecureSession & aSecureSession) override;
+    friend ICDUtil & GetICDUtil();
+    static ICDUtil sICDUtil;
+};
+
+inline ICDUtil & GetICDUtil()
+{
+    return ICDUtil::sICDUtil;
+}