Skip to content

Commit

Permalink
[Android] Split cluster reads and read/default callbacks into separat…
Browse files Browse the repository at this point in the history
…e files (#11353)

* Split JNI clusters code

* Regenerate
  • Loading branch information
austinh0 authored and pull[bot] committed Apr 13, 2023
1 parent d04db6c commit 3617986
Show file tree
Hide file tree
Showing 14 changed files with 27,676 additions and 23,989 deletions.
94 changes: 94 additions & 0 deletions src/controller/java/AndroidClusterExceptions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
*
* Copyright (c) 2021 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 "AndroidClusterExceptions.h"

#include <lib/core/CHIPError.h>
#include <lib/support/CHIPJNIError.h>
#include <lib/support/JniReferences.h>
#include <lib/support/JniTypeWrappers.h>

namespace chip {

CHIP_ERROR AndroidClusterExceptions::CreateChipClusterException(JNIEnv * env, jint errorCode, jthrowable & outEx)
{
CHIP_ERROR err = CHIP_NO_ERROR;
jmethodID exceptionConstructor;
jclass clusterExceptionCls;

err = chip::JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/ChipClusterException", clusterExceptionCls);
VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_JNI_ERROR_TYPE_NOT_FOUND);
chip::JniClass clusterExceptionJniCls(clusterExceptionCls);

exceptionConstructor = env->GetMethodID(clusterExceptionCls, "<init>", "(I)V");
VerifyOrReturnError(exceptionConstructor != nullptr, CHIP_JNI_ERROR_TYPE_NOT_FOUND);

outEx = (jthrowable) env->NewObject(clusterExceptionCls, exceptionConstructor, errorCode);
VerifyOrReturnError(outEx != nullptr, CHIP_JNI_ERROR_TYPE_NOT_FOUND);

return err;
}

CHIP_ERROR AndroidClusterExceptions::CreateIllegalStateException(JNIEnv * env, const char message[], ChipError errorCode,
jthrowable & outEx)
{
CHIP_ERROR err = CHIP_NO_ERROR;
jmethodID exceptionConstructor;
jclass exceptionClass;
jstring errStr;

err = JniReferences::GetInstance().GetClassRef(env, "java/lang/IllegalStateException", exceptionClass);
VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_JNI_ERROR_TYPE_NOT_FOUND);
JniClass exceptionJniClass(exceptionClass);

exceptionConstructor = env->GetMethodID(exceptionClass, "<init>", "(Ljava/lang/String;)V");
VerifyOrReturnError(exceptionConstructor != nullptr, CHIP_JNI_ERROR_TYPE_NOT_FOUND);

char buf[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE];
snprintf(buf, sizeof(buf), "%s: %d", message, errorCode.AsInteger());
errStr = env->NewStringUTF(buf);

outEx = (jthrowable) env->NewObject(exceptionClass, exceptionConstructor, errStr);
VerifyOrReturnError(outEx != nullptr, CHIP_JNI_ERROR_TYPE_NOT_FOUND);

return err;
}

void AndroidClusterExceptions::ReturnIllegalStateException(JNIEnv * env, jobject callback, const char message[],
ChipError errorCode)
{
VerifyOrReturn(callback == nullptr, ChipLogDetail(Zcl, "Callback is null in ReturnIllegalStateException(), exiting early"));

CHIP_ERROR err = CHIP_NO_ERROR;
jmethodID method;
err = JniReferences::GetInstance().FindMethod(env, callback, "onError", "(Ljava/lang/Exception;)V", &method);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "Error throwing IllegalStateException %d", err.AsInteger());
return;
}

jthrowable exception;
err = CreateIllegalStateException(env, message, errorCode, exception);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "Error throwing IllegalStateException %d", err.AsInteger());
return;
}
env->CallVoidMethod(callback, method, exception);
}
} // namespace chip
55 changes: 55 additions & 0 deletions src/controller/java/AndroidClusterExceptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
*
* Copyright (c) 2021 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.
*/

#pragma once

#include <jni.h>
#include <lib/core/CHIPError.h>

namespace chip {
class AndroidClusterExceptions
{
public:
AndroidClusterExceptions(const AndroidClusterExceptions &) = delete;
AndroidClusterExceptions(const AndroidClusterExceptions &&) = delete;
AndroidClusterExceptions & operator=(const AndroidClusterExceptions &) = delete;

static AndroidClusterExceptions & GetInstance()
{
static AndroidClusterExceptions androidClusterExceptions;
return androidClusterExceptions;
}

/**
* Creates a Java ChipClusterException object in outEx.
*/
CHIP_ERROR CreateChipClusterException(JNIEnv * env, jint errorCode, jthrowable & outEx);

/**
* Creates a Java IllegalStateException in outEx.
*/
CHIP_ERROR CreateIllegalStateException(JNIEnv * env, const char message[], ChipError errorCode, jthrowable & outEx);

/**
* Creates an IllegalStateException and passes it to the Java onError() function of the provided callback object.
*/
void ReturnIllegalStateException(JNIEnv * env, jobject callback, const char message[], ChipError errorCode);

private:
AndroidClusterExceptions() {}
};
} // namespace chip
7 changes: 7 additions & 0 deletions src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,17 @@ shared_library("jni") {
"AndroidCallbacks-JNI.cpp",
"AndroidCallbacks.cpp",
"AndroidCallbacks.h",
"AndroidClusterExceptions.cpp",
"AndroidClusterExceptions.h",
"AndroidDeviceControllerWrapper.cpp",
"AndroidDeviceControllerWrapper.h",
"CHIPDefaultCallbacks.cpp",
"CHIPDefaultCallbacks.h",
"CHIPDeviceController-JNI.cpp",
"zap-generated/CHIPClusters-JNI.cpp",
"zap-generated/CHIPClustersRead-JNI.cpp",
"zap-generated/CHIPReadCallbacks.cpp",
"zap-generated/CHIPReadCallbacks.h",
]

deps = [
Expand Down
136 changes: 136 additions & 0 deletions src/controller/java/CHIPDefaultCallbacks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#include "CHIPDefaultCallbacks.h"
#include "AndroidClusterExceptions.h"

#include <lib/support/CHIPJNIError.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/JniReferences.h>
#include <platform/PlatformManager.h>

chip::CHIPDefaultSuccessCallback::CHIPDefaultSuccessCallback(jobject javaCallback) :
Callback::Callback<DefaultSuccessCallback>(CallbackFn, this)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
if (env == nullptr)
{
ChipLogError(Zcl, "Could not create global reference for Java callback");
return;
}
javaCallbackRef = env->NewGlobalRef(javaCallback);
if (javaCallbackRef == nullptr)
{
ChipLogError(Zcl, "Could not create global reference for Java callback");
}
}

chip::CHIPDefaultSuccessCallback::~CHIPDefaultSuccessCallback()
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
if (env == nullptr)
{
ChipLogError(Zcl, "Could not create global reference for Java callback");
return;
}
env->DeleteGlobalRef(javaCallbackRef);
}

void chip::CHIPDefaultSuccessCallback::CallbackFn(void * context)
{
chip::DeviceLayer::StackUnlock unlock;
CHIP_ERROR err = CHIP_NO_ERROR;
jmethodID javaMethod;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
jobject javaCallbackRef;
CHIPDefaultSuccessCallback * cppCallback = nullptr;

VerifyOrExit(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV);

cppCallback = reinterpret_cast<CHIPDefaultSuccessCallback *>(context);
VerifyOrExit(cppCallback != nullptr, err = CHIP_ERROR_INCORRECT_STATE);

// It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
javaCallbackRef = cppCallback->javaCallbackRef;
VerifyOrExit(javaCallbackRef != nullptr, err = CHIP_NO_ERROR);

err = JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onSuccess", "()V", &javaMethod);
SuccessOrExit(err);

env->ExceptionClear();
env->CallVoidMethod(javaCallbackRef, javaMethod);

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "Error invoking Java callback: %" CHIP_ERROR_FORMAT, err.Format());
}
if (cppCallback != nullptr)
{
cppCallback->Cancel();
delete cppCallback;
}
}

chip::CHIPDefaultFailureCallback::CHIPDefaultFailureCallback(jobject javaCallback) :
Callback::Callback<DefaultFailureCallback>(CallbackFn, this)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
if (env == nullptr)
{
ChipLogError(Zcl, "Could not create global reference for Java callback");
return;
}
javaCallbackRef = env->NewGlobalRef(javaCallback);
if (javaCallbackRef == nullptr)
{
ChipLogError(Zcl, "Could not create global reference for Java callback");
}
}

chip::CHIPDefaultFailureCallback::~CHIPDefaultFailureCallback()
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
if (env == nullptr)
{
ChipLogError(Zcl, "Could not create global reference for Java callback");
return;
}
env->DeleteGlobalRef(javaCallbackRef);
}

void chip::CHIPDefaultFailureCallback::CallbackFn(void * context, uint8_t status)
{
chip::DeviceLayer::StackUnlock unlock;
CHIP_ERROR err = CHIP_NO_ERROR;
jmethodID javaMethod;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
jobject javaCallbackRef;
jthrowable exception;
CHIPDefaultFailureCallback * cppCallback = nullptr;

VerifyOrExit(env != nullptr, err = CHIP_JNI_ERROR_NO_ENV);

cppCallback = reinterpret_cast<CHIPDefaultFailureCallback *>(context);
VerifyOrExit(cppCallback != nullptr, err = CHIP_ERROR_INCORRECT_STATE);

// It's valid for javaCallbackRef to be nullptr if the Java code passed in a null callback.
javaCallbackRef = cppCallback->javaCallbackRef;
VerifyOrExit(javaCallbackRef != nullptr, err = CHIP_NO_ERROR);

err = JniReferences::GetInstance().FindMethod(env, javaCallbackRef, "onError", "(Ljava/lang/Exception;)V", &javaMethod);
SuccessOrExit(err);

err = chip::AndroidClusterExceptions::GetInstance().CreateChipClusterException(env, status, exception);
SuccessOrExit(err);

env->ExceptionClear();
env->CallVoidMethod(javaCallbackRef, javaMethod, exception);
exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "Error invoking Java callback: %" CHIP_ERROR_FORMAT, err.Format());
}
if (cppCallback != nullptr)
{
cppCallback->Cancel();
delete cppCallback;
}
}
35 changes: 35 additions & 0 deletions src/controller/java/CHIPDefaultCallbacks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <jni.h>

#include <zap-generated/CHIPClientCallbacks.h>

namespace chip {

/** A success callback that delegates to the Java DefaultClusterCallback.onSuccess(). */
class CHIPDefaultSuccessCallback : public Callback::Callback<DefaultSuccessCallback>
{
public:
CHIPDefaultSuccessCallback(jobject javaCallback);

~CHIPDefaultSuccessCallback();

static void CallbackFn(void * context);

private:
jobject javaCallbackRef;
};

/** A failure callback that delegates to the Java DefaultClusterCallback.onError(). */
class CHIPDefaultFailureCallback : public Callback::Callback<DefaultFailureCallback>
{
public:
CHIPDefaultFailureCallback(jobject javaCallback);

~CHIPDefaultFailureCallback();

static void CallbackFn(void * context, uint8_t status);

private:
jobject javaCallbackRef;
};

} // namespace chip
Loading

0 comments on commit 3617986

Please sign in to comment.