Skip to content

Commit

Permalink
[Android] Integrate cluster state cache with android Java IM API (#22851
Browse files Browse the repository at this point in the history
)

* Integrate cluster state cache with java im API

* address comments
  • Loading branch information
yunhanw-google authored and pull[bot] committed Sep 6, 2023
1 parent 1aa5f34 commit e66ae20
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 14 deletions.
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
46 changes: 42 additions & 4 deletions 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 @@ -280,7 +282,43 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat
VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find addAttribute method"));
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());
VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());

UpdateClusterDataVersion();
}

void ReportCallback::UpdateClusterDataVersion()
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
chip::app::ConcreteClusterPath lastConcreteClusterPath;

if (mClusterCacheAdapter.GetLastReportDataPath(lastConcreteClusterPath) != CHIP_NO_ERROR)
{
return;
}

if (!lastConcreteClusterPath.IsValidConcreteClusterPath())
{
return;
}

chip::Optional<chip::DataVersion> committedDataVersion;
if (mClusterCacheAdapter.GetVersion(lastConcreteClusterPath, committedDataVersion) != CHIP_NO_ERROR)
{
return;
}
if (!committedDataVersion.HasValue())
{
return;
}

// 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()));
VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLVReader * apData, const app::StatusIB * apStatus)
Expand Down Expand Up @@ -356,7 +394,7 @@ void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLV
env->CallVoidMethod(mNodeStateObj, addEventMethod, static_cast<jint>(aEventHeader.mPath.mEndpointId),
static_cast<jlong>(aEventHeader.mPath.mClusterId), static_cast<jlong>(aEventHeader.mPath.mEventId),
eventStateObj);
VerifyOrReturnError(!env->ExceptionCheck(), env->ExceptionDescribe());
VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

CHIP_ERROR ReportCallback::CreateChipAttributePath(const app::ConcreteDataAttributePath & aPath, jobject & outObj)
Expand Down Expand Up @@ -628,7 +666,7 @@ void ReportEventCallback::OnEventData(const app::EventHeader & aEventHeader, TLV
env->CallVoidMethod(mNodeStateObj, addEventMethod, static_cast<jint>(aEventHeader.mPath.mEndpointId),
static_cast<jlong>(aEventHeader.mPath.mClusterId), static_cast<jlong>(aEventHeader.mPath.mEventId),
eventStateObj);
VerifyOrReturnError(!env->ExceptionCheck(), env->ExceptionDescribe());
VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

CHIP_ERROR ReportEventCallback::CreateChipEventPath(const app::ConcreteEventPath & aPath, jobject & outObj)
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 Optional<Integer> getDataVersion() {
return dataVersion;
}

/**
* Convenience utility for getting an {@code AttributeState}.
*
Expand Down
10 changes: 10 additions & 0 deletions src/controller/java/src/chip/devicecontroller/model/NodeState.java
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

0 comments on commit e66ae20

Please sign in to comment.