TV Matter Media: Add logic to message cluster (#31943)

* Adding basic logic

* Updates

* Update message cluster

* Update copyright

* Restyled by whitespace

* Restyled by clang-format

---------

Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/examples/tv-app/android/include/messages/MessagesManager.cpp b/examples/tv-app/android/include/messages/MessagesManager.cpp
new file mode 100644
index 0000000..dcd48f0
--- /dev/null
+++ b/examples/tv-app/android/include/messages/MessagesManager.cpp
@@ -0,0 +1,54 @@
+/**
+ *
+ *    Copyright (c) 2024 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.
+ */
+
+#include "MessagesManager.h"
+
+using namespace std;
+using namespace chip::app;
+using namespace chip::app::Clusters::Messages;
+
+// Commands
+void MessagesManager::HandlePresentMessagesRequest(
+    const chip::ByteSpan & messageId, const MessagePriorityEnum & priority,
+    const chip::BitMask<MessageControlBitmap> & messageControl, const chip::app::DataModel::Nullable<uint32_t> & startTime,
+    const chip::app::DataModel::Nullable<uint16_t> & duration, const chip::CharSpan & messageText,
+    const chip::Optional<chip::app::DataModel::DecodableList<MessageResponseOption>> & responses)
+{
+    // TODO: Present Message
+}
+
+void MessagesManager::HandleCancelMessagesRequest(const chip::app::DataModel::DecodableList<chip::ByteSpan> & messageIds)
+{
+    // TODO: Cancel Message
+}
+
+// Attributes
+CHIP_ERROR MessagesManager::HandleGetMessages(chip::app::AttributeValueEncoder & aEncoder)
+{
+    return aEncoder.EncodeEmptyList();
+}
+
+CHIP_ERROR MessagesManager::HandleGetActiveMessageIds(chip::app::AttributeValueEncoder & aEncoder)
+{
+    return aEncoder.EncodeEmptyList();
+}
+
+// Global Attributes
+uint32_t MessagesManager::GetFeatureMap(chip::EndpointId endpoint)
+{
+    return 1;
+}
diff --git a/examples/tv-app/android/include/messages/MessagesManager.h b/examples/tv-app/android/include/messages/MessagesManager.h
new file mode 100644
index 0000000..5f06d25
--- /dev/null
+++ b/examples/tv-app/android/include/messages/MessagesManager.h
@@ -0,0 +1,45 @@
+/**
+ *
+ *    Copyright (c) 2024 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/clusters/messages-server/messages-server.h>
+#include <list>
+
+class MessagesManager : public chip::app::Clusters::Messages::Delegate
+{
+public:
+    // Commands
+    void HandlePresentMessagesRequest(
+        const chip::ByteSpan & messageId, const chip::app::Clusters::Messages::MessagePriorityEnum & priority,
+        const chip::BitMask<chip::app::Clusters::Messages::MessageControlBitmap> & messageControl,
+        const chip::app::DataModel::Nullable<uint32_t> & startTime, const chip::app::DataModel::Nullable<uint16_t> & duration,
+        const chip::CharSpan & messageText,
+        const chip::Optional<chip::app::DataModel::DecodableList<
+            chip::app::Clusters::Messages::Structs::MessageResponseOptionStruct::DecodableType>> & responses) override;
+    void HandleCancelMessagesRequest(const chip::app::DataModel::DecodableList<chip::ByteSpan> & messageIds) override;
+
+    // Attributes
+    CHIP_ERROR HandleGetMessages(chip::app::AttributeValueEncoder & aEncoder) override;
+    CHIP_ERROR HandleGetActiveMessageIds(chip::app::AttributeValueEncoder & aEncoder) override;
+
+    // Global Attributes
+    uint32_t GetFeatureMap(chip::EndpointId endpoint) override;
+
+protected:
+    std::list<std::string> mMessages;
+};
diff --git a/examples/tv-app/tv-common/BUILD.gn b/examples/tv-app/tv-common/BUILD.gn
index c522709..699a13a 100644
--- a/examples/tv-app/tv-common/BUILD.gn
+++ b/examples/tv-app/tv-common/BUILD.gn
@@ -64,6 +64,8 @@
     "clusters/media-input/MediaInputManager.h",
     "clusters/media-playback/MediaPlaybackManager.cpp",
     "clusters/media-playback/MediaPlaybackManager.h",
+    "clusters/messages/MessagesManager.cpp",
+    "clusters/messages/MessagesManager.h",
     "clusters/target-navigator/TargetNavigatorManager.cpp",
     "clusters/target-navigator/TargetNavigatorManager.h",
     "clusters/wake-on-lan/WakeOnLanManager.cpp",
diff --git a/examples/tv-app/tv-common/clusters/messages/MessagesManager.cpp b/examples/tv-app/tv-common/clusters/messages/MessagesManager.cpp
new file mode 100644
index 0000000..11068dc
--- /dev/null
+++ b/examples/tv-app/tv-common/clusters/messages/MessagesManager.cpp
@@ -0,0 +1,81 @@
+/**
+ *
+ *    Copyright (c) 2024 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.
+ */
+
+#include "MessagesManager.h"
+
+#include <app-common/zap-generated/attributes/Accessors.h>
+
+using namespace std;
+using namespace chip::app;
+using namespace chip::app::Clusters::Messages;
+using Message = chip::app::Clusters::Messages::Structs::MessageStruct::Type;
+
+// Commands
+void MessagesManager::HandlePresentMessagesRequest(
+    const chip::ByteSpan & messageId, const MessagePriorityEnum & priority,
+    const chip::BitMask<MessageControlBitmap> & messageControl, const chip::app::DataModel::Nullable<uint32_t> & startTime,
+    const chip::app::DataModel::Nullable<uint16_t> & duration, const chip::CharSpan & messageText,
+    const chip::Optional<chip::app::DataModel::DecodableList<MessageResponseOption>> & responses)
+{
+    Message message{
+        // TODO: Enable id
+        chip::ByteSpan(), priority, messageControl, startTime, duration,
+        // TODO: Enable text
+        chip::CharSpan()
+        // TODO: Convert responses to Optional<chip::app::DataModel::List<const
+        // chip::app::Clusters::Messages::Structs::MessageResponseOptionStruct::Type>> message.responses = responses;
+    };
+
+    mMessages.push_back(message);
+    // Add your code to present Message
+}
+
+void MessagesManager::HandleCancelMessagesRequest(const chip::app::DataModel::DecodableList<chip::ByteSpan> & messageIds)
+{
+    // TODO: Cancel Message
+}
+
+// Attributes
+CHIP_ERROR MessagesManager::HandleGetMessages(chip::app::AttributeValueEncoder & aEncoder)
+{
+    return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR {
+        for (Message & entry : mMessages)
+        {
+            ReturnErrorOnFailure(encoder.Encode(entry));
+        }
+        return CHIP_NO_ERROR;
+    });
+}
+
+CHIP_ERROR MessagesManager::HandleGetActiveMessageIds(chip::app::AttributeValueEncoder & aEncoder)
+{
+    return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR {
+        for (Message & entry : mMessages)
+        {
+            ReturnErrorOnFailure(encoder.Encode(entry.messageID));
+        }
+        return CHIP_NO_ERROR;
+    });
+}
+
+// Global Attributes
+uint32_t MessagesManager::GetFeatureMap(chip::EndpointId endpoint)
+{
+    uint32_t featureMap = 0;
+    Attributes::FeatureMap::Get(endpoint, &featureMap);
+    return featureMap;
+}
diff --git a/examples/tv-app/tv-common/clusters/messages/MessagesManager.h b/examples/tv-app/tv-common/clusters/messages/MessagesManager.h
new file mode 100644
index 0000000..97ff509
--- /dev/null
+++ b/examples/tv-app/tv-common/clusters/messages/MessagesManager.h
@@ -0,0 +1,48 @@
+/**
+ *
+ *    Copyright (c) 2024 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/clusters/messages-server/messages-server.h>
+
+#include <iostream>
+#include <list>
+
+class MessagesManager : public chip::app::Clusters::Messages::Delegate
+{
+public:
+    // Commands
+    void HandlePresentMessagesRequest(
+        const chip::ByteSpan & messageId, const chip::app::Clusters::Messages::MessagePriorityEnum & priority,
+        const chip::BitMask<chip::app::Clusters::Messages::MessageControlBitmap> & messageControl,
+        const chip::app::DataModel::Nullable<uint32_t> & startTime, const chip::app::DataModel::Nullable<uint16_t> & duration,
+        const chip::CharSpan & messageText,
+        const chip::Optional<
+            chip::app::DataModel::DecodableList<chip::app::Clusters::Messages::Structs::MessageResponseOptionStruct::Type>> &
+            responses) override;
+    void HandleCancelMessagesRequest(const chip::app::DataModel::DecodableList<chip::ByteSpan> & messageIds) override;
+
+    // Attributes
+    CHIP_ERROR HandleGetMessages(chip::app::AttributeValueEncoder & aEncoder) override;
+    CHIP_ERROR HandleGetActiveMessageIds(chip::app::AttributeValueEncoder & aEncoder) override;
+
+    // Global Attributes
+    uint32_t GetFeatureMap(chip::EndpointId endpoint) override;
+
+protected:
+    std::list<chip::app::Clusters::Messages::Structs::MessageStruct::Type> mMessages;
+};
diff --git a/examples/tv-app/tv-common/src/ZCLCallbacks.cpp b/examples/tv-app/tv-common/src/ZCLCallbacks.cpp
index c56a3f7..cffb427 100644
--- a/examples/tv-app/tv-common/src/ZCLCallbacks.cpp
+++ b/examples/tv-app/tv-common/src/ZCLCallbacks.cpp
@@ -37,6 +37,7 @@
 #include "low-power/LowPowerManager.h"
 #include "media-input/MediaInputManager.h"
 #include "media-playback/MediaPlaybackManager.h"
+#include "messages/MessagesManager.h"
 #include "target-navigator/TargetNavigatorManager.h"
 #include "wake-on-lan/WakeOnLanManager.h"
 
@@ -56,6 +57,7 @@
 static LowPowerManager lowPowerManager;
 static MediaInputManager mediaInputManager;
 static MediaPlaybackManager mediaPlaybackManager;
+static MessagesManager messagesManager;
 static TargetNavigatorManager targetNavigatorManager;
 static WakeOnLanManager wakeOnLanManager;
 } // namespace
@@ -170,6 +172,12 @@
     MediaPlayback::SetDefaultDelegate(endpoint, &mediaPlaybackManager);
 }
 
+void emberAfMessagesClusterInitCallback(EndpointId endpoint)
+{
+    ChipLogProgress(Zcl, "TV Linux App: Messages::SetDefaultDelegate");
+    Messages::SetDefaultDelegate(endpoint, &messagesManager);
+}
+
 void emberAfTargetNavigatorClusterInitCallback(EndpointId endpoint)
 {
     ChipLogProgress(Zcl, "TV Linux App: TargetNavigator::SetDefaultDelegate");
diff --git a/examples/tv-app/tv-common/tv-app.cmake b/examples/tv-app/tv-common/tv-app.cmake
index bfa554d..fd98223 100644
--- a/examples/tv-app/tv-common/tv-app.cmake
+++ b/examples/tv-app/tv-common/tv-app.cmake
@@ -62,6 +62,7 @@
             ${CHIP_TV_COMMON_BASE_DIR}/clusters/low-power/LowPowerManager.cpp
             ${CHIP_TV_COMMON_BASE_DIR}/clusters/media-input/MediaInputManager.cpp
             ${CHIP_TV_COMMON_BASE_DIR}/clusters/media-playback/MediaPlaybackManager.cpp
+            ${CHIP_TV_COMMON_BASE_DIR}/clusters/messages/MessagesManager.cpp
             ${CHIP_TV_COMMON_BASE_DIR}/clusters/target-navigator/TargetNavigatorManager.cpp
             ${CHIP_TV_COMMON_BASE_DIR}/clusters/wake-on-lan/WakeOnLanManager.cpp
 
diff --git a/src/app/clusters/messages-server/messages-delegate.h b/src/app/clusters/messages-server/messages-delegate.h
new file mode 100644
index 0000000..b836a6b
--- /dev/null
+++ b/src/app/clusters/messages-server/messages-delegate.h
@@ -0,0 +1,60 @@
+/*
+ *
+ *    Copyright (c) 2024 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.
+ */
+
+#pragma once
+
+#include <app-common/zap-generated/cluster-objects.h>
+
+#include <app/AttributeAccessInterface.h>
+#include <app/CommandResponseHelper.h>
+#include <app/util/af.h>
+
+namespace chip {
+namespace app {
+namespace Clusters {
+namespace Messages {
+
+using MessageResponseOption = chip::app::Clusters::Messages::Structs::MessageResponseOptionStruct::Type;
+
+class Delegate
+{
+public:
+    // Commands
+    virtual void
+    HandlePresentMessagesRequest(const ByteSpan & messageId, const MessagePriorityEnum & priority,
+                                 const chip::BitMask<MessageControlBitmap> & messageControl,
+                                 const DataModel::Nullable<uint32_t> & startTime, const DataModel::Nullable<uint16_t> & duration,
+                                 const CharSpan & messageText,
+                                 const chip::Optional<DataModel::DecodableList<MessageResponseOption>> & responses) = 0;
+    virtual void HandleCancelMessagesRequest(const DataModel::DecodableList<chip::ByteSpan> & messageIds)           = 0;
+
+    // Attributes
+    virtual CHIP_ERROR HandleGetMessages(app::AttributeValueEncoder & aEncoder)         = 0;
+    virtual CHIP_ERROR HandleGetActiveMessageIds(app::AttributeValueEncoder & aEncoder) = 0;
+
+    // Global Attributes
+    bool HasFeature(chip::EndpointId endpoint, Feature feature);
+    virtual uint32_t GetFeatureMap(chip::EndpointId endpoint) = 0;
+
+    virtual ~Delegate() = default;
+};
+
+} // namespace Messages
+} // namespace Clusters
+} // namespace app
+} // namespace chip
diff --git a/src/app/clusters/messages-server/messages-server.cpp b/src/app/clusters/messages-server/messages-server.cpp
index 2cca091..33a403e 100644
--- a/src/app/clusters/messages-server/messages-server.cpp
+++ b/src/app/clusters/messages-server/messages-server.cpp
@@ -1,29 +1,199 @@
-#include "messages-server.h"
+/**
+ *
+ *    Copyright (c) 2024 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.
+ */
+
+#include <app/clusters/messages-server/messages-delegate.h>
+#include <app/clusters/messages-server/messages-server.h>
 
 #include <app-common/zap-generated/attributes/Accessors.h>
-#include <app-common/zap-generated/cluster-objects.h>
-#include <app-common/zap-generated/ids/Attributes.h>
-#include <app-common/zap-generated/ids/Clusters.h>
-#include <app-common/zap-generated/ids/Commands.h>
+#include <app/AttributeAccessInterface.h>
 #include <app/CommandHandler.h>
 #include <app/ConcreteCommandPath.h>
-
-#include <app/util/af.h>
-#include <app/util/common.h>
-#include <app/util/error-mapping.h>
-#include <array>
-#include <lib/support/CodeUtils.h>
-#include <platform/CHIPDeviceLayer.h>
+#include <app/EventLogging.h>
+#include <app/data-model/Encode.h>
+#include <app/util/attribute-storage.h>
+#include <app/util/config.h>
+#include <platform/CHIPDeviceConfig.h>
 
 using namespace chip;
 using namespace chip::app;
+using namespace chip::app::Clusters;
 using namespace chip::app::Clusters::Messages;
+using chip::app::LogEvent;
 using chip::Protocols::InteractionModel::Status;
 
+static constexpr size_t kMessagesDelegateTableSize =
+    MATTER_DM_MESSAGES_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT;
+static_assert(kMessagesDelegateTableSize <= kEmberInvalidEndpointIndex, "Messages Delegate table size error");
+
+// -----------------------------------------------------------------------------
+// Delegate Implementation
+
+namespace {
+
+Delegate * gDelegateTable[kMessagesDelegateTableSize] = { nullptr };
+
+Delegate * GetDelegate(EndpointId endpoint)
+{
+    ChipLogProgress(Zcl, "MessagesCluster NOT returning delegate for endpoint:%u", endpoint);
+
+    uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, Messages::Id, MATTER_DM_MESSAGES_CLUSTER_SERVER_ENDPOINT_COUNT);
+    return (ep >= kMessagesDelegateTableSize ? nullptr : gDelegateTable[ep]);
+}
+
+bool isDelegateNull(Delegate * delegate, EndpointId endpoint)
+{
+    if (delegate == nullptr)
+    {
+        ChipLogProgress(Zcl, "Message Cluster has no delegate set for endpoint:%u", endpoint);
+        return true;
+    }
+    return false;
+}
+} // namespace
+
+namespace chip {
+namespace app {
+namespace Clusters {
+namespace Messages {
+
+void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate)
+{
+    uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, Messages::Id, MATTER_DM_MESSAGES_CLUSTER_SERVER_ENDPOINT_COUNT);
+    // if endpoint is found
+    if (ep < kMessagesDelegateTableSize)
+    {
+        gDelegateTable[ep] = delegate;
+    }
+}
+
+bool Delegate::HasFeature(chip::EndpointId endpoint, Feature feature)
+{
+    uint32_t featureMap = GetFeatureMap(endpoint);
+    return (featureMap & chip::to_underlying(feature));
+}
+
+} // namespace Messages
+} // namespace Clusters
+} // namespace app
+} // namespace chip
+
+// -----------------------------------------------------------------------------
+// Attribute Accessor Implementation
+
+namespace {
+
+class MessagesAttrAccess : public app::AttributeAccessInterface
+{
+public:
+    MessagesAttrAccess() : app::AttributeAccessInterface(Optional<EndpointId>::Missing(), Messages::Id) {}
+
+    CHIP_ERROR Read(const app::ConcreteReadAttributePath & aPath, app::AttributeValueEncoder & aEncoder) override;
+
+private:
+    CHIP_ERROR ReadMessages(app::AttributeValueEncoder & aEncoder, Delegate * delegate);
+    CHIP_ERROR ReadActiveMessageIds(app::AttributeValueEncoder & aEncoder, Delegate * delegate);
+    CHIP_ERROR ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, Delegate * delegate);
+};
+
+MessagesAttrAccess gMessagesAttrAccess;
+
+CHIP_ERROR MessagesAttrAccess::Read(const app::ConcreteReadAttributePath & aPath, app::AttributeValueEncoder & aEncoder)
+{
+    EndpointId endpoint = aPath.mEndpointId;
+    Delegate * delegate = GetDelegate(endpoint);
+
+    switch (aPath.mAttributeId)
+    {
+    case app::Clusters::Messages::Attributes::Messages::Id:
+        if (isDelegateNull(delegate, endpoint))
+        {
+            return aEncoder.EncodeEmptyList();
+        }
+
+        return ReadMessages(aEncoder, delegate);
+    case app::Clusters::Messages::Attributes::ActiveMessageIDs::Id:
+        if (isDelegateNull(delegate, endpoint))
+        {
+            return aEncoder.EncodeEmptyList();
+        }
+
+        return ReadActiveMessageIds(aEncoder, delegate);
+    case app::Clusters::Messages::Attributes::FeatureMap::Id:
+        if (isDelegateNull(delegate, endpoint))
+        {
+            return CHIP_NO_ERROR;
+        }
+
+        return ReadFeatureFlagAttribute(endpoint, aEncoder, delegate);
+    default:
+        break;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MessagesAttrAccess::ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder,
+                                                        Delegate * delegate)
+{
+    uint32_t featureFlag = delegate->GetFeatureMap(endpoint);
+    return aEncoder.Encode(featureFlag);
+}
+
+CHIP_ERROR MessagesAttrAccess::ReadMessages(app::AttributeValueEncoder & aEncoder, Delegate * delegate)
+{
+    return delegate->HandleGetMessages(aEncoder);
+}
+
+CHIP_ERROR MessagesAttrAccess::ReadActiveMessageIds(app::AttributeValueEncoder & aEncoder, Delegate * delegate)
+{
+    return delegate->HandleGetActiveMessageIds(aEncoder);
+}
+
+} // anonymous namespace
+
 bool emberAfMessagesClusterPresentMessagesRequestCallback(
     chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
     const chip::app::Clusters::Messages::Commands::PresentMessagesRequest::DecodableType & commandData)
 {
+    CHIP_ERROR err      = CHIP_NO_ERROR;
+    EndpointId endpoint = commandPath.mEndpointId;
+    Status status       = Status::Success;
+
+    auto & messageId      = commandData.messageID;
+    auto & priority       = commandData.priority;
+    auto & messageControl = commandData.messageControl;
+    auto & startTime      = commandData.startTime;
+    auto & duration       = commandData.duration;
+    auto & messageText    = commandData.messageText;
+    auto & responses      = commandData.responses;
+
+    Delegate * delegate = GetDelegate(endpoint);
+    VerifyOrExit(isDelegateNull(delegate, endpoint) != true, err = CHIP_ERROR_INCORRECT_STATE);
+
+    delegate->HandlePresentMessagesRequest(messageId, priority, messageControl, startTime, duration, messageText, responses);
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(Zcl, "emberAfMessagesClusterPresentMessagesRequestCallback error: %s", err.AsString());
+        status = Status::Failure;
+    }
+
+    commandObj->AddStatus(commandPath, status);
     return true;
 }
 
@@ -35,7 +205,29 @@
     chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath,
     const chip::app::Clusters::Messages::Commands::CancelMessagesRequest::DecodableType & commandData)
 {
+    CHIP_ERROR err      = CHIP_NO_ERROR;
+    EndpointId endpoint = commandPath.mEndpointId;
+    Status status       = Status::Success;
+
+    auto & messageIds = commandData.messageIDs;
+
+    Delegate * delegate = GetDelegate(endpoint);
+    VerifyOrExit(isDelegateNull(delegate, endpoint) != true, err = CHIP_ERROR_INCORRECT_STATE);
+
+    delegate->HandleCancelMessagesRequest(messageIds);
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(Zcl, "emberAfMessagesClusterCancelMessagesRequestCallback error: %s", err.AsString());
+        status = Status::Failure;
+    }
+
+    commandObj->AddStatus(commandPath, status);
     return true;
 }
 
-void MatterMessagesPluginServerInitCallback() {}
+void MatterMessagesPluginServerInitCallback()
+{
+    registerAttributeAccessOverride(&gMessagesAttrAccess);
+}
diff --git a/src/app/clusters/messages-server/messages-server.h b/src/app/clusters/messages-server/messages-server.h
index 767534f..a1ae6c0 100644
--- a/src/app/clusters/messages-server/messages-server.h
+++ b/src/app/clusters/messages-server/messages-server.h
@@ -17,13 +17,18 @@
 
 #pragma once
 
+#include "messages-delegate.h"
 #include <app-common/zap-generated/cluster-enums.h>
 #include <app/util/basic-types.h>
 
 namespace chip {
 namespace app {
 namespace Clusters {
-namespace Messaging {} // namespace Messaging
+namespace Messages {
+
+void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate);
+
+} // namespace Messages
 } // namespace Clusters
 } // namespace app
 } // namespace chip