blob: c2649e1c124c8d07e281578e4b119ed4e8a675ec [file] [log] [blame]
/*
*
* 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 "AndroidCallbacks.h"
#include "JniReferences.h"
#include "JniTypeWrappers.h"
#include <jni.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ErrorStr.h>
#include <lib/support/logging/CHIPLogging.h>
using namespace chip::Controller;
GetConnectedDeviceCallback::GetConnectedDeviceCallback(jobject javaCallback) :
mOnSuccess(OnDeviceConnectedFn, this), mOnFailure(OnDeviceConnectionFailureFn, this)
{
JNIEnv * env = chip::Controller::JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
mJavaCallbackRef = env->NewGlobalRef(javaCallback);
if (mJavaCallbackRef == nullptr)
{
ChipLogError(Controller, "Could not create global reference for Java callback");
}
}
GetConnectedDeviceCallback::~GetConnectedDeviceCallback()
{
JNIEnv * env = chip::Controller::JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturn(env != nullptr, ChipLogError(Controller, "Could not get JNIEnv for current thread"));
env->DeleteGlobalRef(mJavaCallbackRef);
}
void GetConnectedDeviceCallback::OnDeviceConnectedFn(void * context, Device * device)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
auto * self = static_cast<GetConnectedDeviceCallback *>(context);
jobject javaCallback = self->mJavaCallbackRef;
jclass getConnectedDeviceCallbackCls = nullptr;
JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/GetConnectedDeviceCallbackJni$GetConnectedDeviceCallback",
getConnectedDeviceCallbackCls);
VerifyOrReturn(getConnectedDeviceCallbackCls != nullptr,
ChipLogError(Controller, "Could not find GetConnectedDeviceCallback class"));
JniClass getConnectedDeviceCallbackJniCls(getConnectedDeviceCallbackCls);
jmethodID successMethod;
JniReferences::GetInstance().FindMethod(env, javaCallback, "onDeviceConnected", "(J)V", &successMethod);
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");
env->CallVoidMethod(javaCallback, successMethod, reinterpret_cast<jlong>(device));
}
void GetConnectedDeviceCallback::OnDeviceConnectionFailureFn(void * context, NodeId nodeId, CHIP_ERROR error)
{
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
auto * self = static_cast<GetConnectedDeviceCallback *>(context);
jobject javaCallback = self->mJavaCallbackRef;
jclass getConnectedDeviceCallbackCls = nullptr;
JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/GetConnectedDeviceCallbackJni$GetConnectedDeviceCallback",
getConnectedDeviceCallbackCls);
VerifyOrReturn(getConnectedDeviceCallbackCls != nullptr,
ChipLogError(Controller, "Could not find GetConnectedDeviceCallback class"));
JniClass getConnectedDeviceCallbackJniCls(getConnectedDeviceCallbackCls);
jmethodID failureMethod;
JniReferences::GetInstance().FindMethod(env, javaCallback, "onConnectionFailure", "(JLjava/lang/Exception;)V", &failureMethod);
VerifyOrReturn(failureMethod != nullptr, ChipLogError(Controller, "Could not find onConnectionFailure method"));
// Create the exception to return.
jclass controllerExceptionCls;
CHIP_ERROR err = JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/ChipDeviceControllerException",
controllerExceptionCls);
VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Could not find exception type for onConnectionFailure"));
JniClass controllerExceptionJniCls(controllerExceptionCls);
jmethodID exceptionConstructor = env->GetMethodID(controllerExceptionCls, "<init>", "(ILjava/lang/String;)V");
jobject exception = env->NewObject(controllerExceptionCls, exceptionConstructor, error, env->NewStringUTF(ErrorStr(error)));
env->CallVoidMethod(javaCallback, failureMethod, nodeId, exception);
}