diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt index a482a6170f7766..a9861aa4223fa5 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt @@ -179,7 +179,8 @@ class WildcardFragment : Fragment() { minInterval, maxInterval, keepSubscriptions, - isFabricFiltered) + isFabricFiltered, + /* imTimeoutMs= */ 0) } else if (type == EVENT) { val eventPath = ChipEventPath.newInstance(endpointId, clusterId, eventId, isUrgent) deviceController.subscribeToPath(subscriptionEstablishedCallback, @@ -192,7 +193,8 @@ class WildcardFragment : Fragment() { minInterval, maxInterval, keepSubscriptions, - isFabricFiltered) + isFabricFiltered, + /* imTimeoutMs= */ 0) } } @@ -209,7 +211,8 @@ class WildcardFragment : Fragment() { addressUpdateFragment.deviceId), listOf(attributePath), null, - isFabricFiltered) + isFabricFiltered, + /* imTimeoutMs= */ 0) } else if (type == EVENT) { val eventPath = ChipEventPath.newInstance(endpointId, clusterId, eventId) deviceController.readPath(reportCallback, @@ -217,7 +220,8 @@ class WildcardFragment : Fragment() { addressUpdateFragment.deviceId), null, listOf(eventPath), - isFabricFiltered) + isFabricFiltered, + /* imTimeoutMs= */ 0) } } diff --git a/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImReadCommand.kt b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImReadCommand.kt index 218c1ac5230259..418a3f7ff44b4c 100644 --- a/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImReadCommand.kt +++ b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImReadCommand.kt @@ -66,7 +66,7 @@ class PairOnNetworkLongImReadCommand( .getConnectedDevicePointer(getNodeId(), InternalGetConnectedDeviceCallback()) clear() currentCommissioner() - .readPath(InternalReportCallback(), devicePointer, attributePathList, Collections.emptyList(), false) + .readPath(InternalReportCallback(), devicePointer, attributePathList, Collections.emptyList(), false, 0) waitCompleteMs(getTimeoutMillis()) } diff --git a/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImSubscribeCommand.kt b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImSubscribeCommand.kt index d99b25c8ce620f..c4b870da4369c9 100644 --- a/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImSubscribeCommand.kt +++ b/examples/java-matter-controller/java/src/com/matter/controller/commands/pairing/PairOnNetworkLongImSubscribeCommand.kt @@ -81,7 +81,7 @@ class PairOnNetworkLongImSubscribeCommand( .getConnectedDevicePointer(getNodeId(), InternalGetConnectedDeviceCallback()) clear() currentCommissioner() - .subscribeToPath(InternalSubscriptionEstablishedCallback(), InternalResubscriptionAttemptCallback(), InternalReportCallback(), devicePointer, attributePathList, Collections.emptyList(), 0, 5, false, false) + .subscribeToPath(InternalSubscriptionEstablishedCallback(), InternalResubscriptionAttemptCallback(), InternalReportCallback(), devicePointer, attributePathList, Collections.emptyList(), 0, 5, false, false, 0) waitCompleteMs(getTimeoutMillis()) currentCommissioner().shutdownSubscriptions(currentCommissioner().getFabricIndex(), getNodeId(), subscriptionId); } diff --git a/src/controller/java/AndroidCallbacks-JNI.cpp b/src/controller/java/AndroidCallbacks-JNI.cpp index 1916b1b1a68b99..57aadcc8c4bbcd 100644 --- a/src/controller/java/AndroidCallbacks-JNI.cpp +++ b/src/controller/java/AndroidCallbacks-JNI.cpp @@ -38,7 +38,7 @@ JNI_METHOD(void, GetConnectedDeviceCallbackJni, deleteCallback)(JNIEnv * env, jo chip::DeviceLayer::StackLock lock; GetConnectedDeviceCallback * connectedDeviceCallback = reinterpret_cast(callbackHandle); VerifyOrReturn(connectedDeviceCallback != nullptr, ChipLogError(Controller, "GetConnectedDeviceCallback handle is nullptr")); - delete connectedDeviceCallback; + chip::Platform::Delete(connectedDeviceCallback); } JNI_METHOD(jlong, ReportCallbackJni, newCallback) @@ -56,7 +56,7 @@ JNI_METHOD(void, ReportCallbackJni, deleteCallback)(JNIEnv * env, jobject self, chip::DeviceLayer::StackLock lock; ReportCallback * reportCallback = reinterpret_cast(callbackHandle); VerifyOrReturn(reportCallback != nullptr, ChipLogError(Controller, "ReportCallback handle is nullptr")); - delete reportCallback; + chip::Platform::Delete(reportCallback); } JNI_METHOD(jlong, ReportEventCallbackJni, newCallback) @@ -91,7 +91,7 @@ JNI_METHOD(void, WriteAttributesCallbackJni, deleteCallback)(JNIEnv * env, jobje chip::DeviceLayer::StackLock lock; WriteAttributesCallback * writeAttributesCallback = reinterpret_cast(callbackHandle); VerifyOrReturn(writeAttributesCallback != nullptr, ChipLogError(Controller, "WriteAttributesCallback handle is nullptr")); - delete writeAttributesCallback; + chip::Platform::Delete(writeAttributesCallback); } JNI_METHOD(jlong, InvokeCallbackJni, newCallback) @@ -107,5 +107,5 @@ JNI_METHOD(void, InvokeCallbackJni, deleteCallback)(JNIEnv * env, jobject self, chip::DeviceLayer::StackLock lock; InvokeCallback * invokeCallback = reinterpret_cast(callbackHandle); VerifyOrReturn(invokeCallback != nullptr, ChipLogError(Controller, "InvokeCallback handle is nullptr")); - delete invokeCallback; + chip::Platform::Delete(invokeCallback); } diff --git a/src/controller/java/AndroidCallbacks.cpp b/src/controller/java/AndroidCallbacks.cpp index e530e051fd337a..017f377b59e1d2 100644 --- a/src/controller/java/AndroidCallbacks.cpp +++ b/src/controller/java/AndroidCallbacks.cpp @@ -123,7 +123,7 @@ void GetConnectedDeviceCallback::OnDeviceConnectionFailureFn(void * context, con ReportCallback::ReportCallback(jobject wrapperCallback, jobject subscriptionEstablishedCallback, jobject reportCallback, jobject resubscriptionAttemptCallback) : - mClusterCacheAdapter(*this) + mClusterCacheAdapter(*this, Optional::Missing(), false /*cacheData*/) { JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread")); @@ -186,6 +186,19 @@ void ReportCallback::OnReportBegin() mNodeStateObj = env->NewObject(mNodeStateCls, nodeStateCtor, map); } +void ReportCallback::OnDeallocatePaths(app::ReadPrepareParams && aReadPrepareParams) +{ + if (aReadPrepareParams.mpAttributePathParamsList != nullptr) + { + delete[] aReadPrepareParams.mpAttributePathParamsList; + } + + if (aReadPrepareParams.mpEventPathParamsList != nullptr) + { + delete[] aReadPrepareParams.mpEventPathParamsList; + } +} + void ReportCallback::OnReportEnd() { UpdateClusterDataVersion(); @@ -239,8 +252,12 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat readerForJson.Init(*apData); jobject value = DecodeAttributeValue(aPath, readerForJavaObject, &err); - // If we don't know this attribute, just skip it. - VerifyOrReturn(err != CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB); + // If we don't know this attribute, suppress it. + if (err == CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB) + { + err = CHIP_NO_ERROR; + } + VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(attributePathObj, nullptr, err)); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe(), ReportError(attributePathObj, nullptr, CHIP_JNI_ERROR_EXCEPTION_THROWN)); diff --git a/src/controller/java/AndroidCallbacks.h b/src/controller/java/AndroidCallbacks.h index cd058eae43fe56..9fc2e758f101f6 100644 --- a/src/controller/java/AndroidCallbacks.h +++ b/src/controller/java/AndroidCallbacks.h @@ -69,6 +69,8 @@ struct ReportCallback : public app::ClusterStateCache::Callback CHIP_ERROR OnResubscriptionNeeded(app::ReadClient * apReadClient, CHIP_ERROR aTerminationCause) override; + void OnDeallocatePaths(app::ReadPrepareParams && aReadPrepareParams) override; + /** Report errors back to Java layer. attributePath may be nullptr for general errors. */ void ReportError(jobject attributePath, jobject eventPath, CHIP_ERROR err); void ReportError(jobject attributePath, jobject eventPath, Protocols::InteractionModel::Status status); diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 52dca9d77e3a04..d0c491e2a918ec 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -1355,104 +1355,156 @@ JNI_METHOD(jobject, computePaseVerifier) JNI_METHOD(void, subscribe) (JNIEnv * env, jobject self, jlong handle, jlong callbackHandle, jlong devicePtr, jobject attributePathList, jobject eventPathList, - jint minInterval, jint maxInterval, jboolean keepSubscriptions, jboolean isFabricFiltered) + jint minInterval, jint maxInterval, jboolean keepSubscriptions, jboolean isFabricFiltered, jint imTimeoutMs) { chip::DeviceLayer::StackLock lock; - CHIP_ERROR err = CHIP_NO_ERROR; - - DeviceProxy * device = reinterpret_cast(devicePtr); + CHIP_ERROR err = CHIP_NO_ERROR; + app::ReadClient * readClient = nullptr; + jint numAttributePaths = 0; + jint numEventPaths = 0; + auto callback = reinterpret_cast(callbackHandle); + DeviceProxy * device = reinterpret_cast(devicePtr); if (device == nullptr) { - ChipLogError(Controller, "No device found"); + ChipLogProgress(Controller, "Could not cast device pointer to Device object"); JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, CHIP_ERROR_INCORRECT_STATE); return; } + app::ReadPrepareParams params(device->GetSecureSession().Value()); - std::vector attributePathParamsList; - err = ParseAttributePathList(attributePathList, attributePathParamsList); - VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Error parsing Java attribute paths: %s", ErrorStr(err))); + params.mMinIntervalFloorSeconds = minInterval; + params.mMaxIntervalCeilingSeconds = maxInterval; + params.mKeepSubscriptions = (keepSubscriptions != JNI_FALSE); + params.mIsFabricFiltered = (isFabricFiltered != JNI_FALSE); + params.mTimeout = imTimeoutMs != 0 ? System::Clock::Milliseconds32(imTimeoutMs) : System::Clock::kZero; - std::vector eventPathParamsList; - err = ParseEventPathList(eventPathList, eventPathParamsList); - VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Error parsing Java event paths: %s", ErrorStr(err))); + SuccessOrExit(err = JniReferences::GetInstance().GetListSize(attributePathList, numAttributePaths)); + if (numAttributePaths > 0) + { + std::unique_ptr attributePaths(new chip::app::AttributePathParams[numAttributePaths]); + for (uint8_t i = 0; i < numAttributePaths; i++) + { + jobject attributePathItem = nullptr; + SuccessOrExit(err = JniReferences::GetInstance().GetListItem(attributePathList, i, attributePathItem)); + + EndpointId endpointId; + ClusterId clusterId; + AttributeId attributeId; + SuccessOrExit(err = ParseAttributePath(attributePathItem, endpointId, clusterId, attributeId)); + attributePaths[i] = chip::app::AttributePathParams(endpointId, clusterId, attributeId); + } + params.mpAttributePathParamsList = attributePaths.get(); + params.mAttributePathParamsListSize = numAttributePaths; + attributePaths.release(); + } - app::ReadPrepareParams params(device->GetSecureSession().Value()); - params.mMinIntervalFloorSeconds = minInterval; - params.mMaxIntervalCeilingSeconds = maxInterval; - params.mpAttributePathParamsList = attributePathParamsList.data(); - params.mAttributePathParamsListSize = attributePathParamsList.size(); - params.mpEventPathParamsList = eventPathParamsList.data(); - params.mEventPathParamsListSize = eventPathParamsList.size(); - params.mKeepSubscriptions = (keepSubscriptions != JNI_FALSE); - params.mIsFabricFiltered = (isFabricFiltered != JNI_FALSE); + SuccessOrExit(err = JniReferences::GetInstance().GetListSize(eventPathList, numEventPaths)); + if (numEventPaths > 0) + { + std::unique_ptr eventPaths(new chip::app::EventPathParams[numEventPaths]); + for (uint8_t i = 0; i < numEventPaths; i++) + { + jobject eventPathItem = nullptr; + SuccessOrExit(err = JniReferences::GetInstance().GetListItem(eventPathList, i, eventPathItem)); + + EndpointId endpointId; + ClusterId clusterId; + EventId eventId; + bool isUrgent; + SuccessOrExit(err = ParseEventPath(eventPathItem, endpointId, clusterId, eventId, isUrgent)); + eventPaths[i] = chip::app::EventPathParams(endpointId, clusterId, eventId, isUrgent); + } - auto callback = reinterpret_cast(callbackHandle); + params.mpEventPathParamsList = eventPaths.get(); + params.mEventPathParamsListSize = numEventPaths; + eventPaths.release(); + } + + readClient = Platform::New(app::InteractionModelEngine::GetInstance(), device->GetExchangeManager(), + callback->mClusterCacheAdapter.GetBufferedCallback(), + app::ReadClient::InteractionType::Subscribe); - app::ReadClient * readClient = Platform::New( - app::InteractionModelEngine::GetInstance(), device->GetExchangeManager(), - callback->mClusterCacheAdapter.GetBufferedCallback(), app::ReadClient::InteractionType::Subscribe); + SuccessOrExit(err = readClient->SendAutoResubscribeRequest(std::move(params))); + callback->mReadClient = readClient; - err = readClient->SendRequest(params); +exit: if (err != CHIP_NO_ERROR) { + ChipLogError(Controller, "JNI IM Subscribe Error: %s", err.AsString()); + if (err == CHIP_JNI_ERROR_EXCEPTION_THROWN) + { + env->ExceptionDescribe(); + env->ExceptionClear(); + } callback->OnError(err); - delete readClient; - delete callback; - return; + if (readClient != nullptr) + { + Platform::Delete(readClient); + } + if (callback != nullptr) + { + Platform::Delete(callback); + } } - - callback->mReadClient = readClient; } JNI_METHOD(void, read) (JNIEnv * env, jobject self, jlong handle, jlong callbackHandle, jlong devicePtr, jobject attributePathList, jobject eventPathList, - jboolean isFabricFiltered) + jboolean isFabricFiltered, jint imTimeoutMs) { chip::DeviceLayer::StackLock lock; CHIP_ERROR err = CHIP_NO_ERROR; - DeviceProxy * device = reinterpret_cast(devicePtr); + auto callback = reinterpret_cast(callbackHandle); + std::vector attributePathParamsList; + std::vector eventPathParamsList; + app::ReadClient * readClient = nullptr; + DeviceProxy * device = reinterpret_cast(devicePtr); if (device == nullptr) { - ChipLogError(Controller, "No device found"); + ChipLogProgress(Controller, "Could not cast device pointer to Device object"); JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, CHIP_ERROR_INCORRECT_STATE); return; } - - std::vector attributePathParamsList; - err = ParseAttributePathList(attributePathList, attributePathParamsList); - VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Error parsing Java attribute paths: %s", ErrorStr(err))); - - std::vector eventPathParamsList; - err = ParseEventPathList(eventPathList, eventPathParamsList); - VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Error parsing Java event paths: %s", ErrorStr(err))); - - VerifyOrReturn(attributePathParamsList.size() != 0 || eventPathParamsList.size() != 0, - ChipLogError(Controller, "Error parsing Java both event paths and attribute paths")); app::ReadPrepareParams params(device->GetSecureSession().Value()); + + SuccessOrExit(err = ParseAttributePathList(attributePathList, attributePathParamsList)); + SuccessOrExit(err = ParseEventPathList(eventPathList, eventPathParamsList)); + 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(); params.mIsFabricFiltered = (isFabricFiltered != JNI_FALSE); + params.mTimeout = imTimeoutMs != 0 ? System::Clock::Milliseconds32(imTimeoutMs) : System::Clock::kZero; - auto callback = reinterpret_cast(callbackHandle); + readClient = Platform::New(app::InteractionModelEngine::GetInstance(), device->GetExchangeManager(), + callback->mClusterCacheAdapter.GetBufferedCallback(), + app::ReadClient::InteractionType::Read); - app::ReadClient * readClient = Platform::New( - app::InteractionModelEngine::GetInstance(), device->GetExchangeManager(), - callback->mClusterCacheAdapter.GetBufferedCallback(), app::ReadClient::InteractionType::Read); + SuccessOrExit(err = readClient->SendRequest(params)); + callback->mReadClient = readClient; - err = readClient->SendRequest(params); +exit: if (err != CHIP_NO_ERROR) { + ChipLogError(Controller, "JNI IM Read Error: %s", err.AsString()); + if (err == CHIP_JNI_ERROR_EXCEPTION_THROWN) + { + env->ExceptionDescribe(); + env->ExceptionClear(); + } callback->OnError(err); - delete readClient; - delete callback; - return; + if (readClient != nullptr) + { + Platform::Delete(readClient); + } + if (callback != nullptr) + { + Platform::Delete(callback); + } } - - callback->mReadClient = readClient; } JNI_METHOD(void, write) @@ -1576,11 +1628,11 @@ JNI_METHOD(void, write) callback->OnError(writeClient, err); if (writeClient != nullptr) { - delete writeClient; + Platform::Delete(writeClient); } if (callback != nullptr) { - delete callback; + Platform::Delete(callback); } } } @@ -1684,11 +1736,11 @@ JNI_METHOD(void, invoke) callback->OnError(nullptr, err); if (commandSender != nullptr) { - delete commandSender; + Platform::Delete(commandSender); } if (callback != nullptr) { - delete callback; + Platform::Delete(callback); } } } diff --git a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java index c1df558a6b4d51..f57d736a7bd4a2 100644 --- a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java +++ b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java @@ -539,14 +539,29 @@ public byte[] getAttestationChallenge(long devicePtr) { return getAttestationChallenge(deviceControllerPtr, devicePtr); } - /** Subscribe to the given attribute path. */ + /** + * @brief Auto-Resubscribe to the given attribute path with keepSubscriptions and isFabricFiltered + * @param SubscriptionEstablishedCallback Callback when a subscribe response has been received and + * processed + * @param ResubscriptionAttemptCallback Callback when a resubscirption haoppens, the termination + * cause is provided to help inform subsequent re-subscription logic. + * @param ReportCallback Callback when a report data has been received and processed for the given + * paths. + * @param devicePtr connected device pointer + * @param attributePaths a list of attribute paths + * @param minInterval the requested minimum interval boundary floor in seconds + * @param maxInterval the requested maximum interval boundary ceiling in seconds + * @param imTimeoutMs im interaction time out value, it would override the default value in c++ im + * layer if this value is non-zero. + */ public void subscribeToAttributePath( SubscriptionEstablishedCallback subscriptionEstablishedCallback, ReportCallback reportCallback, long devicePtr, List attributePaths, int minInterval, - int maxInterval) { + int maxInterval, + int imTimeoutMs) { ReportCallbackJni jniCallback = new ReportCallbackJni(subscriptionEstablishedCallback, reportCallback, null); subscribe( @@ -558,17 +573,33 @@ public void subscribeToAttributePath( minInterval, maxInterval, false, - false); + false, + imTimeoutMs); } - /** Subscribe to the given event path */ + /** + * @brief Auto-Resubscribe to the given event path with keepSubscriptions and isFabricFiltered + * @param SubscriptionEstablishedCallback Callback when a subscribe response has been received and + * processed + * @param ResubscriptionAttemptCallback Callback when a resubscirption haoppens, the termination + * cause is provided to help inform subsequent re-subscription logic. + * @param ReportCallback Callback when a report data has been received and processed for the given + * paths. + * @param devicePtr connected device pointer + * @param eventPaths a list of event paths + * @param minInterval the requested minimum interval boundary floor in seconds + * @param maxInterval the requested maximum interval boundary ceiling in seconds + * @param imTimeoutMs im interaction time out value, it would override the default value in c++ im + * layer if this value is non-zero. + */ public void subscribeToEventPath( SubscriptionEstablishedCallback subscriptionEstablishedCallback, ReportCallback reportCallback, long devicePtr, List eventPaths, int minInterval, - int maxInterval) { + int maxInterval, + int imTimeoutMs) { ReportCallbackJni jniCallback = new ReportCallbackJni(subscriptionEstablishedCallback, reportCallback, null); subscribe( @@ -580,10 +611,30 @@ public void subscribeToEventPath( minInterval, maxInterval, false, - false); + false, + imTimeoutMs); } - /** Subscribe to the given attribute/event path with keepSubscriptions and isFabricFiltered. */ + /** + * @brief Auto-Resubscribe to the given attribute/event path with keepSubscriptions and + * isFabricFiltered + * @param SubscriptionEstablishedCallback Callback when a subscribe response has been received and + * processed + * @param ResubscriptionAttemptCallback Callback when a resubscirption haoppens, the termination + * cause is provided to help inform subsequent re-subscription logic. + * @param ReportCallback Callback when a report data has been received and processed for the given + * paths. + * @param devicePtr connected device pointer + * @param attributePaths a list of attribute paths + * @param eventPaths a list of event paths + * @param minInterval the requested minimum interval boundary floor in seconds + * @param maxInterval the requested maximum interval boundary ceiling in seconds + * @param keepSubscriptions If KeepSubscriptions is FALSE, all existing or pending subscriptions + * on the publisher for this subscriber SHALL be terminated. + * @param isFabricFiltered limits the data read within fabric-scoped lists to the accessing fabric + * @param imTimeoutMs im interaction time out value, it would override the default value in c++ im + * layer if this value is non-zero. + */ public void subscribeToPath( SubscriptionEstablishedCallback subscriptionEstablishedCallback, ResubscriptionAttemptCallback resubscriptionAttemptCallback, @@ -594,12 +645,11 @@ public void subscribeToPath( int minInterval, int maxInterval, boolean keepSubscriptions, - boolean isFabricFiltered) { - // TODO: pass resubscriptionAttemptCallback to ReportCallbackJni since jni layer - // is not ready - // for auto-resubscribe + boolean isFabricFiltered, + int imTimeoutMs) { ReportCallbackJni jniCallback = - new ReportCallbackJni(subscriptionEstablishedCallback, reportCallback, null); + new ReportCallbackJni( + subscriptionEstablishedCallback, reportCallback, resubscriptionAttemptCallback); subscribe( deviceControllerPtr, jniCallback.getCallbackHandle(), @@ -609,12 +659,24 @@ public void subscribeToPath( minInterval, maxInterval, keepSubscriptions, - isFabricFiltered); + isFabricFiltered, + imTimeoutMs); } - /** Read the given attribute path. */ + /** + * @brief read the given attribute path with isFabricFiltered + * @param ReportCallback Callback when a report data has been received and processed for the given + * paths. + * @param devicePtr connected device pointer + * @param attributePaths a list of attribute paths + * @param imTimeoutMs im interaction time out value, it would override the default value in c++ im + * layer if this value is non-zero. + */ public void readAttributePath( - ReportCallback callback, long devicePtr, List attributePaths) { + ReportCallback callback, + long devicePtr, + List attributePaths, + int imTimeoutMs) { ReportCallbackJni jniCallback = new ReportCallbackJni(null, callback, null); read( deviceControllerPtr, @@ -622,23 +684,49 @@ public void readAttributePath( devicePtr, attributePaths, null, - true); + true, + imTimeoutMs); } - /** Read the given event path. */ + /** + * @brief read the given event path with isFabricFiltered + * @param ReportCallback Callback when a report data has been received and processed for the given + * paths. + * @param devicePtr connected device pointer + * @param eventPaths a list of event paths + * @param imTimeoutMs im interaction time out value, it would override the default value in c++ im + * layer if this value is non-zero. + */ public void readEventPath( - ReportCallback callback, long devicePtr, List eventPaths) { + ReportCallback callback, long devicePtr, List eventPaths, int imTimeoutMs) { ReportCallbackJni jniCallback = new ReportCallbackJni(null, callback, null); - read(deviceControllerPtr, jniCallback.getCallbackHandle(), devicePtr, null, eventPaths, true); + read( + deviceControllerPtr, + jniCallback.getCallbackHandle(), + devicePtr, + null, + eventPaths, + true, + imTimeoutMs); } - /** Read the given attribute/event path with isFabricFiltered flag. */ + /** + * @brief read the given attribute/event path with isFabricFiltered + * @param ReportCallback Callback when a report data has been received and processed for the given + * paths. + * @param devicePtr connected device pointer + * @param attributePaths a list of attribute paths + * @param eventPaths a list of event paths + * @param imTimeoutMs im interaction time out value, it would override the default value in c++ im + * layer if this value is non-zero. + */ public void readPath( ReportCallback callback, long devicePtr, List attributePaths, List eventPaths, - boolean isFabricFiltered) { + boolean isFabricFiltered, + int imTimeoutMs) { ReportCallbackJni jniCallback = new ReportCallbackJni(null, callback, null); read( deviceControllerPtr, @@ -646,7 +734,8 @@ public void readPath( devicePtr, attributePaths, eventPaths, - isFabricFiltered); + isFabricFiltered, + imTimeoutMs); } /** @@ -746,7 +835,8 @@ private native void subscribe( int minInterval, int maxInterval, boolean keepSubscriptions, - boolean isFabricFiltered); + boolean isFabricFiltered, + int imTimeoutMs); private native void read( long deviceControllerPtr, @@ -754,7 +844,8 @@ private native void read( long devicePtr, List attributePaths, List eventPaths, - boolean isFabricFiltered); + boolean isFabricFiltered, + int imTimeoutMs); private native void write( long deviceControllerPtr,