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] Integrate cluster state cache with android Java IM API #22851

Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 5 additions & 0 deletions src/app/ClusterStateCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,5 +532,10 @@ CHIP_ERROR ClusterStateCache::OnUpdateDataVersionFilterList(DataVersionFilterIBs
return err;
}

CHIP_ERROR ClusterStateCache::GetLastReportDataPath(ConcreteClusterPath & aPath)
{
aPath = mLastReportDataPath;
return CHIP_NO_ERROR;
}
} // namespace app
} // namespace chip
2 changes: 2 additions & 0 deletions src/app/ClusterStateCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,8 @@ class ClusterStateCache : protected ReadClient::Callback
mEventStatusCache.clear();
}

CHIP_ERROR GetLastReportDataPath(ConcreteClusterPath & aPath);

private:
using AttributeState = Variant<Platform::ScopedMemoryBufferWithSize<uint8_t>, StatusIB>;
// mPendingDataVersion represents a tentative data version for a cluster that we have gotten some reports for.
Expand Down
32 changes: 31 additions & 1 deletion src/controller/java/AndroidCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void GetConnectedDeviceCallback::OnDeviceConnectionFailureFn(void * context, con

ReportCallback::ReportCallback(jobject wrapperCallback, jobject subscriptionEstablishedCallback, jobject reportCallback,
jobject resubscriptionAttemptCallback) :
mBufferedReadAdapter(*this)
mClusterCacheAdapter(*this)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
Expand Down Expand Up @@ -186,6 +186,8 @@ void ReportCallback::OnReportBegin()

void ReportCallback::OnReportEnd()
{
UpdateClusterDataVersion();

// Transform C++ jobject pair list to a Java HashMap, and call onReport() on the Java callback.
CHIP_ERROR err = CHIP_NO_ERROR;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
Expand Down Expand Up @@ -281,6 +283,34 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat
env->CallVoidMethod(mNodeStateObj, addAttributeMethod, static_cast<jint>(aPath.mEndpointId),
static_cast<jlong>(aPath.mClusterId), static_cast<jlong>(aPath.mAttributeId), attributeStateObj);
VerifyOrReturnError(!env->ExceptionCheck(), env->ExceptionDescribe());

UpdateClusterDataVersion();
}

void ReportCallback::UpdateClusterDataVersion()
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
chip::app::ConcreteClusterPath lastConcreteClusterPath;
if (mClusterCacheAdapter.GetLastReportDataPath(lastConcreteClusterPath) == CHIP_NO_ERROR &&
lastConcreteClusterPath.IsValidConcreteClusterPath())
{
chip::Optional<chip::DataVersion> committedDataVersion;
if (mClusterCacheAdapter.GetVersion(lastConcreteClusterPath, committedDataVersion) == CHIP_NO_ERROR)
{
if (committedDataVersion.HasValue())
{
// SetDataVersion to NodeState
jmethodID setDataVersionMethod;
CHIP_ERROR err =
JniReferences::GetInstance().FindMethod(env, mNodeStateObj, "setDataVersion", "(IJI)V", &setDataVersionMethod);
VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find setDataVersion method"));
env->CallVoidMethod(mNodeStateObj, setDataVersionMethod, static_cast<jint>(lastConcreteClusterPath.mEndpointId),
static_cast<jlong>(lastConcreteClusterPath.mClusterId),
static_cast<jint>(committedDataVersion.Value()));
VerifyOrReturnError(!env->ExceptionCheck(), env->ExceptionDescribe());
}
}
}
}

void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLVReader * apData, const app::StatusIB * apStatus)
Expand Down
6 changes: 4 additions & 2 deletions src/controller/java/AndroidCallbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct GetConnectedDeviceCallback
jobject mJavaCallbackRef = nullptr;
};

struct ReportCallback : public app::ReadClient::Callback
struct ReportCallback : public app::ClusterStateCache::Callback
{
/** Subscription established callback can be nullptr. */
ReportCallback(jobject wrapperCallback, jobject subscriptionEstablishedCallback, jobject reportCallback,
Expand Down Expand Up @@ -74,9 +74,11 @@ struct ReportCallback : public app::ReadClient::Callback

CHIP_ERROR CreateChipEventPath(const app::ConcreteEventPath & aPath, jobject & outObj);

void UpdateClusterDataVersion();

app::ReadClient * mReadClient = nullptr;

app::BufferedReadCallback mBufferedReadAdapter;
app::ClusterStateCache mClusterCacheAdapter;
jobject mWrapperCallbackRef = nullptr;
jobject mSubscriptionEstablishedCallbackRef = nullptr;
jobject mResubscriptionAttemptCallbackRef = nullptr;
Expand Down
12 changes: 6 additions & 6 deletions src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1077,9 +1077,9 @@ JNI_METHOD(void, subscribe)

auto callback = reinterpret_cast<ReportCallback *>(callbackHandle);

app::ReadClient * readClient =
Platform::New<app::ReadClient>(app::InteractionModelEngine::GetInstance(), device->GetExchangeManager(),
callback->mBufferedReadAdapter, app::ReadClient::InteractionType::Subscribe);
app::ReadClient * readClient = Platform::New<app::ReadClient>(
app::InteractionModelEngine::GetInstance(), device->GetExchangeManager(),
callback->mClusterCacheAdapter.GetBufferedCallback(), app::ReadClient::InteractionType::Subscribe);

err = readClient->SendRequest(params);
if (err != CHIP_NO_ERROR)
Expand Down Expand Up @@ -1126,9 +1126,9 @@ JNI_METHOD(void, read)

auto callback = reinterpret_cast<ReportCallback *>(callbackHandle);

app::ReadClient * readClient =
Platform::New<app::ReadClient>(app::InteractionModelEngine::GetInstance(), device->GetExchangeManager(),
callback->mBufferedReadAdapter, app::ReadClient::InteractionType::Read);
app::ReadClient * readClient = Platform::New<app::ReadClient>(
app::InteractionModelEngine::GetInstance(), device->GetExchangeManager(),
callback->mClusterCacheAdapter.GetBufferedCallback(), app::ReadClient::InteractionType::Read);

err = readClient->SendRequest(params);
if (err != CHIP_NO_ERROR)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ public byte[] getAttestationChallenge(long devicePtr) {
}

/** Subscribe to the given attribute path. */
public void subscribeToPath(
public void subscribeToAttributePath(
SubscriptionEstablishedCallback subscriptionEstablishedCallback,
ReportCallback reportCallback,
long devicePtr,
Expand Down Expand Up @@ -524,7 +524,7 @@ public void subscribeToPath(
}

/** Read the given attribute path. */
public void readPath(
public void readAttributePath(
ReportCallback callback, long devicePtr, List<ChipAttributePath> attributePaths) {
ReportCallbackJni jniCallback = new ReportCallbackJni(null, callback, null);
read(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@

import androidx.annotation.Nullable;
import java.util.Map;
import java.util.Optional;

/** Class for tracking CHIP cluster state in a hierarchical manner. */
public final class ClusterState {
private Map<Long, AttributeState> attributes;
private Map<Long, EventState> events;
private Optional<Integer> dataVersion;

public ClusterState(Map<Long, AttributeState> attributes, Map<Long, EventState> events) {
this.attributes = attributes;
this.events = events;
this.dataVersion = Optional.empty();
}

public Map<Long, AttributeState> getAttributeStates() {
Expand All @@ -38,6 +41,14 @@ public Map<Long, EventState> getEventStates() {
return events;
}

public void setDataVersion(int version) {
dataVersion = Optional.of(version);
}

public int getDataVersion() {
return dataVersion.get();
}

/**
* Convenience utility for getting an {@code AttributeState}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ public Map<Integer, EndpointState> getEndpointStates() {
return endpoints;
}

// Called from native code only, which ignores access modifiers.
private void setDataVersion(int endpointId, long clusterId, int dataVersion) {
EndpointState endpointState = getEndpointState(endpointId);
ClusterState clusterState = endpointState.getClusterState(clusterId);

if (clusterState != null) {
clusterState.setDataVersion(dataVersion);
}
}

// Called from native code only, which ignores access modifiers.
private void addAttribute(
int endpointId, long clusterId, long attributeId, AttributeState attributeStateToAdd) {
Expand Down