diff --git a/scripts/py_matter_idl/matter_idl/generators/java/ChipClusters_java.jinja b/scripts/py_matter_idl/matter_idl/generators/java/ChipClusters_java.jinja index 00d09a51cbed85..45621c7e86469a 100644 --- a/scripts/py_matter_idl/matter_idl/generators/java/ChipClusters_java.jinja +++ b/scripts/py_matter_idl/matter_idl/generators/java/ChipClusters_java.jinja @@ -197,7 +197,7 @@ public class ChipClusters { boolean isFabricFiltered) { ReportCallbackJni jniCallback = new ReportCallbackJni(null, callback, null); ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, attributeId); - ChipDeviceController.read(0, jniCallback.getCallbackHandle(), devicePtr, Arrays.asList(path), null, isFabricFiltered, timeoutMillis.orElse(0L).intValue(), null); + ChipDeviceController.read(0, jniCallback.getCallbackHandle(), devicePtr, Arrays.asList(path), null, null, isFabricFiltered, timeoutMillis.orElse(0L).intValue(), null); } protected void writeAttribute( @@ -218,7 +218,7 @@ public class ChipClusters { int maxInterval) { ReportCallbackJni jniCallback = new ReportCallbackJni(callback, callback, null); ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, attributeId); - ChipDeviceController.subscribe(0, jniCallback.getCallbackHandle(), devicePtr, Arrays.asList(path), null, minInterval, maxInterval, false, true, timeoutMillis.orElse(0L).intValue(), null); + ChipDeviceController.subscribe(0, jniCallback.getCallbackHandle(), devicePtr, Arrays.asList(path), null, null, minInterval, maxInterval, false, true, timeoutMillis.orElse(0L).intValue(), null); } protected void invoke( diff --git a/src/app/ReadClient.cpp b/src/app/ReadClient.cpp index 373d2051d3457f..d2a904ebbb5ccc 100644 --- a/src/app/ReadClient.cpp +++ b/src/app/ReadClient.cpp @@ -693,7 +693,7 @@ CHIP_ERROR ReadClient::ProcessAttributeReportIBs(TLV::TLVReader & aAttributeRepo ReturnErrorOnFailure(data.GetDataVersion(&version)); attributePath.mDataVersion.SetValue(version); - if (mReadPrepareParams.mpDataVersionFilterList != nullptr) + if (mReadPrepareParams.mpDataVersionFilterList != nullptr && mReadPrepareParams.mDataVersionFilterListSize != 0) { UpdateDataVersionFilters(attributePath); } diff --git a/src/controller/java/AndroidCallbacks.cpp b/src/controller/java/AndroidCallbacks.cpp index 93344a5e1bc7eb..fd6b043beacb34 100644 --- a/src/controller/java/AndroidCallbacks.cpp +++ b/src/controller/java/AndroidCallbacks.cpp @@ -197,14 +197,25 @@ void ReportCallback::OnReportBegin() void ReportCallback::OnDeallocatePaths(app::ReadPrepareParams && aReadPrepareParams) { - if (aReadPrepareParams.mpAttributePathParamsList != nullptr) + if (aReadPrepareParams.mpAttributePathParamsList != nullptr && aReadPrepareParams.mAttributePathParamsListSize != 0) { delete[] aReadPrepareParams.mpAttributePathParamsList; + aReadPrepareParams.mpAttributePathParamsList = nullptr; + aReadPrepareParams.mAttributePathParamsListSize = 0; } - if (aReadPrepareParams.mpEventPathParamsList != nullptr) + if (aReadPrepareParams.mpEventPathParamsList != nullptr && aReadPrepareParams.mEventPathParamsListSize != 0) { delete[] aReadPrepareParams.mpEventPathParamsList; + aReadPrepareParams.mpEventPathParamsList = nullptr; + aReadPrepareParams.mEventPathParamsListSize = 0; + } + + if (aReadPrepareParams.mpDataVersionFilterList != nullptr && aReadPrepareParams.mDataVersionFilterListSize != 0) + { + delete[] aReadPrepareParams.mpDataVersionFilterList; + aReadPrepareParams.mpDataVersionFilterList = nullptr; + aReadPrepareParams.mDataVersionFilterListSize = 0; } } diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index 7fb098d4a1a88f..4d09f611bc4267 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -465,6 +465,7 @@ android_library("java") { "src/chip/devicecontroller/model/ChipEventPath.java", "src/chip/devicecontroller/model/ChipPathId.java", "src/chip/devicecontroller/model/ClusterState.java", + "src/chip/devicecontroller/model/DataVersionFilter.java", "src/chip/devicecontroller/model/EndpointState.java", "src/chip/devicecontroller/model/EventState.java", "src/chip/devicecontroller/model/InvokeElement.java", diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 7633b0a304d793..0e698ebe81cf17 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -93,6 +94,10 @@ CHIP_ERROR ParseAttributePath(jobject attributePath, EndpointId & outEndpointId, static CHIP_ERROR ParseEventPathList(jobject eventPathList, std::vector & outEventPathParamsList); CHIP_ERROR ParseEventPath(jobject eventPath, EndpointId & outEndpointId, ClusterId & outClusterId, EventId & outEventId, bool & outIsUrgent); +CHIP_ERROR ParseDataVersionFilter(jobject dataVersionFilter, EndpointId & outEndpointId, ClusterId & outClusterId, + DataVersion & outDataVersion); +static CHIP_ERROR ParseDataVersionFilterList(jobject dataVersionFilterList, + std::vector & outDataVersionFilterList); static CHIP_ERROR IsWildcardChipPathId(jobject chipPathId, bool & isWildcard); namespace { @@ -2093,13 +2098,15 @@ JNI_METHOD(jobject, computePaseVerifier) JNI_METHOD(void, subscribe) (JNIEnv * env, jclass clz, jlong handle, jlong callbackHandle, jlong devicePtr, jobject attributePathList, jobject eventPathList, - jint minInterval, jint maxInterval, jboolean keepSubscriptions, jboolean isFabricFiltered, jint imTimeoutMs, jobject eventMin) + jobject dataVersionFilterList, jint minInterval, jint maxInterval, jboolean keepSubscriptions, jboolean isFabricFiltered, + jint imTimeoutMs, jobject eventMin) { chip::DeviceLayer::StackLock lock; CHIP_ERROR err = CHIP_NO_ERROR; app::ReadClient * readClient = nullptr; jint numAttributePaths = 0; jint numEventPaths = 0; + jint numDataVersionFilters = 0; auto callback = reinterpret_cast(callbackHandle); DeviceProxy * device = reinterpret_cast(devicePtr); if (device == nullptr) @@ -2141,6 +2148,30 @@ JNI_METHOD(void, subscribe) attributePaths.release(); } + if (dataVersionFilterList != nullptr) + { + SuccessOrExit(err = JniReferences::GetInstance().GetListSize(dataVersionFilterList, numDataVersionFilters)); + } + + if (numDataVersionFilters > 0) + { + std::unique_ptr dataVersionFilters(new chip::app::DataVersionFilter[numDataVersionFilters]); + for (uint8_t i = 0; i < numDataVersionFilters; i++) + { + jobject dataVersionFilterItem = nullptr; + SuccessOrExit(err = JniReferences::GetInstance().GetListItem(dataVersionFilterList, i, dataVersionFilterItem)); + + EndpointId endpointId; + ClusterId clusterId; + DataVersion dataVersion; + SuccessOrExit(err = ParseDataVersionFilter(dataVersionFilterItem, endpointId, clusterId, dataVersion)); + dataVersionFilters[i] = chip::app::DataVersionFilter(endpointId, clusterId, dataVersion); + } + params.mpDataVersionFilterList = dataVersionFilters.get(); + params.mDataVersionFilterListSize = numDataVersionFilters; + dataVersionFilters.release(); + } + if (eventMin != nullptr) { params.mEventNumber.SetValue(static_cast(JniReferences::GetInstance().LongToPrimitive(eventMin))); @@ -2202,7 +2233,7 @@ JNI_METHOD(void, subscribe) JNI_METHOD(void, read) (JNIEnv * env, jclass clz, jlong handle, jlong callbackHandle, jlong devicePtr, jobject attributePathList, jobject eventPathList, - jboolean isFabricFiltered, jint imTimeoutMs, jobject eventMin) + jobject dataVersionFilterList, jboolean isFabricFiltered, jint imTimeoutMs, jobject eventMin) { chip::DeviceLayer::StackLock lock; CHIP_ERROR err = CHIP_NO_ERROR; @@ -2210,6 +2241,7 @@ JNI_METHOD(void, read) auto callback = reinterpret_cast(callbackHandle); std::vector attributePathParamsList; std::vector eventPathParamsList; + std::vector versionList; app::ReadClient * readClient = nullptr; DeviceProxy * device = reinterpret_cast(devicePtr); if (device == nullptr) @@ -2222,11 +2254,17 @@ JNI_METHOD(void, read) SuccessOrExit(err = ParseAttributePathList(attributePathList, attributePathParamsList)); SuccessOrExit(err = ParseEventPathList(eventPathList, eventPathParamsList)); + SuccessOrExit(err = ParseDataVersionFilterList(dataVersionFilterList, versionList)); VerifyOrExit(attributePathParamsList.size() != 0 || eventPathParamsList.size() != 0, err = CHIP_ERROR_INVALID_ARGUMENT); params.mpAttributePathParamsList = attributePathParamsList.data(); params.mAttributePathParamsListSize = attributePathParamsList.size(); params.mpEventPathParamsList = eventPathParamsList.data(); params.mEventPathParamsListSize = eventPathParamsList.size(); + if (versionList.size() != 0) + { + params.mpDataVersionFilterList = versionList.data(); + params.mDataVersionFilterListSize = versionList.size(); + } params.mIsFabricFiltered = (isFabricFiltered != JNI_FALSE); params.mTimeout = imTimeoutMs != 0 ? System::Clock::Milliseconds32(imTimeoutMs) : System::Clock::kZero; @@ -2745,6 +2783,66 @@ CHIP_ERROR ParseEventPath(jobject eventPath, EndpointId & outEndpointId, Cluster return CHIP_NO_ERROR; } +/** + * Takes objects in dataVersionFilterList, converts them to app:DataVersionFilter, and appends them to outDataVersionFilterList. + */ +CHIP_ERROR ParseDataVersionFilterList(jobject dataVersionFilterList, std::vector & outDataVersionFilterList) +{ + jint listSize; + + if (dataVersionFilterList == nullptr) + { + return CHIP_NO_ERROR; + } + + ReturnErrorOnFailure(JniReferences::GetInstance().GetListSize(dataVersionFilterList, listSize)); + + for (uint8_t i = 0; i < listSize; i++) + { + jobject dataVersionFilterItem = nullptr; + ReturnErrorOnFailure(JniReferences::GetInstance().GetListItem(dataVersionFilterList, i, dataVersionFilterItem)); + + EndpointId endpointId; + ClusterId clusterId; + DataVersion dataVersion; + ReturnErrorOnFailure(ParseDataVersionFilter(dataVersionFilterItem, endpointId, clusterId, dataVersion)); + outDataVersionFilterList.push_back(app::DataVersionFilter(endpointId, clusterId, dataVersion)); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ParseDataVersionFilter(jobject versionFilter, EndpointId & outEndpointId, ClusterId & outClusterId, + DataVersion & outDataVersion) +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + + jmethodID getEndpointIdMethod = nullptr; + jmethodID getClusterIdMethod = nullptr; + jmethodID getDataVersionMethod = nullptr; + + ReturnErrorOnFailure(JniReferences::GetInstance().FindMethod( + env, versionFilter, "getEndpointId", "()Lchip/devicecontroller/model/ChipPathId;", &getEndpointIdMethod)); + ReturnErrorOnFailure(JniReferences::GetInstance().FindMethod( + env, versionFilter, "getClusterId", "()Lchip/devicecontroller/model/ChipPathId;", &getClusterIdMethod)); + ReturnErrorOnFailure( + JniReferences::GetInstance().FindMethod(env, versionFilter, "getDataVersion", "()J;", &getDataVersionMethod)); + + jobject endpointIdObj = env->CallObjectMethod(versionFilter, getEndpointIdMethod); + VerifyOrReturnError(endpointIdObj != nullptr, CHIP_ERROR_INCORRECT_STATE); + uint32_t endpointId = 0; + ReturnErrorOnFailure(GetChipPathIdValue(endpointIdObj, kInvalidEndpointId, endpointId)); + outEndpointId = static_cast(endpointId); + jobject clusterIdObj = env->CallObjectMethod(versionFilter, getClusterIdMethod); + VerifyOrReturnError(clusterIdObj != nullptr, CHIP_ERROR_INCORRECT_STATE); + uint32_t clusterId = 0; + ReturnErrorOnFailure(GetChipPathIdValue(clusterIdObj, kInvalidClusterId, clusterId)); + outClusterId = static_cast(clusterId); + + outDataVersion = static_cast(env->CallLongMethod(versionFilter, getDataVersionMethod)); + return CHIP_NO_ERROR; +} + CHIP_ERROR GetChipPathIdValue(jobject chipPathId, uint32_t wildcardValue, uint32_t & outValue) { JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index fc241abddf6087..19615feca714a5 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -120,7 +120,7 @@ protected void readAttribute( boolean isFabricFiltered) { ReportCallbackJni jniCallback = new ReportCallbackJni(null, callback, null); ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, attributeId); - ChipDeviceController.read(0, jniCallback.getCallbackHandle(), devicePtr, Arrays.asList(path), null, isFabricFiltered, timeoutMillis.orElse(0L).intValue(), null); + ChipDeviceController.read(0, jniCallback.getCallbackHandle(), devicePtr, Arrays.asList(path), null, null, isFabricFiltered, timeoutMillis.orElse(0L).intValue(), null); } protected void writeAttribute( @@ -141,7 +141,7 @@ protected void subscribeAttribute( int maxInterval) { ReportCallbackJni jniCallback = new ReportCallbackJni(callback, callback, null); ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, attributeId); - ChipDeviceController.subscribe(0, jniCallback.getCallbackHandle(), devicePtr, Arrays.asList(path), null, minInterval, maxInterval, false, true, timeoutMillis.orElse(0L).intValue(), null); + ChipDeviceController.subscribe(0, jniCallback.getCallbackHandle(), devicePtr, Arrays.asList(path), null, null, minInterval, maxInterval, false, true, timeoutMillis.orElse(0L).intValue(), null); } protected void invoke(