diff --git a/src/controller/java/AndroidCallbacks.cpp b/src/controller/java/AndroidCallbacks.cpp index 01ef820f82c6ed..fb7975262dff57 100644 --- a/src/controller/java/AndroidCallbacks.cpp +++ b/src/controller/java/AndroidCallbacks.cpp @@ -41,6 +41,8 @@ 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; +jobject DecodeGeneralTLVValue(JNIEnv * env, TLV::TLVReader & readerForGeneralValueObject, CHIP_ERROR & err); + GetConnectedDeviceCallback::GetConnectedDeviceCallback(jobject wrapperCallback, jobject javaCallback, const char * callbackClassSignature) : mOnSuccess(OnDeviceConnectedFn, this), @@ -314,20 +316,24 @@ void ReportCallback::OnAttributeData(const app::ConcreteDataAttributePath & aPat readerForJavaTLV.Init(*apData); jobject value = nullptr; -#ifdef USE_JAVA_TLV_ENCODE_DECODE TLV::TLVReader readerForJavaObject; readerForJavaObject.Init(*apData); - +#ifdef USE_JAVA_TLV_ENCODE_DECODE value = DecodeAttributeValue(aPath, readerForJavaObject, &err); // If we don't know this attribute, suppress it. if (err == CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH_IB) { - err = CHIP_NO_ERROR; + TLV::TLVReader readerForGeneralValueObject; + readerForGeneralValueObject.Init(*apData); + value = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err); + err = CHIP_NO_ERROR; } VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Fail to decode attribute with error %s", ErrorStr(err)); aPath.LogPath()); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); +#else + value = DecodeGeneralTLVValue(env, readerForJavaObject, err); #endif // Create TLV byte array to pass to Java layer size_t bufferLen = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead(); @@ -468,18 +474,23 @@ void ReportCallback::OnEventData(const app::EventHeader & aEventHeader, TLV::TLV } jobject value = nullptr; -#ifdef USE_JAVA_TLV_ENCODE_DECODE TLV::TLVReader readerForJavaObject; readerForJavaObject.Init(*apData); +#ifdef USE_JAVA_TLV_ENCODE_DECODE value = DecodeEventValue(aEventHeader.mPath, readerForJavaObject, &err); // If we don't know this event, just skip it. if (err == CHIP_ERROR_IM_MALFORMED_EVENT_PATH_IB) { - err = CHIP_NO_ERROR; + TLV::TLVReader readerForGeneralValueObject; + readerForGeneralValueObject.Init(*apData); + value = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err); + err = CHIP_NO_ERROR; } VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Fail to decode event with error %s", ErrorStr(err)); aEventHeader.LogPath()); VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); +#else + value = DecodeGeneralTLVValue(env, readerForJavaObject, err); #endif // Create TLV byte array to pass to Java layer @@ -907,6 +918,111 @@ void InvokeCallback::ReportError(const char * message, ChipError::StorageType er VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe()); } +jobject DecodeGeneralTLVValue(JNIEnv * env, TLV::TLVReader & readerForGeneralValueObject, CHIP_ERROR & err) +{ + jobject retValue = nullptr; + + switch (readerForGeneralValueObject.GetType()) + { + case TLV::kTLVType_SignedInteger: { + int64_t signedValue = 0; + VerifyOrReturnValue(readerForGeneralValueObject.Get(signedValue) == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Get TLV Value fail!")); + err = JniReferences::GetInstance().CreateBoxedObject("java/lang/Long", "(J)V", static_cast(signedValue), + retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!")); + return retValue; + } + case TLV::kTLVType_UnsignedInteger: { + uint64_t unsignedValue = 0; + VerifyOrReturnValue(readerForGeneralValueObject.Get(unsignedValue) == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Get TLV Value fail!")); + err = JniReferences::GetInstance().CreateBoxedObject("java/lang/Long", "(J)V", static_cast(unsignedValue), + retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!")); + return retValue; + } + case TLV::kTLVType_Boolean: { + bool booleanValue = false; + VerifyOrReturnValue(readerForGeneralValueObject.Get(booleanValue) == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Get TLV Value fail!")); + err = JniReferences::GetInstance().CreateBoxedObject("java/lang/Boolean", "(Z)V", + static_cast(booleanValue), retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!")); + return retValue; + } + case TLV::kTLVType_FloatingPointNumber: { + double doubleValue = 0.0; + VerifyOrReturnValue(readerForGeneralValueObject.Get(doubleValue) == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Get TLV Value fail!")); + err = JniReferences::GetInstance().CreateBoxedObject("java/lang/Double", "(D)V", static_cast(doubleValue), + retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Create Boxed Object fail!")); + return retValue; + } + case TLV::kTLVType_UTF8String: { + uint32_t bufferLen = readerForGeneralValueObject.GetLength(); + std::unique_ptr buffer = std::unique_ptr(new char[bufferLen + 1]); + err = readerForGeneralValueObject.GetString(buffer.get(), bufferLen + 1); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Get TLV Value fail!")); + chip::CharSpan valueSpan(buffer.get(), bufferLen); + chip::JniReferences::GetInstance().CharToStringUTF(valueSpan, retValue); + return retValue; + } + case TLV::kTLVType_ByteString: { + uint32_t bufferLen = readerForGeneralValueObject.GetLength(); + std::unique_ptr buffer = std::unique_ptr(new uint8_t[bufferLen + 1]); + err = readerForGeneralValueObject.GetBytes(buffer.get(), bufferLen + 1); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogProgress(Controller, "Get TLV Value fail!")); + + jbyteArray valueByteArray = env->NewByteArray(static_cast(bufferLen)); + env->SetByteArrayRegion(valueByteArray, 0, static_cast(bufferLen), reinterpret_cast(buffer.get())); + + return static_cast(valueByteArray); + } + case TLV::kTLVType_Array: { + TLV::TLVType containerType; + err = readerForGeneralValueObject.EnterContainer(containerType); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "EnterContainer fail! : %" CHIP_ERROR_FORMAT, err.Format())); + err = chip::JniReferences::GetInstance().CreateArrayList(retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "CreateArrayList fail! : %" CHIP_ERROR_FORMAT, err.Format())); + while (readerForGeneralValueObject.Next() == CHIP_NO_ERROR) + { + jobject inValue = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Can't parse general value : %" CHIP_ERROR_FORMAT, err.Format())); + err = chip::JniReferences::GetInstance().AddToList(retValue, inValue); + } + return retValue; + } + case TLV::kTLVType_List: { + TLV::TLVType containerType; + err = readerForGeneralValueObject.EnterContainer(containerType); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "EnterContainer fail! : %" CHIP_ERROR_FORMAT, err.Format())); + err = chip::JniReferences::GetInstance().CreateArrayList(retValue); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "CreateArrayList fail! : %" CHIP_ERROR_FORMAT, err.Format())); + while (readerForGeneralValueObject.Next() == CHIP_NO_ERROR) + { + jobject inValue = DecodeGeneralTLVValue(env, readerForGeneralValueObject, err); + VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, + ChipLogProgress(Controller, "Can't parse general value : %" CHIP_ERROR_FORMAT, err.Format())); + err = chip::JniReferences::GetInstance().AddToList(retValue, inValue); + } + return retValue; + } + case TLV::kTLVType_Null: { + return nullptr; + } + default: + err = CHIP_ERROR_WRONG_TLV_TYPE; + return nullptr; + } +} + jlong newConnectedDeviceCallback(JNIEnv * env, jobject self, jobject callback) { chip::DeviceLayer::StackLock lock;