Skip to content

Commit

Permalink
[Android] Support FabricFilter to ChipClusters API (#28208)
Browse files Browse the repository at this point in the history
* [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 <[email protected]>

* Fix unit test errors

Signed-off-by: Youngho Yoon <[email protected]>

* Fix the templates to not add extra whitespace

Signed-off-by: Youngho Yoon <[email protected]>

* Restore empty line of end of file

Signed-off-by: Youngho Yoon <[email protected]>

* Add unit test for FabricFilter

Signed-off-by: Youngho Yoon <[email protected]>

* Remove new apis in ClusterReadMapping

Signed-off-by: Youngho Yoon <[email protected]>

---------

Signed-off-by: Youngho Yoon <[email protected]>
  • Loading branch information
yhoyoon authored and pull[bot] committed Sep 19, 2023
1 parent 639458e commit 2219154
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
extern "C" JNIEXPORT RETURN JNICALL Java_chip_devicecontroller_ChipClusters_00024##CLASS_NAME##_##METHOD_NAME

{%- for attr in cluster.attributes | attributesWithCallback(typeLookup) %}
JNI_METHOD(void, {{cluster.name | capitalcase}}Cluster, read{{attr.definition.name | capitalcase}}Attribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback)
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 %})
{
chip::DeviceLayer::StackLock lock;
using TypeInfo = chip::app::Clusters::{{cluster.name | capitalcase}}::Attributes::{{attr.definition.name | capitalcase}}::TypeInfo;
Expand All @@ -44,7 +44,7 @@ JNI_METHOD(void, {{cluster.name | capitalcase}}Cluster, read{{attr.definition.na

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

onSuccess.release();
Expand Down
11 changes: 10 additions & 1 deletion scripts/py_matter_idl/matter_idl/generators/java/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from matter_idl.generators.types import (BasicInteger, BasicString, FundamentalType, IdlBitmapType, IdlEnumType, IdlType,
ParseDataType, TypeLookupContext)
from matter_idl.matter_idl_types import (Attribute, Cluster, ClusterSide, Command, DataType, Field, FieldQuality, Idl, Struct,
StructTag)
StructQuality, StructTag)
from stringcase import capitalcase


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


def IsFabricScopedList(attr: Attribute, lookup: TypeLookupContext) -> bool:
if not attr.definition.is_list:
return False

struct = lookup.find_struct(attr.definition.data_type.name)
return struct and struct.qualities == StructQuality.FABRIC_SCOPED


def IsResponseStruct(s: Struct) -> bool:
return s.tag == StructTag.RESPONSE

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

self.jinja_env.tests['is_response_struct'] = IsResponseStruct
self.jinja_env.tests['is_using_global_callback'] = _IsUsingGlobalCallback
Expand Down
1 change: 1 addition & 0 deletions scripts/py_matter_idl/matter_idl/test_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ def build_tests(yaml_data) -> List[GeneratorTest]:

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ client cluster First = 1 {
}

client cluster Second = 2 {
fabric_scoped struct FabricDescriptorStruct {
octet_string<65> rootPublicKey = 1;
vendor_id vendorID = 2;
fabric_id fabricID = 3;
node_id nodeID = 4;
char_string<32> label = 5;
fabric_idx fabricIndex = 254;
}

readonly attribute FabricDescriptorStruct fabrics[] = 0;
readonly attribute octet_string<32> someBytes = 123;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,33 @@ message SecondCluster {
CLUSTER_ID = 2;
}

// Structs
message FabricDescriptorStruct {
/** octet_string Type: 5 IsList: 0 FieldId: 1 */
bytes root_public_key = 2621441;
/** vendor_id Type: 1 IsList: 0 FieldId: 2 */
uint32 vendor_id = 524290;
/** fabric_id Type: 1 IsList: 0 FieldId: 3 */
uint64 fabric_id = 524291;
/** node_id Type: 1 IsList: 0 FieldId: 4 */
uint64 node_id = 524292;
/** char_string Type: 4 IsList: 0 FieldId: 5 */
string label = 2097157;
/** fabric_idx Type: 1 IsList: 0 FieldId: 254 */
uint32 fabric_index = 524542;
}


// Attributes
/** FabricDescriptorStruct Type: 6 IsList: 1 FieldId: 0 */
FabricDescriptorStruct fabrics = 3145728;
/*
[(attribute) = {
is_subscribable: true,
}];
*/


/** octet_string Type: 5 IsList: 0 FieldId: 123 */
bytes some_bytes = 2621563;
/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ public long getID() {
}

public enum Attribute {
Fabrics(0L),
SomeBytes(123L),;
private final long id;
Attribute(long id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,18 @@ private static Map<String, InteractionInfo> readFirstInteractionInfo() {
return result;
}
private static Map<String, InteractionInfo> readSecondInteractionInfo() {
Map<String, InteractionInfo> result = new LinkedHashMap<>();Map<String, CommandParameterInfo> readSecondSomeBytesCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
Map<String, InteractionInfo> result = new LinkedHashMap<>();Map<String, CommandParameterInfo> readSecondFabricsCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
InteractionInfo readSecondFabricsAttributeInteractionInfo = new InteractionInfo(
(cluster, callback, commandArguments) -> {
((ChipClusters.SecondCluster) cluster).readFabricsAttribute(
(ChipClusters.SecondCluster.FabricsAttributeCallback) callback
);
},
() -> new ClusterInfoMapping.DelegatedSecondClusterFabricsAttributeCallback(),
readSecondFabricsCommandParams
);
result.put("readFabricsAttribute", readSecondFabricsAttributeInteractionInfo);
Map<String, CommandParameterInfo> readSecondSomeBytesCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
InteractionInfo readSecondSomeBytesAttributeInteractionInfo = new InteractionInfo(
(cluster, callback, commandArguments) -> {
((ChipClusters.SecondCluster) cluster).readSomeBytesAttribute(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ typedef void (*CHIPDefaultFailureCallbackType)(void *, CHIP_ERROR);


typedef void (*CHIPFirstClusterSomeIntegerAttributeCallbackType)(void *, chip::app::Clusters::First::Attributes::SomeInteger::TypeInfo::DecodableArgType);
typedef void (*CHIPSecondClusterFabricsAttributeCallbackType)(void *, const chip::app::Clusters::Second::Attributes::Fabrics::TypeInfo::DecodableType &);
typedef void (*CHIPSecondClusterSomeBytesAttributeCallbackType)(void *, chip::app::Clusters::Second::Attributes::SomeBytes::TypeInfo::DecodableArgType);
typedef void (*CHIPThirdClusterSomeEnumAttributeCallbackType)(void *, chip::app::Clusters::Third::Attributes::SomeEnum::TypeInfo::DecodableArgType);
typedef void (*CHIPThirdClusterOptionsAttributeCallbackType)(void *, chip::app::Clusters::Third::Attributes::Options::TypeInfo::DecodableArgType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,32 @@ class CHIPOctetStringAttributeCallback : public chip::Callback::Callback<OctetSt



class CHIPSecondFabricsAttributeCallback : public chip::Callback::Callback<CHIPSecondClusterFabricsAttributeCallbackType>
{
public:
CHIPSecondFabricsAttributeCallback(jobject javaCallback, bool keepAlive = false);

~CHIPSecondFabricsAttributeCallback();

static void maybeDestroy(CHIPSecondFabricsAttributeCallback * callback) {
if (!callback->keepAlive) {
callback->Cancel();
chip::Platform::Delete<CHIPSecondFabricsAttributeCallback>(callback);
}
}

static void CallbackFn(void * context, const chip::app::DataModel::DecodableList<chip::app::Clusters::Second::Structs::FabricDescriptorStruct::DecodableType> & list);
static void OnSubscriptionEstablished(void * context, chip::SubscriptionId subscriptionId) {
CHIP_ERROR err = chip::JniReferences::GetInstance().CallSubscriptionEstablished(reinterpret_cast<CHIPSecondFabricsAttributeCallback *>(context)->javaCallbackRef, subscriptionId);
VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Zcl, "Error calling onSubscriptionEstablished: %s", ErrorStr(err)));
};

private:
jobject javaCallbackRef;
bool keepAlive;
};




class CHIPThirdSomeEnumAttributeCallback : public chip::Callback::Callback<CHIPThirdClusterSomeEnumAttributeCallbackType>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,28 @@ JNI_METHOD(jlong, SecondCluster, initWithDevice)(JNIEnv * env, jobject self, jlo
return reinterpret_cast<jlong>(cppCluster);
}

JNI_METHOD(void, SecondCluster, subscribeSomeBytesAttribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval)
JNI_METHOD(void, SecondCluster, subscribeFabricsAttribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval)
{
chip::DeviceLayer::StackLock lock;std::unique_ptr<CHIPSecondFabricsAttributeCallback, void (*)(CHIPSecondFabricsAttributeCallback *)> onSuccess(Platform::New<CHIPSecondFabricsAttributeCallback>(callback, true), chip::Platform::Delete<CHIPSecondFabricsAttributeCallback>);
VerifyOrReturn(onSuccess.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY));

std::unique_ptr<CHIPDefaultFailureCallback, void (*)(CHIPDefaultFailureCallback *)> onFailure(Platform::New<CHIPDefaultFailureCallback>(callback), chip::Platform::Delete<CHIPDefaultFailureCallback>);
VerifyOrReturn(onFailure.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY));

CHIP_ERROR err = CHIP_NO_ERROR;
ClusterBase * cppCluster = reinterpret_cast<ClusterBase *>(clusterPtr);
VerifyOrReturn(cppCluster != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE));

using TypeInfo = chip::app::Clusters::Second::Attributes::Fabrics::TypeInfo;
auto successFn = chip::Callback::Callback<CHIPSecondClusterFabricsAttributeCallbackType>::FromCancelable(onSuccess->Cancel());
auto failureFn = chip::Callback::Callback<CHIPDefaultFailureCallbackType>::FromCancelable(onFailure->Cancel());

err = cppCluster->SubscribeAttribute<TypeInfo>(onSuccess->mContext, successFn->mCall, failureFn->mCall, static_cast<uint16_t>(minInterval), static_cast<uint16_t>(maxInterval), CHIPSecondFabricsAttributeCallback::OnSubscriptionEstablished);
VerifyOrReturn(err == CHIP_NO_ERROR, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error subscribing to attribute", err));

onSuccess.release();
onFailure.release();
}JNI_METHOD(void, SecondCluster, subscribeSomeBytesAttribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval)
{
chip::DeviceLayer::StackLock lock;std::unique_ptr<CHIPOctetStringAttributeCallback, void (*)(CHIPOctetStringAttributeCallback *)> onSuccess(Platform::New<CHIPOctetStringAttributeCallback>(callback, true), chip::Platform::Delete<CHIPOctetStringAttributeCallback>);
VerifyOrReturn(onSuccess.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,30 @@

#define JNI_METHOD(RETURN, CLASS_NAME, METHOD_NAME) \
extern "C" JNIEXPORT RETURN JNICALL Java_chip_devicecontroller_ChipClusters_00024##CLASS_NAME##_##METHOD_NAME
JNI_METHOD(void, SecondCluster, readFabricsAttribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jboolean isFabricFiltered)
{
chip::DeviceLayer::StackLock lock;
using TypeInfo = chip::app::Clusters::Second::Attributes::Fabrics::TypeInfo;
std::unique_ptr<CHIPSecondFabricsAttributeCallback, void (*)(CHIPSecondFabricsAttributeCallback *)> onSuccess(chip::Platform::New<CHIPSecondFabricsAttributeCallback>(callback, false), chip::Platform::Delete<CHIPSecondFabricsAttributeCallback>);
VerifyOrReturn(onSuccess.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY));

std::unique_ptr<chip::CHIPDefaultFailureCallback, void (*)(chip::CHIPDefaultFailureCallback *)> onFailure(chip::Platform::New<chip::CHIPDefaultFailureCallback>(callback), chip::Platform::Delete<chip::CHIPDefaultFailureCallback>);
VerifyOrReturn(onFailure.get() != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY));

CHIP_ERROR err = CHIP_NO_ERROR;
chip::Controller::ClusterBase * cppCluster = reinterpret_cast<chip::Controller::ClusterBase *>(clusterPtr);
VerifyOrReturn(cppCluster != nullptr, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE));

auto successFn = chip::Callback::Callback<CHIPSecondClusterFabricsAttributeCallbackType>::FromCancelable(onSuccess->Cancel());
auto failureFn = chip::Callback::Callback<CHIPDefaultFailureCallbackType>::FromCancelable(onFailure->Cancel());
err = cppCluster->ReadAttribute<TypeInfo>(onSuccess->mContext, successFn->mCall, failureFn->mCall, isFabricFiltered);
VerifyOrReturn(err == CHIP_NO_ERROR, chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error reading attribute", err));

onSuccess.release();
onFailure.release();
}


JNI_METHOD(void, SecondCluster, readSomeBytesAttribute)(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback)
{
chip::DeviceLayer::StackLock lock;
Expand Down
17 changes: 16 additions & 1 deletion src/controller/java/templates/ChipClusters-java.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,20 @@ public class ChipClusters {
{{asUpperCamelCase name}}AttributeCallback callback
{{/if_basic_attribute}}
) {
read{{asUpperCamelCase name}}Attribute(chipClusterPtr, callback);
read{{asUpperCamelCase name}}Attribute(chipClusterPtr, callback{{#if_is_fabric_scoped_struct type}}, true{{/if_is_fabric_scoped_struct}});
}
{{#if_is_fabric_scoped_struct type}}
public void read{{asUpperCamelCase name}}AttributeWithFabricFilter(
{{#if_basic_attribute type ../id}}
{{as_underlying_java_zcl_type type ../id boolean="Boolean"}}AttributeCallback callback
{{else}}
{{asUpperCamelCase name}}AttributeCallback callback
{{/if_basic_attribute}},
boolean isFabricFiltered
) {
read{{asUpperCamelCase name}}Attribute(chipClusterPtr, callback, isFabricFiltered);
}
{{/if_is_fabric_scoped_struct}}
{{#if isWritableAttribute}}
{{#unless mustUseTimedWrite}}
public void write{{asUpperCamelCase name}}Attribute(DefaultClusterCallback callback, {{asJavaType type chipType parent.name}} value) {
Expand Down Expand Up @@ -218,6 +230,9 @@ public class ChipClusters {
{{else}}
{{asUpperCamelCase name}}AttributeCallback callback
{{/if_basic_attribute}}
{{#if_is_fabric_scoped_struct type}}
, boolean isFabricFiltered
{{/if_is_fabric_scoped_struct}}
);
{{#if isWritableAttribute}}

Expand Down
Loading

0 comments on commit 2219154

Please sign in to comment.