/*
 *
 *    Copyright (c) 2020-2023 Project CHIP Authors
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
#include "AndroidCallbacks.h"
#include <controller/java/AndroidConnectionFailureExceptions.h>
#include <controller/java/AndroidControllerExceptions.h>
#ifdef USE_JAVA_TLV_ENCODE_DECODE
#include <controller/java/CHIPAttributeTLVValueDecoder.h>
#include <controller/java/CHIPEventTLVValueDecoder.h>
#endif
#include <app/EventLoggingTypes.h>
#include <jni.h>
#include <lib/core/ErrorStr.h>
#include <lib/support/CHIPJNIError.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/JniReferences.h>
#include <lib/support/jsontlv/JsonToTlv.h>
#include <lib/support/jsontlv/TlvToJson.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/PlatformManager.h>
#include <type_traits>

namespace chip {
namespace Controller {

static const int MILLIS_SINCE_BOOT  = 0;
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;

GetConnectedDeviceCallback::GetConnectedDeviceCallback(jobject wrapperCallback, jobject javaCallback,
                                                       const char * callbackClassSignature) :
    mOnSuccess(OnDeviceConnectedFn, this),
    mOnFailure(OnDeviceConnectionFailureFn, this), mCallbackClassSignature(callbackClassSignature)
{
    VerifyOrReturn(mWrapperCallbackRef.Init(wrapperCallback) == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not init mWrapperCallbackRef in %s", __func__));
    VerifyOrReturn(mJavaCallbackRef.Init(javaCallback) == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not init mJavaCallbackRef in %s", __func__));
}

GetConnectedDeviceCallback::~GetConnectedDeviceCallback() {}

void GetConnectedDeviceCallback::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr,
                                                     const SessionHandle & sessionHandle)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    auto * self = static_cast<GetConnectedDeviceCallback *>(context);
    VerifyOrReturn(self->mJavaCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mJavaCallbackRef is not valid in %s", __func__));
    jobject javaCallback = self->mJavaCallbackRef.ObjectRef();
    JniLocalReferenceScope scope(env);
    // Release wrapper's global ref so application can clean up the actual callback underneath.
    VerifyOrReturn(self->mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    JniGlobalReference globalRef(std::move(self->mWrapperCallbackRef));

    jclass getConnectedDeviceCallbackCls = nullptr;
    CHIP_ERROR err =
        JniReferences::GetInstance().GetLocalClassRef(env, self->mCallbackClassSignature, getConnectedDeviceCallbackCls);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "GetLocalClassRef Error! : %" CHIP_ERROR_FORMAT, err.Format()));
    VerifyOrReturn(getConnectedDeviceCallbackCls != nullptr,
                   ChipLogError(Controller, "Could not find GetConnectedDeviceCallback class"));

    jmethodID successMethod;
    err = JniReferences::GetInstance().FindMethod(env, javaCallback, "onDeviceConnected", "(J)V", &successMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "FindMethod Error! : %" CHIP_ERROR_FORMAT, err.Format()));
    VerifyOrReturn(successMethod != nullptr, ChipLogError(Controller, "Could not find onDeviceConnected method"));

    static_assert(sizeof(jlong) >= sizeof(void *), "Need to store a pointer in a Java handle");

    OperationalDeviceProxy * device = new OperationalDeviceProxy(&exchangeMgr, sessionHandle);
    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(javaCallback, successMethod, reinterpret_cast<jlong>(device));
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void GetConnectedDeviceCallback::OnDeviceConnectionFailureFn(void * context,
                                                             const OperationalSessionSetup::ConnnectionFailureInfo & failureInfo)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    auto * self = static_cast<GetConnectedDeviceCallback *>(context);
    VerifyOrReturn(self->mJavaCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mJavaCallbackRef is not valid in %s", __func__));
    jobject javaCallback = self->mJavaCallbackRef.ObjectRef();
    JniLocalReferenceScope scope(env);

    jclass getConnectedDeviceCallbackCls = nullptr;
    CHIP_ERROR err =
        JniReferences::GetInstance().GetLocalClassRef(env, self->mCallbackClassSignature, getConnectedDeviceCallbackCls);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "GetLocalClassRef Error! : %" CHIP_ERROR_FORMAT, err.Format()));
    VerifyOrReturn(getConnectedDeviceCallbackCls != nullptr,
                   ChipLogError(Controller, "Could not find GetConnectedDeviceCallback class"));

    jmethodID failureMethod;
    err = JniReferences::GetInstance().FindMethod(env, javaCallback, "onConnectionFailure", "(JLjava/lang/Exception;)V",
                                                  &failureMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "FindMethod Error! : %" CHIP_ERROR_FORMAT, err.Format()));
    VerifyOrReturn(failureMethod != nullptr, ChipLogError(Controller, "Could not find onConnectionFailure method"));

    jthrowable exception;
    err = AndroidConnectionFailureExceptions::GetInstance().CreateAndroidConnectionFailureException(
        env, failureInfo.error.Format(), failureInfo.error.AsInteger(), failureInfo.sessionStage, exception);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Controller,
                     "Unable to create AndroidControllerException on GetConnectedDeviceCallback::OnDeviceConnectionFailureFn: %s",
                     ErrorStr(err)));
    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(javaCallback, failureMethod, failureInfo.peerId.GetNodeId(), exception);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

CHIP_ERROR CreateOptional(chip::Optional<uint8_t> value, jobject & outObj)
{

    return CHIP_NO_ERROR;
}
jobject GetNodeStateObj(JNIEnv * env, const char * nodeStateClassSignature, jobject wrapperCallback)
{
    jmethodID getNodeStateMethod;
    CHIP_ERROR err =
        JniReferences::GetInstance().FindMethod(env, wrapperCallback, "getNodeState", nodeStateClassSignature, &getNodeStateMethod);
    VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogError(Controller, "Could not find getNodeState method"));

    DeviceLayer::StackUnlock unlock;
    jobject ret = env->CallObjectMethod(wrapperCallback, getNodeStateMethod);
    VerifyOrReturnValue(!env->ExceptionCheck(), nullptr, env->ExceptionDescribe());

    return ret;
}

ReportCallback::ReportCallback(jobject wrapperCallback, jobject subscriptionEstablishedCallback,
                               jobject resubscriptionAttemptCallback, const char * nodeStateClassSignature) :
    mClusterCacheAdapter(*this, Optional<EventNumber>::Missing(), false /*cacheData*/),
    mNodeStateClassSignature(nodeStateClassSignature)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    if (subscriptionEstablishedCallback != nullptr)
    {
        VerifyOrReturn(mSubscriptionEstablishedCallbackRef.Init(subscriptionEstablishedCallback) == CHIP_NO_ERROR,
                       ChipLogError(Controller, "Could not init mSubscriptionEstablishedCallbackRef in %s", __func__));
    }

    VerifyOrReturn(mWrapperCallbackRef.Init(wrapperCallback) == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not init mWrapperCallbackRef in %s", __func__));

    if (resubscriptionAttemptCallback != nullptr)
    {
        VerifyOrReturn(mResubscriptionAttemptCallbackRef.Init(resubscriptionAttemptCallback) == CHIP_NO_ERROR,
                       ChipLogError(Controller, "Could not init mResubscriptionAttemptCallbackRef in %s", __func__));
    }
}

ReportCallback::~ReportCallback()
{
    if (mReadClient != nullptr)
    {
        Platform::Delete(mReadClient);
    }
}

void ReportCallback::OnReportBegin()
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));

    JniLocalReferenceScope scope(env);

    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mReportCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    jmethodID onReportBeginMethod;
    CHIP_ERROR err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onReportBegin", "()V", &onReportBeginMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onReportBegin method"));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onReportBeginMethod);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void ReportCallback::OnDeallocatePaths(app::ReadPrepareParams && aReadPrepareParams)
{
    if (aReadPrepareParams.mpAttributePathParamsList != nullptr && aReadPrepareParams.mAttributePathParamsListSize != 0)
    {
        delete[] aReadPrepareParams.mpAttributePathParamsList;
        aReadPrepareParams.mpAttributePathParamsList    = nullptr;
        aReadPrepareParams.mAttributePathParamsListSize = 0;
    }

    if (aReadPrepareParams.mpEventPathParamsList != nullptr && aReadPrepareParams.mEventPathParamsListSize != 0)
    {
        delete[] aReadPrepareParams.mpEventPathParamsList;
        aReadPrepareParams.mpEventPathParamsList    = nullptr;
        aReadPrepareParams.mEventPathParamsListSize = 0;
    }

    if (aReadPrepareParams.mpDataVersionFilterList != nullptr && aReadPrepareParams.mDataVersionFilterListSize != 0)
    {
        delete[] aReadPrepareParams.mpDataVersionFilterList;
        aReadPrepareParams.mpDataVersionFilterList    = nullptr;
        aReadPrepareParams.mDataVersionFilterListSize = 0;
    }
}

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();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));

    JniLocalReferenceScope scope(env);
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    jmethodID onReportEndMethod;
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onReportEnd", "()V", &onReportEndMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onReportEnd method"));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onReportEndMethod);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

// Convert TLV blob to Json with structure, the element's tag is replaced with the actual attributeId.
CHIP_ERROR ConvertReportTlvToJson(const uint32_t id, TLV::TLVReader & data, std::string & json)
{
    TLV::TLVWriter writer;
    TLV::TLVReader readerForJavaTLV;
    uint32_t size = 0;
    readerForJavaTLV.Init(data);
    size_t bufferLen                  = readerForJavaTLV.GetTotalLength() + EXTRA_SPACE_FOR_ATTRIBUTE_TAG;
    std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
    writer.Init(buffer.get(), bufferLen);
    TLV::TLVType outer;

    ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer));
    TLV::Tag tag;
    ReturnErrorOnFailure(ConvertTlvTag(id, tag));
    ReturnErrorOnFailure(writer.CopyElement(tag, readerForJavaTLV));
    ReturnErrorOnFailure(writer.EndContainer(outer));
    size = writer.GetLengthWritten();

    TLV::TLVReader readerForJson;
    readerForJson.Init(buffer.get(), size);
    ReturnErrorOnFailure(readerForJson.Next());
    // Convert TLV to JSON
    return TlvToJson(readerForJson, json);
}

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();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(!aPath.IsListItemOperation(), ChipLogError(Controller, "Expect non-list item operation"); aPath.LogPath());

    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mReportCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();

    jobject nodeState = GetNodeStateObj(env, mNodeStateClassSignature, wrapperCallback);

    {
        // Add Attribute Status to wrapperCallback
        jmethodID addAttributeStatusMethod = nullptr;
        err = JniReferences::GetInstance().FindMethod(env, nodeState, "addAttributeStatus", "(IJJILjava/lang/Integer;)V",
                                                      &addAttributeStatusMethod);
        VerifyOrReturn(
            err == CHIP_NO_ERROR,
            ChipLogError(Controller, "Could not find addAttributeStatus method with error %" CHIP_ERROR_FORMAT, err.Format()));

        jobject jClusterState = nullptr;
        if (aStatus.mClusterStatus.HasValue())
        {
            err = JniReferences::GetInstance().CreateBoxedObject<jint>(
                "java/lang/Integer", "(I)V", static_cast<jint>(aStatus.mClusterStatus.Value()), jClusterState);
            VerifyOrReturn(err == CHIP_NO_ERROR,
                           ChipLogError(Controller, "Could not CreateBoxedObject with error %" CHIP_ERROR_FORMAT, err.Format()));
        }

        env->CallVoidMethod(nodeState, addAttributeStatusMethod, static_cast<jint>(aPath.mEndpointId),
                            static_cast<jlong>(aPath.mClusterId), static_cast<jlong>(aPath.mAttributeId),
                            static_cast<jint>(aStatus.mStatus), jClusterState);
        VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
    }

    VerifyOrReturn(aStatus.IsSuccess(), ChipLogError(Controller, "Receive bad status %s", ErrorStr(aStatus.ToChipError()));
                   aPath.LogPath());
    VerifyOrReturn(apData != nullptr, ChipLogError(Controller, "Receive empty apData"); aPath.LogPath());

    TLV::TLVReader readerForJavaTLV;
    readerForJavaTLV.Init(*apData);

    jobject value = nullptr;
#ifdef USE_JAVA_TLV_ENCODE_DECODE
    TLV::TLVReader readerForJavaObject;
    readerForJavaObject.Init(*apData);

    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;
    }

    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Fail to decode attribute with error %s", ErrorStr(err));
                   aPath.LogPath());
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
#endif
    // Create TLV byte array to pass to Java layer
    size_t bufferLen                  = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
    std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
    uint32_t size                     = 0;

    // The TLVReader's read head is not pointing to the first element in the container, instead of the container itself, use
    // a TLVWriter to get a TLV with a normalized TLV buffer (Wrapped with an anonymous tag, no extra "end of container" tag
    // at the end.)
    TLV::TLVWriter writer;
    writer.Init(buffer.get(), bufferLen);
    err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Fail to copy tlv element with error %s", ErrorStr(err));
                   aPath.LogPath());
    size = writer.GetLengthWritten();
    chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), static_cast<jint>(size));

    // Convert TLV to JSON
    std::string json;
    err = ConvertReportTlvToJson(static_cast<uint32_t>(aPath.mAttributeId), *apData, json);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Fail to convert report tlv to json with error %s", ErrorStr(err));
                   aPath.LogPath());
    UtfString jsonString(env, json.c_str());

    // Add AttributeState to wrapperCallback
    jmethodID addAttributeMethod;
    err = JniReferences::GetInstance().FindMethod(env, nodeState, "addAttribute", "(IJJLjava/lang/Object;[BLjava/lang/String;)V",
                                                  &addAttributeMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not find addAttribute method with error %s", ErrorStr(err)));
    env->CallVoidMethod(nodeState, addAttributeMethod, static_cast<jint>(aPath.mEndpointId), static_cast<jlong>(aPath.mClusterId),
                        static_cast<jlong>(aPath.mAttributeId), value, jniByteArray.jniValue(), jsonString.jniValue());
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());

    UpdateClusterDataVersion();
}

void ReportCallback::UpdateClusterDataVersion()
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    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;
    }

    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mReportCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    jobject nodeState       = GetNodeStateObj(env, mNodeStateClassSignature, wrapperCallback);

    // SetDataVersion to NodeState
    jmethodID setDataVersionMethod;
    CHIP_ERROR err = JniReferences::GetInstance().FindMethod(env, nodeState, "setDataVersion", "(IJJ)V", &setDataVersionMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find setDataVersion method"));
    env->CallVoidMethod(nodeState, setDataVersionMethod, static_cast<jint>(lastConcreteClusterPath.mEndpointId),
                        static_cast<jlong>(lastConcreteClusterPath.mClusterId), static_cast<jlong>(committedDataVersion.Value()));
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

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();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));

    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mReportCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    jobject nodeState       = GetNodeStateObj(env, mNodeStateClassSignature, wrapperCallback);
    if (apStatus != nullptr)
    {
        // Add Event Status to NodeState
        jmethodID addEventStatusMethod;
        err = JniReferences::GetInstance().FindMethod(env, nodeState, "addEventStatus", "(IJJILjava/lang/Integer;)V",
                                                      &addEventStatusMethod);
        VerifyOrReturn(
            err == CHIP_NO_ERROR,
            ChipLogError(Controller, "Could not find addEventStatus method with error %" CHIP_ERROR_FORMAT, err.Format()));

        jobject jClusterState = nullptr;
        if (apStatus->mClusterStatus.HasValue())
        {
            err = JniReferences::GetInstance().CreateBoxedObject<jint>(
                "java/lang/Integer", "(I)V", static_cast<jint>(apStatus->mClusterStatus.Value()), jClusterState);
            VerifyOrReturn(err == CHIP_NO_ERROR,
                           ChipLogError(Controller, "Could not CreateBoxedObject with error %" CHIP_ERROR_FORMAT, err.Format()));
        }

        env->CallVoidMethod(nodeState, addEventStatusMethod, static_cast<jint>(aEventHeader.mPath.mEndpointId),
                            static_cast<jlong>(aEventHeader.mPath.mClusterId), static_cast<jlong>(aEventHeader.mPath.mEventId),
                            static_cast<jint>(apStatus->mStatus), jClusterState);
        VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
        return;
    }
    VerifyOrReturn(apData != nullptr, ChipLogError(Controller, "Receive empty apData"); aEventHeader.LogPath());

    TLV::TLVReader readerForJavaTLV;
    readerForJavaTLV.Init(*apData);

    jlong eventNumber    = static_cast<jlong>(aEventHeader.mEventNumber);
    jint priorityLevel   = static_cast<jint>(aEventHeader.mPriorityLevel);
    jlong timestampValue = static_cast<jlong>(aEventHeader.mTimestamp.mValue);

    jint timestampType = 0;
    if (aEventHeader.mTimestamp.mType == app::Timestamp::Type::kSystem)
    {
        timestampType = static_cast<jint>(MILLIS_SINCE_BOOT);
    }
    else if (aEventHeader.mTimestamp.mType == app::Timestamp::Type::kEpoch)
    {
        timestampType = static_cast<jint>(MILLIS_SINCE_EPOCH);
    }
    else
    {
        ChipLogError(Controller, "Unsupported event timestamp type");
        aEventHeader.LogPath();
        return;
    }

    jobject value = nullptr;
#ifdef USE_JAVA_TLV_ENCODE_DECODE
    TLV::TLVReader readerForJavaObject;
    readerForJavaObject.Init(*apData);
    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;
    }
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Fail to decode event with error %s", ErrorStr(err));
                   aEventHeader.LogPath());
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
#endif

    // Create TLV byte array to pass to Java layer
    size_t bufferLen                  = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
    std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
    uint32_t size                     = 0;
    // The TLVReader's read head is not pointing to the first element in the container, instead of the container itself, use
    // a TLVWriter to get a TLV with a normalized TLV buffer (Wrapped with an anonymous tag, no extra "end of container" tag
    // at the end.)
    TLV::TLVWriter writer;
    writer.Init(buffer.get(), bufferLen);
    err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);

    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Fail to copy element with error %s", ErrorStr(err));
                   aEventHeader.LogPath());
    size = writer.GetLengthWritten();
    chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), static_cast<jint>(size));

    // Convert TLV to JSON
    std::string json;
    err = ConvertReportTlvToJson(static_cast<uint32_t>(aEventHeader.mPath.mEventId), *apData, json);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Fail to convert report tlv to Json with error %s", ErrorStr(err));
                   aEventHeader.LogPath());
    UtfString jsonString(env, json.c_str());

    jmethodID addEventMethod;
    err = JniReferences::GetInstance().FindMethod(env, nodeState, "addEvent", "(IJJJIIJLjava/lang/Object;[BLjava/lang/String;)V",
                                                  &addEventMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find addEvent method with error %s", ErrorStr(err));
                   aEventHeader.LogPath());
    env->CallVoidMethod(nodeState, addEventMethod, static_cast<jint>(aEventHeader.mPath.mEndpointId),
                        static_cast<jlong>(aEventHeader.mPath.mClusterId), static_cast<jlong>(aEventHeader.mPath.mEventId),
                        eventNumber, priorityLevel, timestampType, timestampValue, value, jniByteArray.jniValue(),
                        jsonString.jniValue());
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe(); aEventHeader.LogPath());
}

void ReportCallback::OnError(CHIP_ERROR aError)
{
    ReportError(nullptr, nullptr, aError);
}

void ReportCallback::OnDone(app::ReadClient *)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jmethodID onDoneMethod;
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    JniGlobalReference globalRef(std::move(mWrapperCallbackRef));

    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onDone", "()V", &onDoneMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onDone method"));

    if (mReadClient != nullptr)
    {
        Platform::Delete(mReadClient);
    }
    mReadClient = nullptr;

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onDoneMethod);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void ReportCallback::OnSubscriptionEstablished(SubscriptionId aSubscriptionId)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    DeviceLayer::StackUnlock unlock;
    VerifyOrReturn(mSubscriptionEstablishedCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, " mSubscriptionEstablishedCallbackRef is not valid in %s", __func__));
    CHIP_ERROR err =
        JniReferences::GetInstance().CallSubscriptionEstablished(mSubscriptionEstablishedCallbackRef.ObjectRef(), aSubscriptionId);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller, "CallSubscriptionEstablished error! : %" CHIP_ERROR_FORMAT, err.Format()));
}

CHIP_ERROR ReportCallback::OnResubscriptionNeeded(app::ReadClient * apReadClient, CHIP_ERROR aTerminationCause)
{
    JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NULL_OBJECT);
    ReturnErrorOnFailure(app::ReadClient::Callback::OnResubscriptionNeeded(apReadClient, aTerminationCause));
    JniLocalReferenceScope scope(env);
    jmethodID onResubscriptionAttemptMethod;
    VerifyOrReturnLogError(mResubscriptionAttemptCallbackRef.HasValidObjectRef(), CHIP_ERROR_INCORRECT_STATE);
    jobject resubscriptionAttemptCallbackRef = mResubscriptionAttemptCallbackRef.ObjectRef();
    ReturnLogErrorOnFailure(JniReferences::GetInstance().FindMethod(
        env, resubscriptionAttemptCallbackRef, "onResubscriptionAttempt", "(JJ)V", &onResubscriptionAttemptMethod));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(resubscriptionAttemptCallbackRef, onResubscriptionAttemptMethod,
                        static_cast<jlong>(aTerminationCause.AsInteger()),
                        static_cast<jlong>(apReadClient->ComputeTimeTillNextSubscription()));
    VerifyOrReturnError(!env->ExceptionCheck(), CHIP_JNI_ERROR_EXCEPTION_THROWN);
    return CHIP_NO_ERROR;
}

void ReportCallback::ReportError(const app::ConcreteAttributePath * attributePath, const app::ConcreteEventPath * eventPath,
                                 CHIP_ERROR err)
{
    ReportError(attributePath, eventPath, ErrorStr(err), err.AsInteger());
}

void ReportCallback::ReportError(const app::ConcreteAttributePath * attributePath, const app::ConcreteEventPath * eventPath,
                                 Protocols::InteractionModel::Status status)
{
    ReportError(attributePath, eventPath, "IM Status",
                static_cast<std::underlying_type_t<Protocols::InteractionModel::Status>>(status));
}

void ReportCallback::ReportError(const app::ConcreteAttributePath * attributePath, const app::ConcreteEventPath * eventPath,
                                 const char * message, ChipError::StorageType errorCode)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    jthrowable exception;
    err = AndroidControllerExceptions::GetInstance().CreateAndroidControllerException(env, message, errorCode, exception);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Controller, "Unable to create AndroidControllerException on ReportCallback::ReportError: %s", ErrorStr(err)));
    jmethodID onErrorMethod;
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onError", "(ZIJJZIJJLjava/lang/Exception;)V",
                                                  &onErrorMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to find onError method: %s", ErrorStr(err)));

    DeviceLayer::StackUnlock unlock;

    jboolean isAttributePath = JNI_FALSE;
    jint attributeEndpointId = static_cast<jint>(kInvalidEndpointId);
    jlong attributeClusterId = static_cast<jlong>(kInvalidClusterId);
    jlong attributeId        = static_cast<jlong>(kInvalidAttributeId);

    jboolean isEventPath = JNI_FALSE;
    jint eventEndpointId = static_cast<jint>(kInvalidEndpointId);
    jlong eventClusterId = static_cast<jlong>(kInvalidClusterId);
    jlong eventId        = static_cast<jlong>(kInvalidAttributeId);

    if (attributePath != nullptr)
    {
        isAttributePath     = JNI_TRUE;
        attributeEndpointId = static_cast<jint>(attributePath->mEndpointId);
        attributeClusterId  = static_cast<jlong>(attributePath->mClusterId);
        attributeId         = static_cast<jlong>(attributePath->mAttributeId);
    }

    if (eventPath != nullptr)
    {
        isEventPath     = JNI_TRUE;
        eventEndpointId = static_cast<jint>(eventPath->mEndpointId);
        eventClusterId  = static_cast<jlong>(eventPath->mClusterId);
        eventId         = static_cast<jlong>(eventPath->mEventId);
    }

    env->CallVoidMethod(wrapperCallback, onErrorMethod, isAttributePath, attributeEndpointId, attributeClusterId, attributeId,
                        isEventPath, eventEndpointId, eventClusterId, eventId, exception);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

WriteAttributesCallback::WriteAttributesCallback(jobject wrapperCallback) : mChunkedWriteCallback(this)
{
    VerifyOrReturn(mWrapperCallbackRef.Init(wrapperCallback) == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not init mWrapperCallbackRef for WriteAttributesCallback"));
}

WriteAttributesCallback::~WriteAttributesCallback()
{
    if (mWriteClient != nullptr)
    {
        Platform::Delete(mWriteClient);
    }
}

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();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);

    if (aStatus.mStatus != Protocols::InteractionModel::Status::Success)
    {
        ReportError(&aPath, aStatus.mStatus);
        return;
    }

    jmethodID onResponseMethod;
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onResponse", "(IJJ)V", &onResponseMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to find onError method: %s", ErrorStr(err)));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onResponseMethod, static_cast<jint>(aPath.mEndpointId),
                        static_cast<jlong>(aPath.mClusterId), static_cast<jlong>(aPath.mAttributeId));
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void WriteAttributesCallback::OnError(const app::WriteClient * apWriteClient, CHIP_ERROR aError)
{
    ReportError(nullptr, aError);
}

void WriteAttributesCallback::OnDone(app::WriteClient *)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jmethodID onDoneMethod;
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    JniGlobalReference globalRef(std::move(mWrapperCallbackRef));

    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onDone", "()V", &onDoneMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onDone method"));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onDoneMethod);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void WriteAttributesCallback::ReportError(const app::ConcreteAttributePath * attributePath, CHIP_ERROR err)
{
    ReportError(attributePath, ErrorStr(err), err.AsInteger());
}

void WriteAttributesCallback::ReportError(const app::ConcreteAttributePath * attributePath,
                                          Protocols::InteractionModel::Status status)
{
    ReportError(attributePath, "IM Status", static_cast<std::underlying_type_t<Protocols::InteractionModel::Status>>(status));
}

void WriteAttributesCallback::ReportError(const app::ConcreteAttributePath * attributePath, const char * message,
                                          ChipError::StorageType errorCode)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    ChipLogError(Controller, "WriteAttributesCallback::ReportError is called with %u", errorCode);
    jthrowable exception;
    err = AndroidControllerExceptions::GetInstance().CreateAndroidControllerException(env, message, errorCode, exception);
    VerifyOrReturn(err == CHIP_NO_ERROR,
                   ChipLogError(Controller,
                                "Unable to create AndroidControllerException on WriteAttributesCallback::ReportError: %s",
                                ErrorStr(err)));
    jmethodID onErrorMethod;
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onError", "(ZIJJLjava/lang/Exception;)V", &onErrorMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to find onError method: %s", ErrorStr(err)));

    jboolean isAttributePath = JNI_FALSE;
    jint attributeEndpointId = static_cast<jint>(kInvalidEndpointId);
    jlong attributeClusterId = static_cast<jlong>(kInvalidClusterId);
    jlong attributeId        = static_cast<jlong>(kInvalidAttributeId);

    if (attributePath != nullptr)
    {
        isAttributePath     = JNI_TRUE;
        attributeEndpointId = static_cast<jint>(attributePath->mEndpointId);
        attributeClusterId  = static_cast<jint>(attributePath->mClusterId);
        attributeId         = static_cast<jint>(attributePath->mAttributeId);
    }

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onErrorMethod, isAttributePath, attributeEndpointId, attributeClusterId, attributeId,
                        exception);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

InvokeCallback::InvokeCallback(jobject wrapperCallback)
{
    VerifyOrReturn(mWrapperCallbackRef.Init(wrapperCallback) == CHIP_NO_ERROR,
                   ChipLogError(Controller, "Could not init mWrapperCallbackRef for InvokeCallback"));
}

InvokeCallback::~InvokeCallback()
{
    if (mCommandSender != nullptr)
    {
        Platform::Delete(mCommandSender);
    }
}

void InvokeCallback::OnResponse(app::CommandSender * apCommandSender, const app::ConcreteCommandPath & aPath,
                                const app::StatusIB & aStatusIB, TLV::TLVReader * apData)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    jmethodID onResponseMethod;
    JniLocalReferenceScope scope(env);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to create Java InvokeElement: %s", ErrorStr(err)));
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallbackRef = mWrapperCallbackRef.ObjectRef();
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallbackRef, "onResponse", "(IJJ[BLjava/lang/String;J)V",
                                                  &onResponseMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to find onResponse method: %s", ErrorStr(err)));

    DeviceLayer::StackUnlock unlock;

    if (apData != nullptr)
    {
        TLV::TLVReader readerForJavaTLV;
        TLV::TLVReader readerForJson;
        readerForJavaTLV.Init(*apData);

        // Create TLV byte array to pass to Java layer
        size_t bufferLen                  = readerForJavaTLV.GetRemainingLength() + readerForJavaTLV.GetLengthRead();
        std::unique_ptr<uint8_t[]> buffer = std::unique_ptr<uint8_t[]>(new uint8_t[bufferLen]);
        uint32_t size                     = 0;

        TLV::TLVWriter writer;
        writer.Init(buffer.get(), bufferLen);
        err = writer.CopyElement(TLV::AnonymousTag(), readerForJavaTLV);
        VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Failed CopyElement: %" CHIP_ERROR_FORMAT, err.Format()));
        size = writer.GetLengthWritten();

        chip::ByteArray jniByteArray(env, reinterpret_cast<jbyte *>(buffer.get()), static_cast<jint>(size));

        // Convert TLV to JSON
        std::string json;
        readerForJson.Init(buffer.get(), size);
        err = readerForJson.Next();
        VerifyOrReturn(err == CHIP_NO_ERROR,
                       ChipLogError(Controller, "Failed readerForJson next: %" CHIP_ERROR_FORMAT, err.Format()));
        err = TlvToJson(readerForJson, json);
        VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Failed TlvToJson: %" CHIP_ERROR_FORMAT, err.Format()));
        UtfString jsonString(env, json.c_str());

        env->CallVoidMethod(wrapperCallbackRef, onResponseMethod, static_cast<jint>(aPath.mEndpointId),
                            static_cast<jlong>(aPath.mClusterId), static_cast<jlong>(aPath.mCommandId), jniByteArray.jniValue(),
                            jsonString.jniValue(),
                            aStatusIB.mClusterStatus.HasValue() ? static_cast<jlong>(aStatusIB.mClusterStatus.Value())
                                                                : static_cast<jlong>(Protocols::InteractionModel::Status::Success));
    }
    else
    {
        env->CallVoidMethod(wrapperCallbackRef, onResponseMethod, static_cast<jint>(aPath.mEndpointId),
                            static_cast<jlong>(aPath.mClusterId), static_cast<jlong>(aPath.mCommandId), nullptr, nullptr,
                            aStatusIB.mClusterStatus.HasValue() ? static_cast<jlong>(aStatusIB.mClusterStatus.Value())
                                                                : static_cast<jlong>(Protocols::InteractionModel::Status::Success));
    }

    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void InvokeCallback::OnError(const app::CommandSender * apCommandSender, CHIP_ERROR aError)
{
    ReportError(aError);
}

void InvokeCallback::OnDone(app::CommandSender * apCommandSender)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    jmethodID onDoneMethod;
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    JniGlobalReference globalRef(std::move(mWrapperCallbackRef));

    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onDone", "()V", &onDoneMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find onDone method"));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onDoneMethod);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

void InvokeCallback::ReportError(CHIP_ERROR err)
{
    ReportError(ErrorStr(err), err.AsInteger());
}

void InvokeCallback::ReportError(Protocols::InteractionModel::Status status)
{
    ReportError("IM Status", static_cast<std::underlying_type_t<Protocols::InteractionModel::Status>>(status));
}

void InvokeCallback::ReportError(const char * message, ChipError::StorageType errorCode)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    JNIEnv * env   = JniReferences::GetInstance().GetEnvForCurrentThread();
    VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
    JniLocalReferenceScope scope(env);
    ChipLogError(Controller, "InvokeCallback::ReportError is called with %u", errorCode);
    jthrowable exception;
    err = AndroidControllerExceptions::GetInstance().CreateAndroidControllerException(env, message, errorCode, exception);
    VerifyOrReturn(
        err == CHIP_NO_ERROR,
        ChipLogError(Controller, "Unable to create AndroidControllerException: %s on InvokeCallback::ReportError", ErrorStr(err)));

    jmethodID onErrorMethod;
    VerifyOrReturn(mWrapperCallbackRef.HasValidObjectRef(),
                   ChipLogError(Controller, "mWrapperCallbackRef is not valid in %s", __func__));
    jobject wrapperCallback = mWrapperCallbackRef.ObjectRef();
    err = JniReferences::GetInstance().FindMethod(env, wrapperCallback, "onError", "(Ljava/lang/Exception;)V", &onErrorMethod);
    VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Unable to find onError method: %s", ErrorStr(err)));

    DeviceLayer::StackUnlock unlock;
    env->CallVoidMethod(wrapperCallback, onErrorMethod, exception);
    VerifyOrReturn(!env->ExceptionCheck(), env->ExceptionDescribe());
}

jlong newConnectedDeviceCallback(JNIEnv * env, jobject self, jobject callback)
{
    chip::DeviceLayer::StackLock lock;
    GetConnectedDeviceCallback * connectedDeviceCallback = chip::Platform::New<GetConnectedDeviceCallback>(self, callback);
    return reinterpret_cast<jlong>(connectedDeviceCallback);
}

void deleteConnectedDeviceCallback(JNIEnv * env, jobject self, jlong callbackHandle)
{
    chip::DeviceLayer::StackLock lock;
    GetConnectedDeviceCallback * connectedDeviceCallback = reinterpret_cast<GetConnectedDeviceCallback *>(callbackHandle);
    VerifyOrReturn(connectedDeviceCallback != nullptr, ChipLogError(Controller, "GetConnectedDeviceCallback handle is nullptr"));
    chip::Platform::Delete(connectedDeviceCallback);
}

jlong newReportCallback(JNIEnv * env, jobject self, jobject subscriptionEstablishedCallbackJava,
                        jobject resubscriptionAttemptCallbackJava, const char * nodeStateClassSignature)
{
    chip::DeviceLayer::StackLock lock;
    ReportCallback * reportCallback = chip::Platform::New<ReportCallback>(
        self, subscriptionEstablishedCallbackJava, resubscriptionAttemptCallbackJava, nodeStateClassSignature);
    return reinterpret_cast<jlong>(reportCallback);
}

void deleteReportCallback(JNIEnv * env, jobject self, jlong callbackHandle)
{
    chip::DeviceLayer::StackLock lock;
    ReportCallback * reportCallback = reinterpret_cast<ReportCallback *>(callbackHandle);
    VerifyOrReturn(reportCallback != nullptr, ChipLogError(Controller, "ReportCallback handle is nullptr"));
    chip::Platform::Delete(reportCallback);
}

jlong newWriteAttributesCallback(JNIEnv * env, jobject self)
{
    chip::DeviceLayer::StackLock lock;
    WriteAttributesCallback * writeAttributesCallback = chip::Platform::New<WriteAttributesCallback>(self);
    return reinterpret_cast<jlong>(writeAttributesCallback);
}

void deleteWriteAttributesCallback(JNIEnv * env, jobject self, jlong callbackHandle)
{
    chip::DeviceLayer::StackLock lock;
    WriteAttributesCallback * writeAttributesCallback = reinterpret_cast<WriteAttributesCallback *>(callbackHandle);
    VerifyOrReturn(writeAttributesCallback != nullptr, ChipLogError(Controller, "WriteAttributesCallback handle is nullptr"));
    chip::Platform::Delete(writeAttributesCallback);
}

jlong newInvokeCallback(JNIEnv * env, jobject self)
{
    chip::DeviceLayer::StackLock lock;
    InvokeCallback * invokeCallback = chip::Platform::New<InvokeCallback>(self);
    return reinterpret_cast<jlong>(invokeCallback);
}

void deleteInvokeCallback(JNIEnv * env, jobject self, jlong callbackHandle)
{
    chip::DeviceLayer::StackLock lock;
    InvokeCallback * invokeCallback = reinterpret_cast<InvokeCallback *>(callbackHandle);
    VerifyOrReturn(invokeCallback != nullptr, ChipLogError(Controller, "InvokeCallback handle is nullptr"));
    chip::Platform::Delete(invokeCallback);
}

} // namespace Controller
} // namespace chip
