diff --git a/src/controller/java/AndroidCallbacks.cpp b/src/controller/java/AndroidCallbacks.cpp index 4c3e05051a9d4e..f81b8c2fc5575a 100644 --- a/src/controller/java/AndroidCallbacks.cpp +++ b/src/controller/java/AndroidCallbacks.cpp @@ -42,6 +42,67 @@ static const int MILLIS_SINCE_EPOCH = 1; // Add the bytes for attribute tag(1:control + 8:tag + 8:length) and structure(1:struct + 1:close container) static const int EXTRA_SPACE_FOR_ATTRIBUTE_TAG = 19; +class JniChipAttributePath +{ +public: + JniChipAttributePath(JNIEnv * env, const app::ConcreteDataAttributePath & aPath) : mEnv(env) + { + jclass attributePathCls = nullptr; + ReturnOnFailure(mError = JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/model/ChipAttributePath", + attributePathCls)); + JniClass attributePathJniCls(attributePathCls); + + jmethodID attributePathCtor = + env->GetStaticMethodID(attributePathCls, "newInstance", "(IJJ)Lchip/devicecontroller/model/ChipAttributePath;"); + VerifyOrReturn(attributePathCtor != nullptr, mError = CHIP_JNI_ERROR_METHOD_NOT_FOUND); + mData = env->CallStaticObjectMethod(attributePathCls, attributePathCtor, static_cast(aPath.mEndpointId), + static_cast(aPath.mClusterId), static_cast(aPath.mAttributeId)); + VerifyOrReturn(mData != nullptr, mError = CHIP_JNI_ERROR_NULL_OBJECT); + return; + } + + ~JniChipAttributePath() { mEnv->DeleteLocalRef(mData); } + + CHIP_ERROR GetError() { return mError; } + jobject GetData() { return mData; } + +private: + JNIEnv * mEnv = nullptr; + jobject mData = nullptr; + CHIP_ERROR mError = CHIP_NO_ERROR; +}; + +class JniChipEventPath +{ +public: + JniChipEventPath(JNIEnv * env, const app::ConcreteEventPath & aPath) : mEnv(env) + { + jclass eventPathCls = nullptr; + ReturnOnFailure( + mError = JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/model/ChipEventPath", eventPathCls)); + JniClass eventPathJniCls(eventPathCls); + + jmethodID eventPathCtor = + env->GetStaticMethodID(eventPathCls, "newInstance", "(IJJ)Lchip/devicecontroller/model/ChipEventPath;"); + VerifyOrReturn(eventPathCtor != nullptr, mError = CHIP_JNI_ERROR_METHOD_NOT_FOUND); + + mData = env->CallStaticObjectMethod(eventPathCls, eventPathCtor, static_cast(aPath.mEndpointId), + static_cast(aPath.mClusterId), static_cast(aPath.mEventId)); + VerifyOrReturn(mData != nullptr, mError = CHIP_JNI_ERROR_NULL_OBJECT); + return; + } + + ~JniChipEventPath() { mEnv->DeleteLocalRef(mData); } + + CHIP_ERROR GetError() { return mError; } + jobject GetData() { return mData; } + +private: + JNIEnv * mEnv = nullptr; + jobject mData = nullptr; + CHIP_ERROR mError = CHIP_NO_ERROR; +}; + GetConnectedDeviceCallback::GetConnectedDeviceCallback(jobject wrapperCallback, jobject javaCallback) : mOnSuccess(OnDeviceConnectedFn, this), mOnFailure(OnDeviceConnectionFailureFn, this) { @@ -254,27 +315,27 @@ CHIP_ERROR ConvertReportTlvToJson(const uint32_t id, TLV::TLVReader & data, std: void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const app::StatusIB & aStatus) { - CHIP_ERROR err = CHIP_NO_ERROR; - JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); - jobject attributePathObj = nullptr; - err = CreateChipAttributePath(aPath, attributePathObj); - VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to create Java ChipAttributePath: %s", ErrorStr(err))); + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + JniChipAttributePath attributePathObj(env, aPath); + VerifyOrReturn(attributePathObj.GetError() == CHIP_NO_ERROR, + ChipLogError(Controller, "Unable to create Java ChipAttributePath: %s", ErrorStr(err))); if (aPath.IsListItemOperation()) { - ReportError(attributePathObj, nullptr, CHIP_ERROR_INCORRECT_STATE); + ReportError(attributePathObj.GetData(), nullptr, CHIP_ERROR_INCORRECT_STATE); return; } if (aStatus.mStatus != Protocols::InteractionModel::Status::Success) { - ReportError(attributePathObj, nullptr, aStatus.mStatus); + ReportError(attributePathObj.GetData(), nullptr, aStatus.mStatus); return; } if (apData == nullptr) { - ReportError(attributePathObj, nullptr, CHIP_ERROR_INVALID_ARGUMENT); + ReportError(attributePathObj.GetData(), nullptr, CHIP_ERROR_INVALID_ARGUMENT); return; } @@ -293,9 +354,9 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat err = CHIP_NO_ERROR; } - VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(attributePathObj, nullptr, err)); + VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(attributePathObj.GetData(), nullptr, err)); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe(), - ReportError(attributePathObj, nullptr, CHIP_JNI_ERROR_EXCEPTION_THROWN)); + ReportError(attributePathObj.GetData(), nullptr, CHIP_JNI_ERROR_EXCEPTION_THROWN)); #endif // Create TLV byte array to pass to Java layer size_t bufferLen = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead(); @@ -308,14 +369,14 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat TLV::TLVWriter writer; writer.Init(buffer.get(), bufferLen); err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV); - VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(attributePathObj, nullptr, err)); + VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(attributePathObj.GetData(), nullptr, err)); size = writer.GetLengthWritten(); chip::ByteArray jniByteArray(env, reinterpret_cast(buffer.get()), size); // Convert TLV to JSON std::string json; err = ConvertReportTlvToJson(static_cast(aPath.mAttributeId), *apData, json); - VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(attributePathObj, nullptr, err)); + VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(attributePathObj.GetData(), nullptr, err)); UtfString jsonString(env, json.c_str()); // Create AttributeState object @@ -338,6 +399,7 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat env->CallVoidMethod(mNodeStateObj, addAttributeMethod, static_cast(aPath.mEndpointId), static_cast(aPath.mClusterId), static_cast(aPath.mAttributeId), attributeStateObj); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); + env->DeleteLocalRef(attributeStateObj); UpdateClusterDataVersion(); } @@ -378,15 +440,15 @@ void ReportCallback::UpdateClusterDataVersion() void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLVReader * apData, const app::StatusIB * apStatus) { - CHIP_ERROR err = CHIP_NO_ERROR; - JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); - jobject eventPathObj = nullptr; - err = CreateChipEventPath(aEventHeader.mPath, eventPathObj); - VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to create Java ChipEventPath: %s", ErrorStr(err))); + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + JniChipEventPath eventPathObj(env, aEventHeader.mPath); + VerifyOrReturn(eventPathObj.GetError() == CHIP_NO_ERROR, + ChipLogError(Controller, "Unable to create Java ChipEventPath: %s", ErrorStr(err))); if (apData == nullptr) { - ReportError(nullptr, eventPathObj, CHIP_ERROR_INVALID_ARGUMENT); + ReportError(nullptr, eventPathObj.GetData(), CHIP_ERROR_INVALID_ARGUMENT); return; } @@ -409,7 +471,7 @@ void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLV else { ChipLogError(Controller, "Unsupported event timestamp type"); - ReportError(nullptr, eventPathObj, CHIP_ERROR_INVALID_ARGUMENT); + ReportError(nullptr, eventPathObj.GetData(), CHIP_ERROR_INVALID_ARGUMENT); return; } @@ -423,9 +485,9 @@ void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLV { err = CHIP_NO_ERROR; } - VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, eventPathObj, err)); + VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, eventPathObj.GetData(), err)); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe(), - ReportError(nullptr, eventPathObj, CHIP_JNI_ERROR_EXCEPTION_THROWN)); + ReportError(nullptr, eventPathObj.GetData(), CHIP_JNI_ERROR_EXCEPTION_THROWN)); #endif // Create TLV byte array to pass to Java layer @@ -438,14 +500,14 @@ void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLV TLV::TLVWriter writer; writer.Init(buffer.get(), bufferLen); err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV); - VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, eventPathObj, err)); + VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(nullptr, eventPathObj.GetData(), err)); size = writer.GetLengthWritten(); chip::ByteArray jniByteArray(env, reinterpret_cast(buffer.get()), size); // Convert TLV to JSON std::string json; err = ConvertReportTlvToJson(static_cast(aEventHeader.mPath.mEventId), *apData, json); - VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(eventPathObj, nullptr, err)); + VerifyOrReturn(err == CHIP_NO_ERROR, ReportError(eventPathObj.GetData(), nullptr, err)); UtfString jsonString(env, json.c_str()); // Create EventState object @@ -469,27 +531,7 @@ void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLV static_cast(aEventHeader.mPath.mClusterId), static_cast(aEventHeader.mPath.mEventId), eventStateObj); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); -} - -CHIP_ERROR CreateChipAttributePath(const app::ConcreteDataAttributePath & aPath, jobject & outObj) -{ - JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); - CHIP_ERROR err = CHIP_NO_ERROR; - - jclass attributePathCls = nullptr; - err = JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/model/ChipAttributePath", attributePathCls); - VerifyOrReturnError(err == CHIP_NO_ERROR, err); - JniClass attributePathJniCls(attributePathCls); - - jmethodID attributePathCtor = - env->GetStaticMethodID(attributePathCls, "newInstance", "(IJJ)Lchip/devicecontroller/model/ChipAttributePath;"); - VerifyOrReturnError(attributePathCtor != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND); - - outObj = env->CallStaticObjectMethod(attributePathCls, attributePathCtor, static_cast(aPath.mEndpointId), - static_cast(aPath.mClusterId), static_cast(aPath.mAttributeId)); - VerifyOrReturnError(outObj != nullptr, CHIP_JNI_ERROR_NULL_OBJECT); - - return err; + env->DeleteLocalRef(eventStateObj); } CHIP_ERROR InvokeCallback::CreateInvokeElement(const app::ConcreteCommandPath & aPath, TLV::TLVReader * apData, jobject & outObj) @@ -549,27 +591,6 @@ CHIP_ERROR InvokeCallback::CreateInvokeElement(const app::ConcreteCommandPath & return err; } -CHIP_ERROR ReportCallback::CreateChipEventPath(const app::ConcreteEventPath & aPath, jobject & outObj) -{ - JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); - CHIP_ERROR err = CHIP_NO_ERROR; - - jclass eventPathCls = nullptr; - err = JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/model/ChipEventPath", eventPathCls); - VerifyOrReturnError(err == CHIP_NO_ERROR, err); - JniClass eventPathJniCls(eventPathCls); - - jmethodID eventPathCtor = - env->GetStaticMethodID(eventPathCls, "newInstance", "(IJJ)Lchip/devicecontroller/model/ChipEventPath;"); - VerifyOrReturnError(eventPathCtor != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND); - - outObj = env->CallStaticObjectMethod(eventPathCls, eventPathCtor, static_cast(aPath.mEndpointId), - static_cast(aPath.mClusterId), static_cast(aPath.mEventId)); - VerifyOrReturnError(outObj != nullptr, CHIP_JNI_ERROR_NULL_OBJECT); - - return err; -} - void ReportCallback::OnError(CHIP_ERROR aError) { ReportError(nullptr, nullptr, aError); @@ -690,15 +711,15 @@ WriteAttributesCallback::~WriteAttributesCallback() void WriteAttributesCallback::OnResponse(const app::WriteClient * apWriteClient, const app::ConcreteDataAttributePath & aPath, app::StatusIB aStatus) { - CHIP_ERROR err = CHIP_NO_ERROR; - JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); - jobject attributePathObj = nullptr; - err = CreateChipAttributePath(aPath, attributePathObj); - VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to create Java ChipAttributePath: %s", ErrorStr(err))); + CHIP_ERROR err = CHIP_NO_ERROR; + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + JniChipAttributePath attributePathObj(env, aPath); + VerifyOrReturn(attributePathObj.GetError() == CHIP_NO_ERROR, + ChipLogError(Controller, "Unable to create Java ChipAttributePath: %s", ErrorStr(err))); if (aStatus.mStatus != Protocols::InteractionModel::Status::Success) { - ReportError(attributePathObj, aStatus.mStatus); + ReportError(attributePathObj.GetData(), aStatus.mStatus); return; } @@ -708,7 +729,7 @@ void WriteAttributesCallback::OnResponse(const app::WriteClient * apWriteClient, VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to find onError method: %s", ErrorStr(err))); DeviceLayer::StackUnlock unlock; - env->CallVoidMethod(mJavaCallbackRef, onResponseMethod, attributePathObj); + env->CallVoidMethod(mJavaCallbackRef, onResponseMethod, attributePathObj.GetData()); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); }