Skip to content

Commit 2620834

Browse files
yhoyoonpull[bot]
authored andcommitted
[Android] Support FabricFilter to ChipClusters API (#28208)
* [Android] Support FabricFilter to ChipClusters API This change adds a version that allows users to set FabricFilter options to APIs that read Attribute, which is Fabric-Scoped List. For example, - OperationalCredentialsCluster.readFabricsAttribute - OperationalCredentialsCluster.readFabricsAttributeWithFabricFilter In the existing API, FabricFilter was hard-coded with true value. So, there was no way to read all fabric information of the attribute on the PASE Session before the Android commissioner completed commissioning of the device. New API provides a FabricFilter parameter. So, before the Android commissioner completes device commissioning, all fabric information of the corresponding attribute can be read based on PASE Session. Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Fix unit test errors Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Fix the templates to not add extra whitespace Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Restore empty line of end of file Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Add unit test for FabricFilter Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> * Remove new apis in ClusterReadMapping Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com> --------- Signed-off-by: Youngho Yoon <34558998+yhoyoon@users.noreply.github.com>
1 parent 9f07592 commit 2620834

File tree

13 files changed

+241
-16
lines changed

13 files changed

+241
-16
lines changed

scripts/py_matter_idl/matter_idl/generators/java/ChipClustersRead.jinja

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
extern "C" JNIEXPORT RETURN JNICALL Java_chip_devicecontroller_ChipClusters_00024##CLASS_NAME##_##METHOD_NAME
2828

2929
{%- for attr in cluster.attributes | attributesWithCallback(typeLookup) %}
30-
JNI_METHOD(void, {{cluster.name | capitalcase}}Cluster, read{{attr.definition.name | capitalcase}}Attribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback)
30+
JNI_METHOD(void, {{cluster.name | capitalcase}}Cluster, read{{attr.definition.name | capitalcase}}Attribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback{% if attr | isFabricScopedList(typeLookup) %}, jboolean isFabricFiltered{% endif %})
3131
{
3232
chip::DeviceLayer::StackLock lock;
3333
using TypeInfo = chip::app::Clusters::{{cluster.name | capitalcase}}::Attributes::{{attr.definition.name | capitalcase}}::TypeInfo;
@@ -44,7 +44,7 @@ JNI_METHOD(void, {{cluster.name | capitalcase}}Cluster, read{{attr.definition.na
4444

4545
auto successFn = chip::Callback::Callback<CHIP{{cluster.name | capitalcase}}Cluster{{attr.definition.name | capitalcase}}AttributeCallbackType>::FromCancelable(onSuccess->Cancel());
4646
auto failureFn = chip::Callback::Callback<CHIPDefaultFailureCallbackType>::FromCancelable(onFailure->Cancel());
47-
err = cppCluster->ReadAttribute<TypeInfo>(onSuccess->mContext, successFn->mCall, failureFn->mCall);
47+
err = cppCluster->ReadAttribute<TypeInfo>(onSuccess->mContext, successFn->mCall, failureFn->mCall{% if attr | isFabricScopedList(typeLookup) %}, isFabricFiltered{% endif %});
4848
VerifyOrReturn(err == CHIP_NO_ERROR, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error reading attribute", err));
4949

5050
onSuccess.release();

scripts/py_matter_idl/matter_idl/generators/java/__init__.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from matter_idl.generators.types import (BasicInteger, BasicString, FundamentalType, IdlBitmapType, IdlEnumType, IdlType,
2424
ParseDataType, TypeLookupContext)
2525
from matter_idl.matter_idl_types import (Attribute, Cluster, ClusterSide, Command, DataType, Field, FieldQuality, Idl, Struct,
26-
StructTag)
26+
StructQuality, StructTag)
2727
from stringcase import capitalcase
2828

2929

@@ -601,6 +601,14 @@ def CanGenerateSubscribe(attr: Attribute, lookup: TypeLookupContext) -> bool:
601601
return not lookup.is_struct_type(attr.definition.data_type.name)
602602

603603

604+
def IsFabricScopedList(attr: Attribute, lookup: TypeLookupContext) -> bool:
605+
if not attr.definition.is_list:
606+
return False
607+
608+
struct = lookup.find_struct(attr.definition.data_type.name)
609+
return struct and struct.qualities == StructQuality.FABRIC_SCOPED
610+
611+
604612
def IsResponseStruct(s: Struct) -> bool:
605613
return s.tag == StructTag.RESPONSE
606614

@@ -632,6 +640,7 @@ def __init__(self, storage: GeneratorStorage, idl: Idl, **kargs):
632640
self.jinja_env.filters['createLookupContext'] = CreateLookupContext
633641
self.jinja_env.filters['canGenerateSubscribe'] = CanGenerateSubscribe
634642
self.jinja_env.filters['decodableJniType'] = DecodableJniType
643+
self.jinja_env.filters['isFabricScopedList'] = IsFabricScopedList
635644

636645
self.jinja_env.tests['is_response_struct'] = IsResponseStruct
637646
self.jinja_env.tests['is_using_global_callback'] = _IsUsingGlobalCallback

scripts/py_matter_idl/matter_idl/test_generators.py

+1
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ def build_tests(yaml_data) -> List[GeneratorTest]:
164164

165165
class TestGenerators(unittest.TestCase):
166166
def test_generators(self):
167+
self.maxDiff = None
167168
with open(os.path.join(TESTS_DIR, "available_tests.yaml"), 'rt') as stream:
168169
yaml_data = yaml.safe_load(stream)
169170

scripts/py_matter_idl/matter_idl/tests/inputs/several_clusters.matter

+10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@ client cluster First = 1 {
33
}
44

55
client cluster Second = 2 {
6+
fabric_scoped struct FabricDescriptorStruct {
7+
octet_string<65> rootPublicKey = 1;
8+
vendor_id vendorID = 2;
9+
fabric_id fabricID = 3;
10+
node_id nodeID = 4;
11+
char_string<32> label = 5;
12+
fabric_idx fabricIndex = 254;
13+
}
14+
15+
readonly attribute FabricDescriptorStruct fabrics[] = 0;
616
readonly attribute octet_string<32> someBytes = 123;
717
}
818

scripts/py_matter_idl/matter_idl/tests/outputs/proto/second_cluster.proto

+26
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,33 @@ message SecondCluster {
1515
CLUSTER_ID = 2;
1616
}
1717

18+
// Structs
19+
message FabricDescriptorStruct {
20+
/** octet_string Type: 5 IsList: 0 FieldId: 1 */
21+
bytes root_public_key = 2621441;
22+
/** vendor_id Type: 1 IsList: 0 FieldId: 2 */
23+
uint32 vendor_id = 524290;
24+
/** fabric_id Type: 1 IsList: 0 FieldId: 3 */
25+
uint64 fabric_id = 524291;
26+
/** node_id Type: 1 IsList: 0 FieldId: 4 */
27+
uint64 node_id = 524292;
28+
/** char_string Type: 4 IsList: 0 FieldId: 5 */
29+
string label = 2097157;
30+
/** fabric_idx Type: 1 IsList: 0 FieldId: 254 */
31+
uint32 fabric_index = 524542;
32+
}
33+
34+
1835
// Attributes
36+
/** FabricDescriptorStruct Type: 6 IsList: 1 FieldId: 0 */
37+
FabricDescriptorStruct fabrics = 3145728;
38+
/*
39+
[(attribute) = {
40+
is_subscribable: true,
41+
}];
42+
*/
43+
44+
1945
/** octet_string Type: 5 IsList: 0 FieldId: 123 */
2046
bytes some_bytes = 2621563;
2147
/*

scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/java/ClusterIDMapping.java

+1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ public long getID() {
140140
}
141141

142142
public enum Attribute {
143+
Fabrics(0L),
143144
SomeBytes(123L),;
144145
private final long id;
145146
Attribute(long id) {

scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/java/ClusterReadMapping.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,18 @@ private static Map<String, InteractionInfo> readFirstInteractionInfo() {
4141
return result;
4242
}
4343
private static Map<String, InteractionInfo> readSecondInteractionInfo() {
44-
Map<String, InteractionInfo> result = new LinkedHashMap<>();Map<String, CommandParameterInfo> readSecondSomeBytesCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
44+
Map<String, InteractionInfo> result = new LinkedHashMap<>();Map<String, CommandParameterInfo> readSecondFabricsCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
45+
InteractionInfo readSecondFabricsAttributeInteractionInfo = new InteractionInfo(
46+
(cluster, callback, commandArguments) -> {
47+
((ChipClusters.SecondCluster) cluster).readFabricsAttribute(
48+
(ChipClusters.SecondCluster.FabricsAttributeCallback) callback
49+
);
50+
},
51+
() -> new ClusterInfoMapping.DelegatedSecondClusterFabricsAttributeCallback(),
52+
readSecondFabricsCommandParams
53+
);
54+
result.put("readFabricsAttribute", readSecondFabricsAttributeInteractionInfo);
55+
Map<String, CommandParameterInfo> readSecondSomeBytesCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
4556
InteractionInfo readSecondSomeBytesAttributeInteractionInfo = new InteractionInfo(
4657
(cluster, callback, commandArguments) -> {
4758
((ChipClusters.SecondCluster) cluster).readSomeBytesAttribute(

scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/jni/CHIPCallbackTypes.h

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ typedef void (*CHIPDefaultFailureCallbackType)(void *, CHIP_ERROR);
2424

2525

2626
typedef void (*CHIPFirstClusterSomeIntegerAttributeCallbackType)(void *, chip::app::Clusters::First::Attributes::SomeInteger::TypeInfo::DecodableArgType);
27+
typedef void (*CHIPSecondClusterFabricsAttributeCallbackType)(void *, const chip::app::Clusters::Second::Attributes::Fabrics::TypeInfo::DecodableType &);
2728
typedef void (*CHIPSecondClusterSomeBytesAttributeCallbackType)(void *, chip::app::Clusters::Second::Attributes::SomeBytes::TypeInfo::DecodableArgType);
2829
typedef void (*CHIPThirdClusterSomeEnumAttributeCallbackType)(void *, chip::app::Clusters::Third::Attributes::SomeEnum::TypeInfo::DecodableArgType);
2930
typedef void (*CHIPThirdClusterOptionsAttributeCallbackType)(void *, chip::app::Clusters::Third::Attributes::Options::TypeInfo::DecodableArgType);

scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/jni/CHIPReadReadCallbacks.h

+26
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,32 @@ class CHIPOctetStringAttributeCallback : public chip::Callback::Callback<OctetSt
340340

341341

342342

343+
class CHIPSecondFabricsAttributeCallback : public chip::Callback::Callback<CHIPSecondClusterFabricsAttributeCallbackType>
344+
{
345+
public:
346+
CHIPSecondFabricsAttributeCallback(jobject javaCallback, bool keepAlive = false);
347+
348+
~CHIPSecondFabricsAttributeCallback();
349+
350+
static void maybeDestroy(CHIPSecondFabricsAttributeCallback * callback) {
351+
if (!callback->keepAlive) {
352+
callback->Cancel();
353+
chip::Platform::Delete<CHIPSecondFabricsAttributeCallback>(callback);
354+
}
355+
}
356+
357+
static void CallbackFn(void * context, const chip::app::DataModel::DecodableList<chip::app::Clusters::Second::Structs::FabricDescriptorStruct::DecodableType> & list);
358+
static void OnSubscriptionEstablished(void * context, chip::SubscriptionId subscriptionId) {
359+
CHIP_ERROR err = chip::JniReferences::GetInstance().CallSubscriptionEstablished(reinterpret_cast<CHIPSecondFabricsAttributeCallback *>(context)->javaCallbackRef, subscriptionId);
360+
VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error calling onSubscriptionEstablished: %s", ErrorStr(err)));
361+
};
362+
363+
private:
364+
jobject javaCallbackRef;
365+
bool keepAlive;
366+
};
367+
368+
343369

344370

345371
class CHIPThirdSomeEnumAttributeCallback : public chip::Callback::Callback<CHIPThirdClusterSomeEnumAttributeCallbackType>

scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/jni/SecondClient-InvokeSubscribeImpl.cpp

+22-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,28 @@ JNI_METHOD(jlong, SecondCluster, initWithDevice)(JNIEnv * env, jobject self, jlo
3434
return reinterpret_cast<jlong>(cppCluster);
3535
}
3636

37-
JNI_METHOD(void, SecondCluster, subscribeSomeBytesAttribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval)
37+
JNI_METHOD(void, SecondCluster, subscribeFabricsAttribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval)
38+
{
39+
chip::DeviceLayer::StackLock lock;std::unique_ptr<CHIPSecondFabricsAttributeCallback, void (*)(CHIPSecondFabricsAttributeCallback *)> onSuccess(Platform::New<CHIPSecondFabricsAttributeCallback>(callback, true), chip::Platform::Delete<CHIPSecondFabricsAttributeCallback>);
40+
VerifyOrReturn(onSuccess.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY));
41+
42+
std::unique_ptr<CHIPDefaultFailureCallback, void (*)(CHIPDefaultFailureCallback *)> onFailure(Platform::New<CHIPDefaultFailureCallback>(callback), chip::Platform::Delete<CHIPDefaultFailureCallback>);
43+
VerifyOrReturn(onFailure.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY));
44+
45+
CHIP_ERROR err = CHIP_NO_ERROR;
46+
ClusterBase * cppCluster = reinterpret_cast<ClusterBase *>(clusterPtr);
47+
VerifyOrReturn(cppCluster != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE));
48+
49+
using TypeInfo = chip::app::Clusters::Second::Attributes::Fabrics::TypeInfo;
50+
auto successFn = chip::Callback::Callback<CHIPSecondClusterFabricsAttributeCallbackType>::FromCancelable(onSuccess->Cancel());
51+
auto failureFn = chip::Callback::Callback<CHIPDefaultFailureCallbackType>::FromCancelable(onFailure->Cancel());
52+
53+
err = cppCluster->SubscribeAttribute<TypeInfo>(onSuccess->mContext, successFn->mCall, failureFn->mCall, static_cast<uint16_t>(minInterval), static_cast<uint16_t>(maxInterval), CHIPSecondFabricsAttributeCallback::OnSubscriptionEstablished);
54+
VerifyOrReturn(err == CHIP_NO_ERROR, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error subscribing to attribute", err));
55+
56+
onSuccess.release();
57+
onFailure.release();
58+
}JNI_METHOD(void, SecondCluster, subscribeSomeBytesAttribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval)
3859
{
3960
chip::DeviceLayer::StackLock lock;std::unique_ptr<CHIPOctetStringAttributeCallback, void (*)(CHIPOctetStringAttributeCallback *)> onSuccess(Platform::New<CHIPOctetStringAttributeCallback>(callback, true), chip::Platform::Delete<CHIPOctetStringAttributeCallback>);
4061
VerifyOrReturn(onSuccess.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY));

scripts/py_matter_idl/matter_idl/tests/outputs/several_clusters/jni/SecondClient-ReadImpl.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,30 @@
1212

1313
#define JNI_METHOD(RETURN, CLASS_NAME, METHOD_NAME) \
1414
extern "C" JNIEXPORT RETURN JNICALL Java_chip_devicecontroller_ChipClusters_00024##CLASS_NAME##_##METHOD_NAME
15+
JNI_METHOD(void, SecondCluster, readFabricsAttribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jboolean isFabricFiltered)
16+
{
17+
chip::DeviceLayer::StackLock lock;
18+
using TypeInfo = chip::app::Clusters::Second::Attributes::Fabrics::TypeInfo;
19+
std::unique_ptr<CHIPSecondFabricsAttributeCallback, void (*)(CHIPSecondFabricsAttributeCallback *)> onSuccess(chip::Platform::New<CHIPSecondFabricsAttributeCallback>(callback, false), chip::Platform::Delete<CHIPSecondFabricsAttributeCallback>);
20+
VerifyOrReturn(onSuccess.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY));
21+
22+
std::unique_ptr<chip::CHIPDefaultFailureCallback, void (*)(chip::CHIPDefaultFailureCallback *)> onFailure(chip::Platform::New<chip::CHIPDefaultFailureCallback>(callback), chip::Platform::Delete<chip::CHIPDefaultFailureCallback>);
23+
VerifyOrReturn(onFailure.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY));
24+
25+
CHIP_ERROR err = CHIP_NO_ERROR;
26+
chip::Controller::ClusterBase * cppCluster = reinterpret_cast<chip::Controller::ClusterBase *>(clusterPtr);
27+
VerifyOrReturn(cppCluster != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE));
28+
29+
auto successFn = chip::Callback::Callback<CHIPSecondClusterFabricsAttributeCallbackType>::FromCancelable(onSuccess->Cancel());
30+
auto failureFn = chip::Callback::Callback<CHIPDefaultFailureCallbackType>::FromCancelable(onFailure->Cancel());
31+
err = cppCluster->ReadAttribute<TypeInfo>(onSuccess->mContext, successFn->mCall, failureFn->mCall, isFabricFiltered);
32+
VerifyOrReturn(err == CHIP_NO_ERROR, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error reading attribute", err));
33+
34+
onSuccess.release();
35+
onFailure.release();
36+
}
37+
38+
1539
JNI_METHOD(void, SecondCluster, readSomeBytesAttribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback)
1640
{
1741
chip::DeviceLayer::StackLock lock;

src/controller/java/templates/ChipClusters-java.zapt

+16-1
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,20 @@ public class ChipClusters {
181181
{{asUpperCamelCase name}}AttributeCallback callback
182182
{{/if_basic_attribute}}
183183
) {
184-
read{{asUpperCamelCase name}}Attribute(chipClusterPtr, callback);
184+
read{{asUpperCamelCase name}}Attribute(chipClusterPtr, callback{{#if_is_fabric_scoped_struct type}}, true{{/if_is_fabric_scoped_struct}});
185185
}
186+
{{#if_is_fabric_scoped_struct type}}
187+
public void read{{asUpperCamelCase name}}AttributeWithFabricFilter(
188+
{{#if_basic_attribute type ../id}}
189+
{{as_underlying_java_zcl_type type ../id boolean="Boolean"}}AttributeCallback callback
190+
{{else}}
191+
{{asUpperCamelCase name}}AttributeCallback callback
192+
{{/if_basic_attribute}},
193+
boolean isFabricFiltered
194+
) {
195+
read{{asUpperCamelCase name}}Attribute(chipClusterPtr, callback, isFabricFiltered);
196+
}
197+
{{/if_is_fabric_scoped_struct}}
186198
{{#if isWritableAttribute}}
187199
{{#unless mustUseTimedWrite}}
188200
public void write{{asUpperCamelCase name}}Attribute(DefaultClusterCallback callback, {{asJavaType type chipType parent.name}} value) {
@@ -218,6 +230,9 @@ public class ChipClusters {
218230
{{else}}
219231
{{asUpperCamelCase name}}AttributeCallback callback
220232
{{/if_basic_attribute}}
233+
{{#if_is_fabric_scoped_struct type}}
234+
, boolean isFabricFiltered
235+
{{/if_is_fabric_scoped_struct}}
221236
);
222237
{{#if isWritableAttribute}}
223238

0 commit comments

Comments
 (0)