| /* |
| * |
| * 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); |
| } |