Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Add data version filter support in IM #30427

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import chip.devicecontroller.model.AttributeState
import chip.devicecontroller.model.ChipAttributePath
import chip.devicecontroller.model.ChipEventPath
import chip.devicecontroller.model.ChipPathId
import chip.devicecontroller.model.DataVersionFilter
import chip.devicecontroller.model.EventState
import chip.devicecontroller.model.NodeState
import com.matter.controller.commands.common.CredentialsIssuer
Expand Down Expand Up @@ -169,6 +170,15 @@ class PairOnNetworkLongImReadCommand(
)
)

val dataVersionFilterList =
listOf(
DataVersionFilter.newInstance(
ChipPathId.forId(/* endpointId= */ 0),
ChipPathId.forId(CLUSTER_ID_BASIC),
CLUSTER_ID_BASIC_VERSION,
)
)

currentCommissioner()
.pairDeviceWithAddress(
getNodeId(),
Expand All @@ -184,7 +194,15 @@ class PairOnNetworkLongImReadCommand(
.getConnectedDevicePointer(getNodeId(), InternalGetConnectedDeviceCallback())
clear()
currentCommissioner()
.readPath(InternalReportCallback(), devicePointer, attributePathList, eventPathList, false, 0)
.readPath(
InternalReportCallback(),
devicePointer,
attributePathList,
eventPathList,
dataVersionFilterList,
false,
0
)
waitCompleteMs(getTimeoutMillis())
}

Expand All @@ -198,5 +216,6 @@ class PairOnNetworkLongImReadCommand(
private const val ATTR_ID_LOCAL_CONFIG_DISABLED = 16L
private const val EVENT_ID_START_UP = 0L
private const val GLOBAL_ATTRIBUTE_LIST = 65531L
private const val CLUSTER_ID_BASIC_VERSION = 0L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import chip.devicecontroller.ResubscriptionAttemptCallback
import chip.devicecontroller.SubscriptionEstablishedCallback
import chip.devicecontroller.model.ChipAttributePath
import chip.devicecontroller.model.ChipEventPath
import chip.devicecontroller.model.ChipPathId
import chip.devicecontroller.model.DataVersionFilter
import chip.devicecontroller.model.NodeState
import com.matter.controller.commands.common.CredentialsIssuer
import java.util.Collections
Expand Down Expand Up @@ -81,6 +83,15 @@ class PairOnNetworkLongImSubscribeCommand(
)
)

val dataVersionFilterList =
listOf(
DataVersionFilter.newInstance(
ChipPathId.forId(/* endpointId= */ 0),
ChipPathId.forId(CLUSTER_ID_BASIC),
CLUSTER_ID_BASIC_VERSION,
)
)

currentCommissioner()
.pairDeviceWithAddress(
getNodeId(),
Expand All @@ -103,6 +114,7 @@ class PairOnNetworkLongImSubscribeCommand(
devicePointer,
attributePathList,
Collections.emptyList(),
dataVersionFilterList,
0,
5,
false,
Expand All @@ -120,5 +132,6 @@ class PairOnNetworkLongImSubscribeCommand(
private const val MATTER_PORT = 5540
private const val CLUSTER_ID_BASIC = 0x0028L
private const val ATTR_ID_LOCAL_CONFIG_DISABLED = 16L
private const val CLUSTER_ID_BASIC_VERSION = 0L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yunhanw-google Why was this change needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, it is not needed, but i think it is better to have?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

{
UpdateDataVersionFilters(attributePath);
}
Expand Down
15 changes: 13 additions & 2 deletions src/controller/java/AndroidCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
102 changes: 100 additions & 2 deletions src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <lib/support/JniTypeWrappers.h>

#include <app/AttributePathParams.h>
#include <app/DataVersionFilter.h>
#include <app/InteractionModelEngine.h>
#include <app/ReadClient.h>
#include <app/WriteClient.h>
Expand Down Expand Up @@ -93,6 +94,10 @@ CHIP_ERROR ParseAttributePath(jobject attributePath, EndpointId & outEndpointId,
static CHIP_ERROR ParseEventPathList(jobject eventPathList, std::vector<app::EventPathParams> & 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<app::DataVersionFilter> & outDataVersionFilterList);
static CHIP_ERROR IsWildcardChipPathId(jobject chipPathId, bool & isWildcard);

namespace {
Expand Down Expand Up @@ -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<ReportCallback *>(callbackHandle);
DeviceProxy * device = reinterpret_cast<DeviceProxy *>(devicePtr);
if (device == nullptr)
Expand Down Expand Up @@ -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<chip::app::DataVersionFilter[]> 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<chip::EventNumber>(JniReferences::GetInstance().LongToPrimitive(eventMin)));
Expand Down Expand Up @@ -2202,14 +2233,15 @@ 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;

auto callback = reinterpret_cast<ReportCallback *>(callbackHandle);
std::vector<app::AttributePathParams> attributePathParamsList;
std::vector<app::EventPathParams> eventPathParamsList;
std::vector<app::DataVersionFilter> versionList;
app::ReadClient * readClient = nullptr;
DeviceProxy * device = reinterpret_cast<DeviceProxy *>(devicePtr);
if (device == nullptr)
Expand All @@ -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;
Expand Down Expand Up @@ -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<app::DataVersionFilter> & 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>(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>(clusterId);

outDataVersion = static_cast<DataVersion>(env->CallLongMethod(versionFilter, getDataVersionMethod));
return CHIP_NO_ERROR;
}

CHIP_ERROR GetChipPathIdValue(jobject chipPathId, uint32_t wildcardValue, uint32_t & outValue)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand Down
Loading
Loading