Add featureflags to content app (dynamic) endpoints (#19930)
* Add featureflags to content app (dynamic) endpoints
* Add featureflag support to dynamic endpoints with clusters channel, keypadinput, mediaplayback
* Add featureflag support to android implementation
* Fix Darwin clang-tidy errors
* Fix missing vendorId in AddNoc from tv-app
diff --git a/examples/platform/linux/CommissionerMain.cpp b/examples/platform/linux/CommissionerMain.cpp
index f30e922..afa4f80 100644
--- a/examples/platform/linux/CommissionerMain.cpp
+++ b/examples/platform/linux/CommissionerMain.cpp
@@ -42,6 +42,7 @@
#include <setup_payload/SetupPayload.h>
#include <platform/CommissionableDataProvider.h>
+#include <platform/DeviceInstanceInfoProvider.h>
#include <platform/DiagnosticDataProvider.h>
#include <platform/TestOnlyCommissionableDataProvider.h>
@@ -132,6 +133,10 @@
factoryParams.groupDataProvider = &gGroupDataProvider;
params.operationalCredentialsDelegate = &gOpCredsIssuer;
+ uint16_t vendorId;
+ DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(vendorId);
+ ChipLogProgress(Support, " ----- Commissioner using vendorId 0x%04X", vendorId);
+ params.controllerVendorId = static_cast<VendorId>(vendorId);
ReturnErrorOnFailure(gOpCredsIssuer.Initialize(gServerStorage));
diff --git a/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp b/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp
index 1d15233..6dc80c5 100644
--- a/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp
+++ b/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp
@@ -100,3 +100,15 @@
ChipLogProgress(Zcl, "AppContentLauncherManager::HandleGetSupportedStreamingProtocols");
return mSupportedStreamingProtocols;
}
+
+uint32_t AppContentLauncherManager::GetFeatureMap(chip::EndpointId endpoint)
+{
+ if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT)
+ {
+ return mDynamicEndpointFeatureMap;
+ }
+
+ uint32_t featureMap = 0;
+ Attributes::FeatureMap::Get(endpoint, &featureMap);
+ return featureMap;
+}
diff --git a/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.h b/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.h
index af0b987..b5b8f7a 100644
--- a/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.h
+++ b/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.h
@@ -19,6 +19,7 @@
#pragma once
#include "../../java/ContentAppCommandDelegate.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
#include <app/clusters/content-launch-server/content-launch-server.h>
using chip::CharSpan;
@@ -47,6 +48,8 @@
void SetEndpointId(EndpointId epId) { mEndpointId = epId; };
+ uint32_t GetFeatureMap(chip::EndpointId endpoint) override;
+
protected:
std::list<std::string> mAcceptHeaderList;
uint32_t mSupportedStreamingProtocols;
@@ -54,4 +57,7 @@
private:
EndpointId mEndpointId;
ContentAppCommandDelegate mCommandDelegate;
+
+ // TODO: set this based upon meta data from app
+ uint32_t mDynamicEndpointFeatureMap = 3;
};
diff --git a/examples/tv-app/android/java/AppImpl.cpp b/examples/tv-app/android/java/AppImpl.cpp
index a0564d2..063a2be 100644
--- a/examples/tv-app/android/java/AppImpl.cpp
+++ b/examples/tv-app/android/java/AppImpl.cpp
@@ -113,6 +113,12 @@
// CONTENT APP ENDPOINT: contains the following clusters:
// - Descriptor
// - Application Basic
+// - Keypad Input
+// - Application Launcher
+// - Account Login
+// - Content Launcher
+// - Target Navigator
+// - Channel
// Declare Descriptor cluster attributes
DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(descriptorAttrs)
@@ -123,23 +129,27 @@
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Application Basic information cluster attributes
-// TODO: add missing attributes once schema is updated
DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(applicationBasicAttrs)
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VENDOR_NAME_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* VendorName */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VENDOR_ID_ATTRIBUTE_ID, INT16U, 1, 0), /* VendorID */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_NAME_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* ApplicationName */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_PRODUCT_ID_ATTRIBUTE_ID, INT16U, 1, 0), /* ProductID */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_STATUS_ATTRIBUTE_ID, INT8U, 1, 0), /* ApplicationStatus */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VERSION_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* ApplicationVersion */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_ALLOWED_VENDOR_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize,
+ 0), /* AllowedVendorList */
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Keypad Input cluster attributes
DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(keypadInputAttrs)
-DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
+DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */
+ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Application Launcher cluster attributes
-// TODO: add missing attributes once schema is updated
+// NOTE: Does not make sense for content app to be able to set the AP feature flag
DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(applicationLauncherAttrs)
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_LAUNCHER_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* catalog list */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_LAUNCHER_CURRENT_APP_ATTRIBUTE_ID, STRUCT, 1, 0), /* current app */
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Account Login cluster attributes
@@ -151,18 +161,20 @@
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CONTENT_LAUNCHER_ACCEPT_HEADER_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize,
0), /* accept header list */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CONTENT_LAUNCHER_SUPPORTED_STREAMING_PROTOCOLS_ATTRIBUTE_ID, BITMAP32, 1,
- 0), /* streaming protocols */
+ 0), /* streaming protocols */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Media Playback cluster attributes
-// TODO: add missing attributes once schema is updated
DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(mediaPlaybackAttrs)
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_STATE_ATTRIBUTE_ID, ENUM8, 1, 0), /* current state */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_START_TIME_ATTRIBUTE_ID, EPOCH_US, 1, 0), /* start time */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_DURATION_ATTRIBUTE_ID, INT64U, 1, 0), /* duration */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_POSITION_ATTRIBUTE_ID, STRUCT, 1, 0), /* playback speed */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SPEED_ATTRIBUTE_ID, SINGLE, 1, 0), /* playback speed */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SEEK_RANGE_END_ATTRIBUTE_ID, INT64U, 1, 0), /* seek range end */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SEEK_RANGE_START_ATTRIBUTE_ID, INT64U, 1, 0), /* seek range start */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Target Navigator cluster attributes
@@ -176,6 +188,7 @@
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* channel list */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_LINEUP_ATTRIBUTE_ID, STRUCT, 1, 0), /* lineup */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_CURRENT_CHANNEL_ATTRIBUTE_ID, STRUCT, 1, 0), /* current channel */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
constexpr CommandId keypadInputIncomingCommands[] = {
diff --git a/examples/tv-app/android/java/ChannelManager.cpp b/examples/tv-app/android/java/ChannelManager.cpp
index e8231b3..fb8a4d8 100644
--- a/examples/tv-app/android/java/ChannelManager.cpp
+++ b/examples/tv-app/android/java/ChannelManager.cpp
@@ -17,6 +17,7 @@
#include "ChannelManager.h"
#include "TvApp-JNI.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <cstdlib>
#include <jni.h>
@@ -407,3 +408,15 @@
env->ExceptionClear();
}
}
+
+uint32_t ChannelManager::GetFeatureMap(chip::EndpointId endpoint)
+{
+ if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT)
+ {
+ return mDynamicEndpointFeatureMap;
+ }
+
+ uint32_t featureMap = 0;
+ Attributes::FeatureMap::Get(endpoint, &featureMap);
+ return featureMap;
+}
diff --git a/examples/tv-app/android/java/ChannelManager.h b/examples/tv-app/android/java/ChannelManager.h
index e7fb8e3..0439900 100644
--- a/examples/tv-app/android/java/ChannelManager.h
+++ b/examples/tv-app/android/java/ChannelManager.h
@@ -40,6 +40,8 @@
bool HandleChangeChannelByNumber(const uint16_t & majorNumber, const uint16_t & minorNumber) override;
bool HandleSkipChannel(const uint16_t & count) override;
+ uint32_t GetFeatureMap(chip::EndpointId endpoint) override;
+
private:
jobject mChannelManagerObject = nullptr;
jmethodID mGetChannelListMethod = nullptr;
@@ -49,4 +51,7 @@
jmethodID mChangeChannelMethod = nullptr;
jmethodID mChangeChannelByNumberMethod = nullptr;
jmethodID mSkipChannelMethod = nullptr;
+
+ // TODO: set this based upon meta data from app
+ uint32_t mDynamicEndpointFeatureMap = 3;
};
diff --git a/examples/tv-app/android/java/ContentLauncherManager.cpp b/examples/tv-app/android/java/ContentLauncherManager.cpp
index 3b2be95..81fa61b 100644
--- a/examples/tv-app/android/java/ContentLauncherManager.cpp
+++ b/examples/tv-app/android/java/ContentLauncherManager.cpp
@@ -18,6 +18,7 @@
#include "ContentLauncherManager.h"
#include "TvApp-JNI.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <jni.h>
#include <lib/core/CHIPSafeCasts.h>
@@ -272,3 +273,10 @@
env->ExceptionClear();
}
}
+
+uint32_t ContentLauncherManager::GetFeatureMap(chip::EndpointId endpoint)
+{
+ uint32_t featureMap = 0;
+ Attributes::FeatureMap::Get(endpoint, &featureMap);
+ return featureMap;
+}
diff --git a/examples/tv-app/android/java/ContentLauncherManager.h b/examples/tv-app/android/java/ContentLauncherManager.h
index a034afd..79a35de 100644
--- a/examples/tv-app/android/java/ContentLauncherManager.h
+++ b/examples/tv-app/android/java/ContentLauncherManager.h
@@ -47,6 +47,8 @@
CHIP_ERROR HandleGetAcceptHeaderList(AttributeValueEncoder & aEncoder) override;
uint32_t HandleGetSupportedStreamingProtocols() override;
+ uint32_t GetFeatureMap(chip::EndpointId endpoint) override;
+
private:
jobject mContentLauncherManagerObject = nullptr;
jmethodID mGetAcceptHeaderMethod = nullptr;
diff --git a/examples/tv-app/android/java/KeypadInputManager.cpp b/examples/tv-app/android/java/KeypadInputManager.cpp
index f8c19a1..e4cfdad 100644
--- a/examples/tv-app/android/java/KeypadInputManager.cpp
+++ b/examples/tv-app/android/java/KeypadInputManager.cpp
@@ -18,6 +18,7 @@
#include "KeypadInputManager.h"
#include "TvApp-JNI.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <lib/support/CHIPJNIError.h>
#include <lib/support/JniReferences.h>
@@ -86,3 +87,15 @@
env->ExceptionClear();
}
}
+
+uint32_t KeypadInputManager::GetFeatureMap(chip::EndpointId endpoint)
+{
+ if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT)
+ {
+ return mDynamicEndpointFeatureMap;
+ }
+
+ uint32_t featureMap = 0;
+ Attributes::FeatureMap::Get(endpoint, &featureMap);
+ return featureMap;
+}
diff --git a/examples/tv-app/android/java/KeypadInputManager.h b/examples/tv-app/android/java/KeypadInputManager.h
index 416c878..8c43cc0 100644
--- a/examples/tv-app/android/java/KeypadInputManager.h
+++ b/examples/tv-app/android/java/KeypadInputManager.h
@@ -34,7 +34,12 @@
void HandleSendKey(CommandResponseHelper<SendKeyResponseType> & helper,
const chip::app::Clusters::KeypadInput::CecKeyCode & keyCode) override;
+ uint32_t GetFeatureMap(chip::EndpointId endpoint) override;
+
private:
jobject mKeypadInputManagerObject = nullptr;
jmethodID mSendKeyMethod = nullptr;
+
+ // TODO: set this based upon meta data from app
+ uint32_t mDynamicEndpointFeatureMap = 7;
};
diff --git a/examples/tv-app/android/java/MediaPlaybackManager.cpp b/examples/tv-app/android/java/MediaPlaybackManager.cpp
index 85d2e60..0bc9244 100644
--- a/examples/tv-app/android/java/MediaPlaybackManager.cpp
+++ b/examples/tv-app/android/java/MediaPlaybackManager.cpp
@@ -17,6 +17,7 @@
#include "MediaPlaybackManager.h"
#include "TvApp-JNI.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <cstdint>
#include <jni.h>
@@ -298,3 +299,15 @@
return aEncoder.Encode(response);
}
+
+uint32_t MediaPlaybackManager::GetFeatureMap(chip::EndpointId endpoint)
+{
+ if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT)
+ {
+ return mDynamicEndpointFeatureMap;
+ }
+
+ uint32_t featureMap = 0;
+ Attributes::FeatureMap::Get(endpoint, &featureMap);
+ return featureMap;
+}
diff --git a/examples/tv-app/android/java/MediaPlaybackManager.h b/examples/tv-app/android/java/MediaPlaybackManager.h
index 74f2812..822fcf5 100644
--- a/examples/tv-app/android/java/MediaPlaybackManager.h
+++ b/examples/tv-app/android/java/MediaPlaybackManager.h
@@ -81,6 +81,8 @@
void HandleNext(CommandResponseHelper<PlaybackResponseType> & helper) override;
void HandleStartOver(CommandResponseHelper<PlaybackResponseType> & helper) override;
+ uint32_t GetFeatureMap(chip::EndpointId endpoint) override;
+
private:
jobject mMediaPlaybackManagerObject = nullptr;
jmethodID mRequestMethod = nullptr;
@@ -90,4 +92,7 @@
uint64_t HandleMediaRequestGetAttribute(MediaPlaybackRequestAttribute attribute);
chip::app::Clusters::MediaPlayback::Commands::PlaybackResponse::Type
HandleMediaRequest(MediaPlaybackRequest mediaPlaybackRequest, uint64_t deltaPositionMilliseconds);
+
+ // TODO: set this based upon meta data from app
+ uint32_t mDynamicEndpointFeatureMap = 3;
};
diff --git a/examples/tv-app/linux/AppImpl.cpp b/examples/tv-app/linux/AppImpl.cpp
index 2cc16ac..06c9829 100644
--- a/examples/tv-app/linux/AppImpl.cpp
+++ b/examples/tv-app/linux/AppImpl.cpp
@@ -22,6 +22,7 @@
#include "AppImpl.h"
#include <app-common/zap-generated/attribute-id.h>
+#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-id.h>
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
@@ -138,6 +139,12 @@
// CONTENT APP ENDPOINT: contains the following clusters:
// - Descriptor
// - Application Basic
+// - Keypad Input
+// - Application Launcher
+// - Account Login
+// - Content Launcher
+// - Target Navigator
+// - Channel
// Declare Descriptor cluster attributes
DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(descriptorAttrs)
@@ -148,23 +155,27 @@
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Application Basic information cluster attributes
-// TODO: add missing attributes once schema is updated
DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(applicationBasicAttrs)
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VENDOR_NAME_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* VendorName */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VENDOR_ID_ATTRIBUTE_ID, INT16U, 1, 0), /* VendorID */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_NAME_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* ApplicationName */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_PRODUCT_ID_ATTRIBUTE_ID, INT16U, 1, 0), /* ProductID */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_STATUS_ATTRIBUTE_ID, INT8U, 1, 0), /* ApplicationStatus */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VERSION_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* ApplicationVersion */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_ALLOWED_VENDOR_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize,
+ 0), /* AllowedVendorList */
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Keypad Input cluster attributes
DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(keypadInputAttrs)
-DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
+DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */
+ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Application Launcher cluster attributes
-// TODO: add missing attributes once schema is updated
+// NOTE: Does not make sense for content app to be able to set the AP feature flag
DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(applicationLauncherAttrs)
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_LAUNCHER_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* catalog list */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_LAUNCHER_CURRENT_APP_ATTRIBUTE_ID, STRUCT, 1, 0), /* current app */
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Account Login cluster attributes
@@ -176,18 +187,20 @@
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CONTENT_LAUNCHER_ACCEPT_HEADER_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize,
0), /* accept header list */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CONTENT_LAUNCHER_SUPPORTED_STREAMING_PROTOCOLS_ATTRIBUTE_ID, BITMAP32, 1,
- 0), /* streaming protocols */
+ 0), /* streaming protocols */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Media Playback cluster attributes
-// TODO: add missing attributes once schema is updated
DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(mediaPlaybackAttrs)
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_STATE_ATTRIBUTE_ID, ENUM8, 1, 0), /* current state */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_START_TIME_ATTRIBUTE_ID, EPOCH_US, 1, 0), /* start time */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_DURATION_ATTRIBUTE_ID, INT64U, 1, 0), /* duration */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_POSITION_ATTRIBUTE_ID, STRUCT, 1, 0), /* playback speed */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SPEED_ATTRIBUTE_ID, SINGLE, 1, 0), /* playback speed */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SEEK_RANGE_END_ATTRIBUTE_ID, INT64U, 1, 0), /* seek range end */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SEEK_RANGE_START_ATTRIBUTE_ID, INT64U, 1, 0), /* seek range start */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
// Declare Target Navigator cluster attributes
@@ -201,6 +214,7 @@
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* channel list */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_LINEUP_ATTRIBUTE_ID, STRUCT, 1, 0), /* lineup */
DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_CURRENT_CHANNEL_ATTRIBUTE_ID, STRUCT, 1, 0), /* current channel */
+ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */
DECLARE_DYNAMIC_ATTRIBUTE_LIST_END();
constexpr CommandId keypadInputIncomingCommands[] = {
diff --git a/examples/tv-app/linux/include/channel/ChannelManager.cpp b/examples/tv-app/linux/include/channel/ChannelManager.cpp
index 4e07025..53c83a2 100644
--- a/examples/tv-app/linux/include/channel/ChannelManager.cpp
+++ b/examples/tv-app/linux/include/channel/ChannelManager.cpp
@@ -16,6 +16,7 @@
*/
#include "ChannelManager.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
#include <vector>
using namespace chip;
@@ -172,3 +173,15 @@
mCurrentChannel = mChannels[mCurrentChannelIndex];
return true;
}
+
+uint32_t ChannelManager::GetFeatureMap(chip::EndpointId endpoint)
+{
+ if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT)
+ {
+ return mDynamicEndpointFeatureMap;
+ }
+
+ uint32_t featureMap = 0;
+ Attributes::FeatureMap::Get(endpoint, &featureMap);
+ return featureMap;
+}
diff --git a/examples/tv-app/linux/include/channel/ChannelManager.h b/examples/tv-app/linux/include/channel/ChannelManager.h
index 7ea0cf7..e56681e 100644
--- a/examples/tv-app/linux/include/channel/ChannelManager.h
+++ b/examples/tv-app/linux/include/channel/ChannelManager.h
@@ -41,8 +41,14 @@
bool HandleChangeChannelByNumber(const uint16_t & majorNumber, const uint16_t & minorNumber) override;
bool HandleSkipChannel(const uint16_t & count) override;
+ uint32_t GetFeatureMap(chip::EndpointId endpoint) override;
+
protected:
uint16_t mCurrentChannelIndex;
ChannelInfoType mCurrentChannel;
std::vector<ChannelInfoType> mChannels;
+
+private:
+ // TODO: set this based upon meta data from app
+ uint32_t mDynamicEndpointFeatureMap = 3;
};
diff --git a/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.cpp b/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.cpp
index a563231..ceb37ec 100644
--- a/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.cpp
+++ b/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.cpp
@@ -17,6 +17,7 @@
*/
#include "ContentLauncherManager.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
using namespace std;
using namespace chip::app;
@@ -186,3 +187,15 @@
ChipLogProgress(Zcl, "ContentLauncherManager::HandleGetSupportedStreamingProtocols");
return mSupportedStreamingProtocols;
}
+
+uint32_t ContentLauncherManager::GetFeatureMap(chip::EndpointId endpoint)
+{
+ if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT)
+ {
+ return mDynamicEndpointFeatureMap;
+ }
+
+ uint32_t featureMap = 0;
+ Attributes::FeatureMap::Get(endpoint, &featureMap);
+ return featureMap;
+}
diff --git a/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.h b/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.h
index 6033ac6..7073d89 100644
--- a/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.h
+++ b/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.h
@@ -51,6 +51,8 @@
CHIP_ERROR HandleGetAcceptHeaderList(AttributeValueEncoder & aEncoder) override;
uint32_t HandleGetSupportedStreamingProtocols() override;
+ uint32_t GetFeatureMap(chip::EndpointId endpoint) override;
+
protected:
std::list<std::string> mAcceptHeaderList;
uint32_t mSupportedStreamingProtocols;
@@ -58,4 +60,6 @@
private:
EndpointId mEndpointId;
+ // TODO: set this based upon meta data from app
+ uint32_t mDynamicEndpointFeatureMap = 3;
};
diff --git a/examples/tv-app/linux/include/keypad-input/KeypadInputManager.cpp b/examples/tv-app/linux/include/keypad-input/KeypadInputManager.cpp
index 7f30c64..84bae28 100644
--- a/examples/tv-app/linux/include/keypad-input/KeypadInputManager.cpp
+++ b/examples/tv-app/linux/include/keypad-input/KeypadInputManager.cpp
@@ -17,6 +17,7 @@
*/
#include "KeypadInputManager.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
using namespace chip;
using namespace chip::app::Clusters::KeypadInput;
@@ -94,3 +95,15 @@
helper.Success(response);
}
+
+uint32_t KeypadInputManager::GetFeatureMap(chip::EndpointId endpoint)
+{
+ if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT)
+ {
+ return mDynamicEndpointFeatureMap;
+ }
+
+ uint32_t featureMap = 0;
+ Attributes::FeatureMap::Get(endpoint, &featureMap);
+ return featureMap;
+}
diff --git a/examples/tv-app/linux/include/keypad-input/KeypadInputManager.h b/examples/tv-app/linux/include/keypad-input/KeypadInputManager.h
index 6936c69..79a83b3 100644
--- a/examples/tv-app/linux/include/keypad-input/KeypadInputManager.h
+++ b/examples/tv-app/linux/include/keypad-input/KeypadInputManager.h
@@ -29,4 +29,10 @@
{
public:
void HandleSendKey(CommandResponseHelper<SendKeyResponseType> & helper, const CecKeyCodeType & keyCode) override;
+
+ uint32_t GetFeatureMap(chip::EndpointId endpoint) override;
+
+private:
+ // TODO: set this based upon meta data from app
+ uint32_t mDynamicEndpointFeatureMap = 7;
};
diff --git a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp
index 9e26f9a..d080b9e 100644
--- a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp
+++ b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp
@@ -16,6 +16,7 @@
*/
#include "MediaPlaybackManager.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
using namespace std;
using namespace chip::app::DataModel;
@@ -236,3 +237,15 @@
response.status = MediaPlaybackStatusEnum::kSuccess;
helper.Success(response);
}
+
+uint32_t MediaPlaybackManager::GetFeatureMap(chip::EndpointId endpoint)
+{
+ if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT)
+ {
+ return mDynamicEndpointFeatureMap;
+ }
+
+ uint32_t featureMap = 0;
+ Attributes::FeatureMap::Get(endpoint, &featureMap);
+ return featureMap;
+}
diff --git a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h
index 1c35764..ec02313 100644
--- a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h
+++ b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h
@@ -51,6 +51,8 @@
void HandleNext(CommandResponseHelper<PlaybackResponseType> & helper) override;
void HandleStartOver(CommandResponseHelper<PlaybackResponseType> & helper) override;
+ uint32_t GetFeatureMap(chip::EndpointId endpoint) override;
+
protected:
// NOTE: it does not make sense to have default state of playing with a speed of 0, but
// the CI test cases expect these values, and need to be fixed.
@@ -64,4 +66,8 @@
static const int kPlaybackMaxForwardSpeed = 10;
static const int kPlaybackMaxRewindSpeed = -10;
+
+private:
+ // TODO: set this based upon meta data from app
+ uint32_t mDynamicEndpointFeatureMap = 3;
};
diff --git a/src/app/clusters/channel-server/channel-delegate.h b/src/app/clusters/channel-server/channel-delegate.h
index 4845858..60f5aba 100644
--- a/src/app/clusters/channel-server/channel-delegate.h
+++ b/src/app/clusters/channel-server/channel-delegate.h
@@ -44,6 +44,9 @@
virtual bool HandleChangeChannelByNumber(const uint16_t & majorNumber, const uint16_t & minorNumber) = 0;
virtual bool HandleSkipChannel(const uint16_t & count) = 0;
+ bool HasFeature(chip::EndpointId endpoint, ChannelFeature feature);
+ virtual uint32_t GetFeatureMap(chip::EndpointId endpoint) = 0;
+
virtual ~Delegate() = default;
};
diff --git a/src/app/clusters/channel-server/channel-server.cpp b/src/app/clusters/channel-server/channel-server.cpp
index fab495d..453b019 100644
--- a/src/app/clusters/channel-server/channel-server.cpp
+++ b/src/app/clusters/channel-server/channel-server.cpp
@@ -115,18 +115,10 @@
}
}
-bool HasFeature(chip::EndpointId endpoint, ChannelFeature feature)
+bool Delegate::HasFeature(chip::EndpointId endpoint, ChannelFeature feature)
{
- bool hasFeature = false;
- uint32_t featureMap = 0;
-
- EmberAfStatus status = Attributes::FeatureMap::Get(endpoint, &featureMap);
- if (EMBER_ZCL_STATUS_SUCCESS == status)
- {
- hasFeature = (featureMap & chip::to_underlying(feature));
- }
-
- return hasFeature;
+ uint32_t featureMap = GetFeatureMap(endpoint);
+ return (featureMap & chip::to_underlying(feature));
}
} // namespace Channel
@@ -150,6 +142,7 @@
CHIP_ERROR ReadChannelListAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate);
CHIP_ERROR ReadLineupAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate);
CHIP_ERROR ReadCurrentChannelAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate);
+ CHIP_ERROR ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, Delegate * delegate);
};
ChannelAttrAccess gChannelAttrAccess;
@@ -162,7 +155,7 @@
switch (aPath.mAttributeId)
{
case app::Clusters::Channel::Attributes::ChannelList::Id: {
- if (isDelegateNull(delegate, endpoint) || !HasFeature(endpoint, ChannelFeature::kChannelList))
+ if (isDelegateNull(delegate, endpoint) || !delegate->HasFeature(endpoint, ChannelFeature::kChannelList))
{
return aEncoder.EncodeEmptyList();
}
@@ -170,7 +163,7 @@
return ReadChannelListAttribute(aEncoder, delegate);
}
case app::Clusters::Channel::Attributes::Lineup::Id: {
- if (isDelegateNull(delegate, endpoint) || !HasFeature(endpoint, ChannelFeature::kLineupInfo))
+ if (isDelegateNull(delegate, endpoint) || !delegate->HasFeature(endpoint, ChannelFeature::kLineupInfo))
{
return CHIP_NO_ERROR;
}
@@ -185,6 +178,14 @@
return ReadCurrentChannelAttribute(aEncoder, delegate);
}
+ case app::Clusters::Channel::Attributes::FeatureMap::Id: {
+ if (isDelegateNull(delegate, endpoint))
+ {
+ return CHIP_NO_ERROR;
+ }
+
+ return ReadFeatureFlagAttribute(endpoint, aEncoder, delegate);
+ }
default: {
break;
}
@@ -193,6 +194,13 @@
return CHIP_NO_ERROR;
}
+CHIP_ERROR ChannelAttrAccess::ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder,
+ Delegate * delegate)
+{
+ uint32_t featureFlag = delegate->GetFeatureMap(endpoint);
+ return aEncoder.Encode(featureFlag);
+}
+
CHIP_ERROR ChannelAttrAccess::ReadChannelListAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate)
{
return delegate->HandleGetChannelList(aEncoder);
diff --git a/src/app/clusters/content-launch-server/content-launch-delegate.h b/src/app/clusters/content-launch-server/content-launch-delegate.h
index 5fb6e02..0c0f65d 100644
--- a/src/app/clusters/content-launch-server/content-launch-delegate.h
+++ b/src/app/clusters/content-launch-server/content-launch-delegate.h
@@ -51,6 +51,9 @@
virtual uint32_t HandleGetSupportedStreamingProtocols() = 0;
+ bool HasFeature(chip::EndpointId endpoint, ContentLauncherFeature feature);
+ virtual uint32_t GetFeatureMap(chip::EndpointId endpoint) = 0;
+
virtual ~Delegate() = default;
};
diff --git a/src/app/clusters/content-launch-server/content-launch-server.cpp b/src/app/clusters/content-launch-server/content-launch-server.cpp
index 7722480..3cbeea1 100644
--- a/src/app/clusters/content-launch-server/content-launch-server.cpp
+++ b/src/app/clusters/content-launch-server/content-launch-server.cpp
@@ -120,18 +120,10 @@
}
}
-bool HasFeature(chip::EndpointId endpoint, ContentLauncherFeature feature)
+bool Delegate::HasFeature(chip::EndpointId endpoint, ContentLauncherFeature feature)
{
- bool hasFeature = false;
- uint32_t featureMap = 0;
-
- EmberAfStatus status = Attributes::FeatureMap::Get(endpoint, &featureMap);
- if (EMBER_ZCL_STATUS_SUCCESS == status)
- {
- hasFeature = (featureMap & chip::to_underlying(feature));
- }
-
- return hasFeature;
+ uint32_t featureMap = GetFeatureMap(endpoint);
+ return (featureMap & chip::to_underlying(feature));
}
} // namespace ContentLauncher
@@ -154,6 +146,7 @@
private:
CHIP_ERROR ReadAcceptHeaderAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate);
CHIP_ERROR ReadSupportedStreamingProtocolsAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate);
+ CHIP_ERROR ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, Delegate * delegate);
};
ContentLauncherAttrAccess gContentLauncherAttrAccess;
@@ -181,6 +174,14 @@
return ReadSupportedStreamingProtocolsAttribute(aEncoder, delegate);
}
+ case app::Clusters::ContentLauncher::Attributes::FeatureMap::Id: {
+ if (isDelegateNull(delegate, endpoint))
+ {
+ return CHIP_NO_ERROR;
+ }
+
+ return ReadFeatureFlagAttribute(endpoint, aEncoder, delegate);
+ }
default: {
break;
}
@@ -189,6 +190,13 @@
return CHIP_NO_ERROR;
}
+CHIP_ERROR ContentLauncherAttrAccess::ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder,
+ Delegate * delegate)
+{
+ uint32_t featureFlag = delegate->GetFeatureMap(endpoint);
+ return aEncoder.Encode(featureFlag);
+}
+
CHIP_ERROR ContentLauncherAttrAccess::ReadAcceptHeaderAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate)
{
return delegate->HandleGetAcceptHeaderList(aEncoder);
@@ -220,7 +228,8 @@
Delegate * delegate = GetDelegate(endpoint);
- VerifyOrExit(isDelegateNull(delegate, endpoint) != true && HasFeature(endpoint, ContentLauncherFeature::kContentSearch),
+ VerifyOrExit(isDelegateNull(delegate, endpoint) != true &&
+ delegate->HasFeature(endpoint, ContentLauncherFeature::kContentSearch),
err = CHIP_ERROR_INCORRECT_STATE);
delegate->HandleLaunchContent(responder, decodableParameterList, autoplay, data.HasValue() ? data.Value() : CharSpan());
@@ -253,7 +262,7 @@
app::CommandResponseHelper<Commands::LaunchResponse::Type> responder(commandObj, commandPath);
Delegate * delegate = GetDelegate(endpoint);
- VerifyOrExit(isDelegateNull(delegate, endpoint) != true && HasFeature(endpoint, ContentLauncherFeature::kURLPlayback),
+ VerifyOrExit(isDelegateNull(delegate, endpoint) != true && delegate->HasFeature(endpoint, ContentLauncherFeature::kURLPlayback),
err = CHIP_ERROR_INCORRECT_STATE);
{
delegate->HandleLaunchUrl(responder, contentUrl, displayString.HasValue() ? displayString.Value() : CharSpan(),
diff --git a/src/app/clusters/keypad-input-server/keypad-input-delegate.h b/src/app/clusters/keypad-input-server/keypad-input-delegate.h
index 24fd575..65e217b 100644
--- a/src/app/clusters/keypad-input-server/keypad-input-delegate.h
+++ b/src/app/clusters/keypad-input-server/keypad-input-delegate.h
@@ -36,6 +36,10 @@
public:
virtual void HandleSendKey(CommandResponseHelper<Commands::SendKeyResponse::Type> & helper, const CecKeyCode & keyCode) = 0;
+ bool HasFeature(chip::EndpointId endpoint, KeypadInputFeature feature);
+
+ virtual uint32_t GetFeatureMap(chip::EndpointId endpoint) = 0;
+
virtual ~Delegate() = default;
};
diff --git a/src/app/clusters/keypad-input-server/keypad-input-server.cpp b/src/app/clusters/keypad-input-server/keypad-input-server.cpp
index 1389caa..2dce476 100644
--- a/src/app/clusters/keypad-input-server/keypad-input-server.cpp
+++ b/src/app/clusters/keypad-input-server/keypad-input-server.cpp
@@ -25,12 +25,15 @@
#include <app/clusters/keypad-input-server/keypad-input-server.h>
#include <app-common/zap-generated/attributes/Accessors.h>
+#include <app/AttributeAccessInterface.h>
#include <app/CommandHandler.h>
#include <app/ConcreteCommandPath.h>
#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
#include <app/app-platform/ContentAppPlatform.h>
#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
#include <app/data-model/Encode.h>
+#include <app/util/af.h>
+#include <app/util/attribute-storage.h>
#include <platform/CHIPDeviceConfig.h>
using namespace chip;
@@ -97,18 +100,10 @@
}
}
-bool HasFeature(chip::EndpointId endpoint, KeypadInputFeature feature)
+bool Delegate::HasFeature(chip::EndpointId endpoint, KeypadInputFeature feature)
{
- bool hasFeature = false;
- uint32_t featureMap = 0;
-
- EmberAfStatus status = Attributes::FeatureMap::Get(endpoint, &featureMap);
- if (EMBER_ZCL_STATUS_SUCCESS == status)
- {
- hasFeature = (featureMap & chip::to_underlying(feature));
- }
-
- return hasFeature;
+ uint32_t featureMap = GetFeatureMap(endpoint);
+ return (featureMap & chip::to_underlying(feature));
}
} // namespace KeypadInput
@@ -117,6 +112,57 @@
} // namespace chip
// -----------------------------------------------------------------------------
+// Attribute Accessor Implementation
+
+namespace {
+
+class KeypadInputAttrAccess : public app::AttributeAccessInterface
+{
+public:
+ KeypadInputAttrAccess() : app::AttributeAccessInterface(Optional<EndpointId>::Missing(), KeypadInput::Id) {}
+
+ CHIP_ERROR Read(const app::ConcreteReadAttributePath & aPath, app::AttributeValueEncoder & aEncoder) override;
+
+private:
+ CHIP_ERROR ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, Delegate * delegate);
+};
+
+KeypadInputAttrAccess gKeypadInputAttrAccess;
+
+CHIP_ERROR KeypadInputAttrAccess::Read(const app::ConcreteReadAttributePath & aPath, app::AttributeValueEncoder & aEncoder)
+{
+ EndpointId endpoint = aPath.mEndpointId;
+ Delegate * delegate = GetDelegate(endpoint);
+
+ if (isDelegateNull(delegate, endpoint))
+ {
+ return CHIP_NO_ERROR;
+ }
+
+ switch (aPath.mAttributeId)
+ {
+ case app::Clusters::KeypadInput::Attributes::FeatureMap::Id: {
+ return ReadFeatureFlagAttribute(endpoint, aEncoder, delegate);
+ }
+
+ default: {
+ break;
+ }
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR KeypadInputAttrAccess::ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder,
+ Delegate * delegate)
+{
+ uint32_t featureFlag = delegate->GetFeatureMap(endpoint);
+ return aEncoder.Encode(featureFlag);
+}
+
+} // anonymous namespace
+
+// -----------------------------------------------------------------------------
// Matter Framework Callbacks Implementation
bool emberAfKeypadInputClusterSendKeyCallback(app::CommandHandler * command, const app::ConcreteCommandPath & commandPath,
@@ -142,4 +188,7 @@
return true;
}
-void MatterKeypadInputPluginServerInitCallback() {}
+void MatterKeypadInputPluginServerInitCallback()
+{
+ registerAttributeAccessOverride(&gKeypadInputAttrAccess);
+}
diff --git a/src/app/clusters/media-playback-server/media-playback-delegate.h b/src/app/clusters/media-playback-server/media-playback-delegate.h
index b5e64d3..64b85b8 100644
--- a/src/app/clusters/media-playback-server/media-playback-delegate.h
+++ b/src/app/clusters/media-playback-server/media-playback-delegate.h
@@ -59,6 +59,8 @@
virtual void HandleNext(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper) = 0;
virtual void HandleStartOver(CommandResponseHelper<Commands::PlaybackResponse::Type> & helper) = 0;
+ virtual uint32_t GetFeatureMap(chip::EndpointId endpoint) = 0;
+
virtual ~Delegate() = default;
};
diff --git a/src/app/clusters/media-playback-server/media-playback-server.cpp b/src/app/clusters/media-playback-server/media-playback-server.cpp
index 1c43463..c4ae274 100644
--- a/src/app/clusters/media-playback-server/media-playback-server.cpp
+++ b/src/app/clusters/media-playback-server/media-playback-server.cpp
@@ -25,6 +25,7 @@
#include <app/clusters/media-playback-server/media-playback-delegate.h>
#include <app/clusters/media-playback-server/media-playback-server.h>
+#include <app-common/zap-generated/attributes/Accessors.h>
#include <app/AttributeAccessInterface.h>
#include <app/CommandHandler.h>
#include <app/ConcreteCommandPath.h>
@@ -124,6 +125,7 @@
CHIP_ERROR ReadPlaybackSpeedAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate);
CHIP_ERROR ReadSeekRangeStartAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate);
CHIP_ERROR ReadSeekRangeEndAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate);
+ CHIP_ERROR ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, Delegate * delegate);
};
MediaPlaybackAttrAccess gMediaPlaybackAttrAccess;
@@ -161,6 +163,9 @@
case app::Clusters::MediaPlayback::Attributes::SeekRangeEnd::Id: {
return ReadSeekRangeEndAttribute(aEncoder, delegate);
}
+ case app::Clusters::ContentLauncher::Attributes::FeatureMap::Id: {
+ return ReadFeatureFlagAttribute(endpoint, aEncoder, delegate);
+ }
default: {
break;
}
@@ -169,6 +174,13 @@
return CHIP_NO_ERROR;
}
+CHIP_ERROR MediaPlaybackAttrAccess::ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder,
+ Delegate * delegate)
+{
+ uint32_t featureFlag = delegate->GetFeatureMap(endpoint);
+ return aEncoder.Encode(featureFlag);
+}
+
CHIP_ERROR MediaPlaybackAttrAccess::ReadCurrentStateAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate)
{
MediaPlayback::PlaybackStateEnum currentState = delegate->HandleGetCurrentState();