2 * Copyright (c) 2020-2021 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
21 * Implementation of JNI bridge for CHIP Device Controller for Android apps
25 #include "AndroidBleApplicationDelegate.h"
26 #include "AndroidBleConnectionDelegate.h"
27 #include "AndroidBlePlatformDelegate.h"
28 #include "AndroidDeviceControllerWrapper.h"
29 #include "CHIPJNIError.h"
31 #include <app/chip-zcl-zpro-codec.h>
33 #include <ble/BleUUID.h>
34 #include <controller/CHIPDeviceController.h>
37 #include <support/CHIPMem.h>
38 #include <support/CodeUtils.h>
39 #include <support/ErrorStr.h>
40 #include <support/SafeInt.h>
41 #include <support/logging/CHIPLogging.h>
43 // Choose an approximation of PTHREAD_NULL if pthread.h doesn't define one.
45 #define PTHREAD_NULL 0
46 #endif // PTHREAD_NULL
49 using namespace chip::Inet;
50 using namespace chip::Controller;
52 #define JNI_METHOD(RETURN, METHOD_NAME) \
53 extern "C" JNIEXPORT RETURN JNICALL Java_chip_devicecontroller_ChipDeviceController_##METHOD_NAME
55 #define JNI_ANDROID_CHIP_STACK_METHOD(RETURN, METHOD_NAME) \
56 extern "C" JNIEXPORT RETURN JNICALL Java_chip_devicecontroller_AndroidChipStack_##METHOD_NAME
58 #define CDC_JNI_CALLBACK_LOCAL_REF_COUNT 256
60 static void GetCHIPDevice(JNIEnv * env, long wrapperHandle, uint64_t deviceId, Device ** device);
61 static void HandleNotifyChipConnectionClosed(BLE_CONNECTION_OBJECT connObj);
62 static bool HandleSendCharacteristic(BLE_CONNECTION_OBJECT connObj, const uint8_t * svcId, const uint8_t * charId,
63 const uint8_t * characteristicData, uint32_t characteristicDataLen);
64 static bool HandleSubscribeCharacteristic(BLE_CONNECTION_OBJECT connObj, const uint8_t * svcId, const uint8_t * charId);
65 static bool HandleUnsubscribeCharacteristic(BLE_CONNECTION_OBJECT connObj, const uint8_t * svcId, const uint8_t * charId);
66 static bool HandleCloseConnection(BLE_CONNECTION_OBJECT connObj);
67 static uint16_t HandleGetMTU(BLE_CONNECTION_OBJECT connObj);
68 static void HandleNewConnection(void * appState, const uint16_t discriminator);
69 static void ThrowError(JNIEnv * env, CHIP_ERROR errToThrow);
70 static void ReportError(JNIEnv * env, CHIP_ERROR cbErr, const char * cbName);
71 static void * IOThreadMain(void * arg);
72 static CHIP_ERROR GetClassRef(JNIEnv * env, const char * clsType, jclass & outCls);
73 static CHIP_ERROR N2J_ByteArray(JNIEnv * env, const uint8_t * inArray, uint32_t inArrayLen, jbyteArray & outArray);
74 static CHIP_ERROR N2J_Error(JNIEnv * env, CHIP_ERROR inErr, jthrowable & outEx);
79 System::Layer sSystemLayer;
80 Inet::InetLayer sInetLayer;
82 #if CONFIG_NETWORK_LAYER_BLE
83 Ble::BleLayer sBleLayer;
84 AndroidBleApplicationDelegate sBleApplicationDelegate;
85 AndroidBlePlatformDelegate sBlePlatformDelegate;
86 AndroidBleConnectionDelegate sBleConnectionDelegate;
89 pthread_mutex_t sStackLock = PTHREAD_MUTEX_INITIALIZER;
90 pthread_t sIOThread = PTHREAD_NULL;
91 bool sShutdown = false;
93 jclass sAndroidChipStackCls = NULL;
94 jclass sChipDeviceControllerExceptionCls = NULL;
96 /** A scoped lock/unlock around a mutex. */
97 class ScopedPthreadLock
100 ScopedPthreadLock(pthread_mutex_t * mutex) : mMutex(mutex) { pthread_mutex_lock(mMutex); }
101 ~ScopedPthreadLock() { pthread_mutex_unlock(mMutex); }
104 pthread_mutex_t * mMutex;
107 // Use StackUnlockGuard to temporarily unlock the CHIP BLE stack, e.g. when calling application
108 // or Android BLE code as a result of a BLE event.
109 struct StackUnlockGuard
111 StackUnlockGuard() { pthread_mutex_unlock(&sStackLock); }
112 ~StackUnlockGuard() { pthread_mutex_lock(&sStackLock); }
118 JniUtfString(JNIEnv * env, jstring string) : mEnv(env), mString(string) { mChars = env->GetStringUTFChars(string, 0); }
119 ~JniUtfString() { mEnv->ReleaseStringUTFChars(mString, mChars); }
121 const char * c_str() const { return mChars; }
132 JniByteArray(JNIEnv * env, jbyteArray array) :
133 mEnv(env), mArray(array), mData(env->GetByteArrayElements(array, nullptr)), mDataLength(env->GetArrayLength(array))
135 ~JniByteArray() { mEnv->ReleaseByteArrayElements(mArray, mData, 0); }
137 const jbyte * data() const { return mData; }
138 jsize size() const { return mDataLength; }
149 // NOTE: Remote device ID is in sync with the echo server device id
150 // At some point, we may want to add an option to connect to a device without
151 // knowing its id, because the ID can be learned on the first response that is received.
152 chip::NodeId kLocalDeviceId = chip::kTestControllerNodeId;
153 chip::NodeId kRemoteDeviceId = chip::kTestDeviceNodeId;
155 jint JNI_OnLoad(JavaVM * jvm, void * reserved)
157 CHIP_ERROR err = CHIP_NO_ERROR;
161 ChipLogProgress(Controller, "JNI_OnLoad() called");
163 chip::Platform::MemoryInit();
165 // Save a reference to the JVM. Will need this to call back into Java.
168 // Get a JNI environment object.
169 sJVM->GetEnv((void **) &env, JNI_VERSION_1_6);
171 ChipLogProgress(Controller, "Loading Java class references.");
173 // Get various class references need by the API.
174 err = GetClassRef(env, "chip/devicecontroller/AndroidChipStack", sAndroidChipStackCls);
176 err = GetClassRef(env, "chip/devicecontroller/ChipDeviceControllerException", sChipDeviceControllerExceptionCls);
178 ChipLogProgress(Controller, "Java class references loaded.");
180 // Initialize the CHIP System Layer.
181 err = sSystemLayer.Init(NULL);
184 // Initialize the CHIP Inet layer.
185 err = sInetLayer.Init(sSystemLayer, NULL);
187 ChipLogProgress(Controller, "Inet layer initialized.");
189 #if CONFIG_NETWORK_LAYER_BLE
190 ChipLogProgress(Controller, "BLE Layer being configured.");
192 // Initialize the BleApplicationDelegate
193 sBleApplicationDelegate.SetNotifyChipConnectionClosedCallback(HandleNotifyChipConnectionClosed);
194 // Initialize the BlePlatformDelegate
195 sBlePlatformDelegate.SetSendWriteRequestCallback(HandleSendCharacteristic);
196 sBlePlatformDelegate.SetSubscribeCharacteristicCallback(HandleSubscribeCharacteristic);
197 sBlePlatformDelegate.SetUnsubscribeCharacteristicCallback(HandleUnsubscribeCharacteristic);
198 sBlePlatformDelegate.SetCloseConnectionCallback(HandleCloseConnection);
199 sBlePlatformDelegate.SetGetMTUCallback(HandleGetMTU);
200 // Initialize the BleConnectionDelegate
201 sBleConnectionDelegate.SetNewConnectionCallback(HandleNewConnection);
203 ChipLogProgress(Controller, "Asking for BLE Layer initialization.");
204 // Initialize the BleLayer object.
205 err = sBleLayer.Init(&sBlePlatformDelegate, &sBleConnectionDelegate, &sBleApplicationDelegate, &sSystemLayer);
208 ChipLogProgress(Controller, "BLE was initialized.");
211 // Create and start the IO thread.
213 pthreadErr = pthread_create(&sIOThread, NULL, IOThreadMain, NULL);
214 VerifyOrExit(pthreadErr == 0, err = System::MapErrorPOSIX(pthreadErr));
217 if (err != CHIP_NO_ERROR)
219 ThrowError(env, err);
220 JNI_OnUnload(jvm, reserved);
223 return (err == CHIP_NO_ERROR) ? JNI_VERSION_1_6 : JNI_ERR;
226 void JNI_OnUnload(JavaVM * jvm, void * reserved)
228 ChipLogProgress(Controller, "JNI_OnUnload() called");
230 // If the IO thread has been started, shut it down and wait for it to exit.
231 if (sIOThread != PTHREAD_NULL)
234 sSystemLayer.WakeSelect();
235 pthread_join(sIOThread, NULL);
238 #if CONFIG_NETWORK_LAYER_BLE
239 sBleLayer.Shutdown();
242 sSystemLayer.Shutdown();
243 sInetLayer.Shutdown();
246 chip::Platform::MemoryShutdown();
249 JNI_METHOD(jlong, newDeviceController)(JNIEnv * env, jobject self)
251 CHIP_ERROR err = CHIP_NO_ERROR;
252 AndroidDeviceControllerWrapper * wrapper = NULL;
255 ChipLogProgress(Controller, "newDeviceController() called");
257 wrapper = AndroidDeviceControllerWrapper::AllocateNew(sJVM, self, kLocalDeviceId, &sSystemLayer, &sInetLayer, &err);
260 result = wrapper->ToJNIHandle();
263 if (err != CHIP_NO_ERROR)
270 if (err != CHIP_JNI_ERROR_EXCEPTION_THROWN)
272 ThrowError(env, err);
279 JNI_METHOD(void, pairDevice)(JNIEnv * env, jobject self, jlong handle, jlong deviceId, jint connObj, jlong pinCode)
281 CHIP_ERROR err = CHIP_NO_ERROR;
282 AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);
284 ChipLogProgress(Controller, "pairDevice() called with device ID, connection object, and pincode");
287 ScopedPthreadLock lock(&sStackLock);
288 sBleLayer.mAppState = (void *) self;
289 RendezvousParameters params = RendezvousParameters()
290 .SetSetupPINCode(pinCode)
291 .SetConnectionObject(reinterpret_cast<BLE_CONNECTION_OBJECT>(connObj))
292 .SetBleLayer(&sBleLayer)
293 .SetPeerAddress(Transport::PeerAddress::BLE());
294 err = wrapper->Controller()->PairDevice(deviceId, params);
297 if (err != CHIP_NO_ERROR)
299 ChipLogError(Controller, "Failed to pair the device.");
300 ThrowError(env, err);
304 JNI_METHOD(void, unpairDevice)(JNIEnv * env, jobject self, jlong handle, jlong deviceId)
306 CHIP_ERROR err = CHIP_NO_ERROR;
307 AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);
309 ChipLogProgress(Controller, "unpairDevice() called with device ID");
312 ScopedPthreadLock lock(&sStackLock);
313 err = wrapper->Controller()->UnpairDevice(deviceId);
316 if (err != CHIP_NO_ERROR)
318 ChipLogError(Controller, "Failed to unpair the device.");
319 ThrowError(env, err);
323 JNI_METHOD(void, stopDevicePairing)(JNIEnv * env, jobject self, jlong handle, jlong deviceId)
325 CHIP_ERROR err = CHIP_NO_ERROR;
326 AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);
328 ChipLogProgress(Controller, "stopDevicePairing() called with device ID");
331 ScopedPthreadLock lock(&sStackLock);
332 err = wrapper->Controller()->StopPairing(deviceId);
335 if (err != CHIP_NO_ERROR)
337 ChipLogError(Controller, "Failed to unpair the device.");
338 ThrowError(env, err);
342 JNI_METHOD(void, sendWiFiCredentials)(JNIEnv * env, jobject self, jlong handle, jstring ssid, jstring password)
344 JniUtfString ssidStr(env, ssid);
345 JniUtfString passwordStr(env, password);
347 ChipLogProgress(Controller, "Sending Wi-Fi credentials for: %s", ssidStr.c_str());
349 ScopedPthreadLock lock(&sStackLock);
350 AndroidDeviceControllerWrapper::FromJNIHandle(handle)->SendNetworkCredentials(ssidStr.c_str(), passwordStr.c_str());
354 JNI_METHOD(void, sendThreadCredentials)
355 (JNIEnv * env, jobject self, jlong handle, jint channel, jint panId, jbyteArray xpanId, jbyteArray masterKey)
357 using namespace chip::DeviceLayer::Internal;
359 JniByteArray xpanIdBytes(env, xpanId);
360 JniByteArray masterKeyBytes(env, masterKey);
362 VerifyOrReturn(CanCastTo<uint8_t>(channel), ChipLogError(Controller, "sendThreadCredentials() called with invalid Channel"));
363 VerifyOrReturn(CanCastTo<uint16_t>(panId), ChipLogError(Controller, "sendThreadCredentials() called with invalid PAN ID"));
364 VerifyOrReturn(xpanIdBytes.size() <= static_cast<jsize>(kThreadExtendedPANIdLength),
365 ChipLogError(Controller, "sendThreadCredentials() called with invalid XPAN ID"));
366 VerifyOrReturn(masterKeyBytes.size() <= static_cast<jsize>(kThreadMasterKeyLength),
367 ChipLogError(Controller, "sendThreadCredentials() called with invalid Master Key"));
369 DeviceNetworkInfo threadData = {};
370 threadData.ThreadChannel = channel;
371 threadData.ThreadPANId = panId;
372 threadData.FieldPresent.ThreadExtendedPANId = 1;
373 memcpy(threadData.ThreadExtendedPANId, xpanIdBytes.data(), xpanIdBytes.size());
374 memcpy(threadData.ThreadMasterKey, masterKeyBytes.data(), masterKeyBytes.size());
376 ScopedPthreadLock lock(&sStackLock);
377 AndroidDeviceControllerWrapper::FromJNIHandle(handle)->SendThreadCredentials(threadData);
380 JNI_METHOD(void, pairTestDeviceWithoutSecurity)(JNIEnv * env, jobject self, jlong handle, jstring deviceAddr)
382 CHIP_ERROR err = CHIP_NO_ERROR;
383 AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);
384 chip::Inet::IPAddress deviceIPAddr;
386 ChipLogProgress(Controller, "pairTestDeviceWithoutSecurity() called with IP Address");
388 const char * deviceAddrStr = env->GetStringUTFChars(deviceAddr, 0);
389 deviceIPAddr.FromString(deviceAddrStr, deviceIPAddr);
390 env->ReleaseStringUTFChars(deviceAddr, deviceAddrStr);
393 ScopedPthreadLock lock(&sStackLock);
394 Controller::SerializedDevice mSerializedTestDevice;
395 err = wrapper->Controller()->PairTestDeviceWithoutSecurity(kRemoteDeviceId, chip::Transport::PeerAddress::UDP(deviceIPAddr),
396 mSerializedTestDevice);
399 if (err != CHIP_NO_ERROR)
401 ChipLogError(Controller, "Failed to connect to device.");
402 ThrowError(env, err);
406 JNI_METHOD(void, disconnectDevice)(JNIEnv * env, jobject self, jlong handle, jlong deviceId)
408 AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);
409 CHIP_ERROR err = CHIP_NO_ERROR;
410 Device * chipDevice = nullptr;
412 ChipLogProgress(Controller, "disconnectDevice() called with deviceId");
415 ScopedPthreadLock lock(&sStackLock);
416 err = wrapper->Controller()->GetDevice(deviceId, &chipDevice);
419 if (err != CHIP_NO_ERROR || !chipDevice)
421 ChipLogError(Controller, "Failed to get paired device.");
422 ThrowError(env, err);
425 wrapper->Controller()->ReleaseDevice(chipDevice);
428 JNI_METHOD(jboolean, isActive)(JNIEnv * env, jobject self, jlong handle)
430 Device * chipDevice = reinterpret_cast<Device *>(handle);
433 ScopedPthreadLock lock(&sStackLock);
434 return chipDevice->IsActive();
438 void GetCHIPDevice(JNIEnv * env, long wrapperHandle, uint64_t deviceId, Device ** chipDevice)
440 AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(wrapperHandle);
441 CHIP_ERROR err = CHIP_NO_ERROR;
444 ScopedPthreadLock lock(&sStackLock);
445 err = wrapper->Controller()->GetDevice(deviceId, chipDevice);
448 if (err != CHIP_NO_ERROR || !chipDevice)
450 ChipLogError(Controller, "Failed to get paired device.");
451 ThrowError(env, err);
455 JNI_METHOD(jstring, getIpAddress)(JNIEnv * env, jobject self, jlong handle, jlong deviceId)
457 Device * chipDevice = nullptr;
459 GetCHIPDevice(env, handle, deviceId, &chipDevice);
461 chip::Inet::IPAddress addr;
466 ScopedPthreadLock lock(&sStackLock);
467 if (!chipDevice->GetAddress(addr, port))
471 addr.ToString(addrStr);
472 return env->NewStringUTF(addrStr);
475 JNI_METHOD(void, sendMessage)(JNIEnv * env, jobject self, jlong handle, jlong deviceId, jstring messageObj)
477 CHIP_ERROR err = CHIP_NO_ERROR;
478 Device * chipDevice = nullptr;
480 ChipLogProgress(Controller, "sendMessage() called with device id and message object");
482 GetCHIPDevice(env, handle, deviceId, &chipDevice);
484 const char * messageStr = env->GetStringUTFChars(messageObj, 0);
485 size_t messageLen = strlen(messageStr);
488 ScopedPthreadLock lock(&sStackLock);
490 System::PacketBufferHandle buffer = System::PacketBufferHandle::NewWithData(messageStr, messageLen);
493 err = CHIP_ERROR_NO_MEMORY;
497 err = chipDevice->SendMessage(std::move(buffer));
501 env->ReleaseStringUTFChars(messageObj, messageStr);
503 if (err != CHIP_NO_ERROR)
505 ChipLogError(Controller, "Failed to send message.");
506 ThrowError(env, err);
510 JNI_METHOD(void, sendCommand)(JNIEnv * env, jobject self, jlong handle, jlong deviceId, jobject commandObj, jint aValue)
512 CHIP_ERROR err = CHIP_NO_ERROR;
513 Device * chipDevice = nullptr;
515 GetCHIPDevice(env, handle, deviceId, &chipDevice);
517 ChipLogProgress(Controller, "sendCommand() called");
519 jclass commandCls = env->GetObjectClass(commandObj);
520 jmethodID commandMethodID = env->GetMethodID(commandCls, "getValue", "()I");
521 jint commandID = env->CallIntMethod(commandObj, commandMethodID);
524 ScopedPthreadLock lock(&sStackLock);
525 System::PacketBufferHandle buffer;
527 // Hardcode endpoint to 1 for now
528 uint8_t endpoint = 1;
533 buffer = encodeOnOffClusterOffCommand(0, endpoint);
536 buffer = encodeOnOffClusterOnCommand(0, endpoint);
539 buffer = encodeOnOffClusterToggleCommand(0, endpoint);
542 buffer = encodeLevelControlClusterMoveToLevelCommand(0, endpoint, (uint8_t)(aValue & 0xff), 0xFFFF, 0, 0);
545 ChipLogError(Controller, "Unknown command: %d", commandID);
551 err = CHIP_ERROR_NO_MEMORY;
555 err = chipDevice->SendMessage(std::move(buffer));
559 if (err != CHIP_NO_ERROR)
561 ChipLogError(Controller, "Failed to send CHIP command.");
562 ThrowError(env, err);
566 JNI_METHOD(jboolean, openPairingWindow)(JNIEnv * env, jobject self, jlong handle, jlong deviceId, jint duration)
568 CHIP_ERROR err = CHIP_NO_ERROR;
569 Device * chipDevice = nullptr;
570 chip::SetupPayload setupPayload;
572 GetCHIPDevice(env, handle, deviceId, &chipDevice);
575 ScopedPthreadLock lock(&sStackLock);
576 err = chipDevice->OpenPairingWindow(duration, chip::Controller::Device::PairingWindowOption::kOriginalSetupCode,
580 if (err != CHIP_NO_ERROR)
582 ChipLogError(Controller, "OpenPairingWindow failed: %d", err);
589 static bool JavaBytesToUUID(JNIEnv * env, jbyteArray value, chip::Ble::ChipBleUUID & uuid)
591 const auto valueBegin = env->GetByteArrayElements(value, nullptr);
592 const auto valueLength = env->GetArrayLength(value);
595 VerifyOrExit(valueBegin && valueLength == sizeof(uuid.bytes), result = false);
596 memcpy(uuid.bytes, valueBegin, valueLength);
599 env->ReleaseByteArrayElements(value, valueBegin, 0);
603 JNI_ANDROID_CHIP_STACK_METHOD(void, handleIndicationReceived)
604 (JNIEnv * env, jobject self, jint conn, jbyteArray svcId, jbyteArray charId, jbyteArray value)
606 BLE_CONNECTION_OBJECT const connObj = reinterpret_cast<BLE_CONNECTION_OBJECT>(conn);
607 const auto valueBegin = env->GetByteArrayElements(value, nullptr);
608 const auto valueLength = env->GetArrayLength(value);
610 chip::Ble::ChipBleUUID svcUUID;
611 chip::Ble::ChipBleUUID charUUID;
612 chip::System::PacketBufferHandle buffer;
614 VerifyOrExit(JavaBytesToUUID(env, svcId, svcUUID),
615 ChipLogError(Controller, "handleIndicationReceived() called with invalid service ID"));
616 VerifyOrExit(JavaBytesToUUID(env, charId, charUUID),
617 ChipLogError(Controller, "handleIndicationReceived() called with invalid characteristic ID"));
619 buffer = System::PacketBufferHandle::NewWithData(valueBegin, valueLength);
620 VerifyOrExit(!buffer.IsNull(), ChipLogError(Controller, "Failed to allocate packet buffer"));
622 pthread_mutex_lock(&sStackLock);
623 sBleLayer.HandleIndicationReceived(connObj, &svcUUID, &charUUID, std::move(buffer));
624 pthread_mutex_unlock(&sStackLock);
626 env->ReleaseByteArrayElements(value, valueBegin, 0);
629 JNI_ANDROID_CHIP_STACK_METHOD(void, handleWriteConfirmation)
630 (JNIEnv * env, jobject self, jint conn, jbyteArray svcId, jbyteArray charId)
632 BLE_CONNECTION_OBJECT const connObj = reinterpret_cast<BLE_CONNECTION_OBJECT>(conn);
634 chip::Ble::ChipBleUUID svcUUID;
635 chip::Ble::ChipBleUUID charUUID;
636 VerifyOrExit(JavaBytesToUUID(env, svcId, svcUUID),
637 ChipLogError(Controller, "handleWriteConfirmation() called with invalid service ID"));
638 VerifyOrExit(JavaBytesToUUID(env, charId, charUUID),
639 ChipLogError(Controller, "handleWriteConfirmation() called with invalid characteristic ID"));
641 pthread_mutex_lock(&sStackLock);
642 sBleLayer.HandleWriteConfirmation(connObj, &svcUUID, &charUUID);
643 pthread_mutex_unlock(&sStackLock);
648 JNI_ANDROID_CHIP_STACK_METHOD(void, handleSubscribeComplete)
649 (JNIEnv * env, jobject self, jint conn, jbyteArray svcId, jbyteArray charId)
651 BLE_CONNECTION_OBJECT const connObj = reinterpret_cast<BLE_CONNECTION_OBJECT>(conn);
653 chip::Ble::ChipBleUUID svcUUID;
654 chip::Ble::ChipBleUUID charUUID;
655 VerifyOrExit(JavaBytesToUUID(env, svcId, svcUUID),
656 ChipLogError(Controller, "handleSubscribeComplete() called with invalid service ID"));
657 VerifyOrExit(JavaBytesToUUID(env, charId, charUUID),
658 ChipLogError(Controller, "handleSubscribeComplete() called with invalid characteristic ID"));
660 pthread_mutex_lock(&sStackLock);
661 sBleLayer.HandleSubscribeComplete(connObj, &svcUUID, &charUUID);
662 pthread_mutex_unlock(&sStackLock);
667 JNI_ANDROID_CHIP_STACK_METHOD(void, handleUnsubscribeComplete)
668 (JNIEnv * env, jobject self, jint conn, jbyteArray svcId, jbyteArray charId)
670 BLE_CONNECTION_OBJECT const connObj = reinterpret_cast<BLE_CONNECTION_OBJECT>(conn);
672 chip::Ble::ChipBleUUID svcUUID;
673 chip::Ble::ChipBleUUID charUUID;
674 VerifyOrExit(JavaBytesToUUID(env, svcId, svcUUID),
675 ChipLogError(Controller, "handleUnsubscribeComplete() called with invalid service ID"));
676 VerifyOrExit(JavaBytesToUUID(env, charId, charUUID),
677 ChipLogError(Controller, "handleUnsubscribeComplete() called with invalid characteristic ID"));
679 pthread_mutex_lock(&sStackLock);
680 sBleLayer.HandleUnsubscribeComplete(connObj, &svcUUID, &charUUID);
681 pthread_mutex_unlock(&sStackLock);
686 JNI_ANDROID_CHIP_STACK_METHOD(void, handleConnectionError)(JNIEnv * env, jobject self, jint conn)
688 BLE_CONNECTION_OBJECT const connObj = reinterpret_cast<BLE_CONNECTION_OBJECT>(conn);
690 pthread_mutex_lock(&sStackLock);
691 sBleLayer.HandleConnectionError(connObj, BLE_ERROR_APP_CLOSED_CONNECTION);
692 pthread_mutex_unlock(&sStackLock);
695 JNI_METHOD(void, deleteDeviceController)(JNIEnv * env, jobject self, jlong handle)
697 AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);
699 ChipLogProgress(Controller, "deleteDeviceController() called");
707 void HandleNotifyChipConnectionClosed(BLE_CONNECTION_OBJECT connObj)
709 StackUnlockGuard unlockGuard;
710 CHIP_ERROR err = CHIP_NO_ERROR;
715 ChipLogProgress(Controller, "Received NotifyChipConnectionClosed");
717 sJVM->GetEnv((void **) &env, JNI_VERSION_1_6);
719 method = env->GetStaticMethodID(sAndroidChipStackCls, "onNotifyChipConnectionClosed", "(I)V");
720 VerifyOrExit(method != NULL, err = CHIP_JNI_ERROR_METHOD_NOT_FOUND);
722 ChipLogProgress(Controller, "Calling Java NotifyChipConnectionClosed");
724 env->ExceptionClear();
725 tmpConnObj = reinterpret_cast<intptr_t>(connObj);
726 env->CallStaticVoidMethod(sAndroidChipStackCls, method, static_cast<jint>(tmpConnObj));
727 VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
730 if (err != CHIP_NO_ERROR)
732 ReportError(env, err, __FUNCTION__);
734 env->ExceptionClear();
737 bool HandleSendCharacteristic(BLE_CONNECTION_OBJECT connObj, const uint8_t * svcId, const uint8_t * charId,
738 const uint8_t * characteristicData, uint32_t characteristicDataLen)
740 StackUnlockGuard unlockGuard;
741 CHIP_ERROR err = CHIP_NO_ERROR;
744 jbyteArray charIdObj;
745 jbyteArray characteristicDataObj;
750 ChipLogProgress(Controller, "Received SendCharacteristic");
752 sJVM->GetEnv((void **) &env, JNI_VERSION_1_6);
754 err = N2J_ByteArray(env, svcId, 16, svcIdObj);
757 err = N2J_ByteArray(env, charId, 16, charIdObj);
760 err = N2J_ByteArray(env, characteristicData, characteristicDataLen, characteristicDataObj);
763 method = env->GetStaticMethodID(sAndroidChipStackCls, "onSendCharacteristic", "(I[B[B[B)Z");
764 VerifyOrExit(method != NULL, err = CHIP_JNI_ERROR_METHOD_NOT_FOUND);
766 ChipLogProgress(Controller, "Calling Java SendCharacteristic");
768 env->ExceptionClear();
769 tmpConnObj = reinterpret_cast<intptr_t>(connObj);
770 rc = (bool) env->CallStaticBooleanMethod(sAndroidChipStackCls, method, static_cast<jint>(tmpConnObj), svcIdObj, charIdObj,
771 characteristicDataObj);
772 VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
775 if (err != CHIP_NO_ERROR)
777 ReportError(env, err, __FUNCTION__);
780 env->ExceptionClear();
785 bool HandleSubscribeCharacteristic(BLE_CONNECTION_OBJECT connObj, const uint8_t * svcId, const uint8_t * charId)
787 StackUnlockGuard unlockGuard;
788 CHIP_ERROR err = CHIP_NO_ERROR;
791 jbyteArray charIdObj;
796 ChipLogProgress(Controller, "Received SubscribeCharacteristic");
798 sJVM->GetEnv((void **) &env, JNI_VERSION_1_6);
800 err = N2J_ByteArray(env, svcId, 16, svcIdObj);
803 err = N2J_ByteArray(env, charId, 16, charIdObj);
806 method = env->GetStaticMethodID(sAndroidChipStackCls, "onSubscribeCharacteristic", "(I[B[B)Z");
807 VerifyOrExit(method != NULL, err = CHIP_JNI_ERROR_METHOD_NOT_FOUND);
809 ChipLogProgress(Controller, "Calling Java SubscribeCharacteristic");
811 env->ExceptionClear();
812 tmpConnObj = reinterpret_cast<intptr_t>(connObj);
813 rc = (bool) env->CallStaticBooleanMethod(sAndroidChipStackCls, method, static_cast<jint>(tmpConnObj), svcIdObj, charIdObj);
814 VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
817 if (err != CHIP_NO_ERROR)
819 ReportError(env, err, __FUNCTION__);
822 env->ExceptionClear();
827 bool HandleUnsubscribeCharacteristic(BLE_CONNECTION_OBJECT connObj, const uint8_t * svcId, const uint8_t * charId)
829 StackUnlockGuard unlockGuard;
830 CHIP_ERROR err = CHIP_NO_ERROR;
833 jbyteArray charIdObj;
838 ChipLogProgress(Controller, "Received UnsubscribeCharacteristic");
840 sJVM->GetEnv((void **) &env, JNI_VERSION_1_6);
842 err = N2J_ByteArray(env, svcId, 16, svcIdObj);
845 err = N2J_ByteArray(env, charId, 16, charIdObj);
848 method = env->GetStaticMethodID(sAndroidChipStackCls, "onUnsubscribeCharacteristic", "(I[B[B)Z");
849 VerifyOrExit(method != NULL, err = CHIP_JNI_ERROR_METHOD_NOT_FOUND);
851 ChipLogProgress(Controller, "Calling Java UnsubscribeCharacteristic");
853 env->ExceptionClear();
854 tmpConnObj = reinterpret_cast<intptr_t>(connObj);
855 rc = (bool) env->CallStaticBooleanMethod(sAndroidChipStackCls, method, static_cast<jint>(tmpConnObj), svcIdObj, charIdObj);
856 VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
859 if (err != CHIP_NO_ERROR)
861 ReportError(env, err, __FUNCTION__);
864 env->ExceptionClear();
869 bool HandleCloseConnection(BLE_CONNECTION_OBJECT connObj)
871 StackUnlockGuard unlockGuard;
872 CHIP_ERROR err = CHIP_NO_ERROR;
878 ChipLogProgress(Controller, "Received CloseConnection");
880 sJVM->GetEnv((void **) &env, JNI_VERSION_1_6);
882 method = env->GetStaticMethodID(sAndroidChipStackCls, "onCloseConnection", "(I)Z");
883 VerifyOrExit(method != NULL, err = CHIP_JNI_ERROR_METHOD_NOT_FOUND);
885 ChipLogProgress(Controller, "Calling Java CloseConnection");
887 env->ExceptionClear();
888 tmpConnObj = reinterpret_cast<intptr_t>(connObj);
889 rc = (bool) env->CallStaticBooleanMethod(sAndroidChipStackCls, method, static_cast<jint>(tmpConnObj));
890 VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
893 if (err != CHIP_NO_ERROR)
895 ReportError(env, err, __FUNCTION__);
898 env->ExceptionClear();
902 uint16_t HandleGetMTU(BLE_CONNECTION_OBJECT connObj)
904 StackUnlockGuard unlockGuard;
905 CHIP_ERROR err = CHIP_NO_ERROR;
911 ChipLogProgress(Controller, "Received GetMTU");
913 sJVM->GetEnv((void **) &env, JNI_VERSION_1_6);
915 method = env->GetStaticMethodID(sAndroidChipStackCls, "onGetMTU", "(I)I");
916 VerifyOrExit(method != NULL, err = CHIP_JNI_ERROR_METHOD_NOT_FOUND);
918 ChipLogProgress(Controller, "Calling Java onGetMTU");
920 env->ExceptionClear();
921 tmpConnObj = reinterpret_cast<intptr_t>(connObj);
922 mtu = (int16_t) env->CallStaticIntMethod(sAndroidChipStackCls, method, static_cast<jint>(tmpConnObj));
923 VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
926 if (err != CHIP_NO_ERROR)
928 ReportError(env, err, __FUNCTION__);
931 env->ExceptionClear();
936 void HandleNewConnection(void * appState, const uint16_t discriminator)
938 StackUnlockGuard unlockGuard;
939 CHIP_ERROR err = CHIP_NO_ERROR;
942 jclass deviceControllerCls;
943 AndroidDeviceControllerWrapper * wrapper = reinterpret_cast<AndroidDeviceControllerWrapper *>(appState);
944 jobject self = wrapper->JavaObjectRef();
946 ChipLogProgress(Controller, "Received New Connection");
948 sJVM->GetEnv((void **) &env, JNI_VERSION_1_6);
950 deviceControllerCls = env->GetObjectClass(self);
951 VerifyOrExit(deviceControllerCls != NULL, err = CHIP_JNI_ERROR_TYPE_NOT_FOUND);
953 method = env->GetMethodID(deviceControllerCls, "onConnectDeviceComplete", "()V");
954 VerifyOrExit(method != NULL, err = CHIP_JNI_ERROR_METHOD_NOT_FOUND);
956 ChipLogProgress(Controller, "Calling Java onConnectDeviceComplete");
958 env->ExceptionClear();
959 env->CallVoidMethod(self, method);
960 VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
963 if (err != CHIP_NO_ERROR)
965 ReportError(env, err, __FUNCTION__);
967 env->ExceptionClear();
970 void * IOThreadMain(void * arg)
973 JavaVMAttachArgs attachArgs;
974 struct timeval sleepTime;
975 fd_set readFDs, writeFDs, exceptFDs;
978 // Attach the IO thread to the JVM as a daemon thread.
979 // This allows the JVM to shutdown without waiting for this thread to exit.
980 attachArgs.version = JNI_VERSION_1_6;
981 attachArgs.name = (char *) "CHIP Device Controller IO Thread";
982 attachArgs.group = NULL;
984 sJVM->AttachCurrentThreadAsDaemon(&env, (void *) &attachArgs);
986 sJVM->AttachCurrentThreadAsDaemon((void **) &env, (void *) &attachArgs);
989 // Set to true to quit the loop. This is currently unused.
990 std::atomic<bool> quit;
992 ChipLogProgress(Controller, "IO thread starting");
994 // Lock the stack to prevent collisions with Java threads.
995 pthread_mutex_lock(&sStackLock);
997 // Loop until we are told to exit.
998 while (!quit.load(std::memory_order_relaxed))
1003 FD_ZERO(&exceptFDs);
1005 sleepTime.tv_sec = 10;
1006 sleepTime.tv_usec = 0;
1008 // Collect the currently active file descriptors.
1009 sSystemLayer.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, sleepTime);
1010 sInetLayer.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, sleepTime);
1012 // Unlock the stack so that Java threads can make API calls.
1013 pthread_mutex_unlock(&sStackLock);
1015 // Wait for for I/O or for the next timer to expire.
1016 int selectRes = select(numFDs, &readFDs, &writeFDs, &exceptFDs, &sleepTime);
1018 // Break the loop if requested to shutdown.
1022 // Re-lock the stack.
1023 pthread_mutex_lock(&sStackLock);
1025 // Perform I/O and/or dispatch timers.
1026 sSystemLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
1027 sInetLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
1030 // Detach the thread from the JVM.
1031 sJVM->DetachCurrentThread();
1036 void ReportError(JNIEnv * env, CHIP_ERROR cbErr, const char * functName)
1038 if (cbErr == CHIP_JNI_ERROR_EXCEPTION_THROWN)
1040 ChipLogError(Controller, "Java exception thrown in %s", functName);
1041 env->ExceptionDescribe();
1045 const char * errStr;
1048 case CHIP_JNI_ERROR_TYPE_NOT_FOUND:
1049 errStr = "JNI type not found";
1051 case CHIP_JNI_ERROR_METHOD_NOT_FOUND:
1052 errStr = "JNI method not found";
1054 case CHIP_JNI_ERROR_FIELD_NOT_FOUND:
1055 errStr = "JNI field not found";
1058 errStr = ErrorStr(cbErr);
1061 ChipLogError(Controller, "Error in %s : %s", functName, errStr);
1065 void ThrowError(JNIEnv * env, CHIP_ERROR errToThrow)
1067 CHIP_ERROR err = CHIP_NO_ERROR;
1070 err = N2J_Error(env, errToThrow, ex);
1071 if (err == CHIP_NO_ERROR)
1077 CHIP_ERROR GetClassRef(JNIEnv * env, const char * clsType, jclass & outCls)
1079 CHIP_ERROR err = CHIP_NO_ERROR;
1082 cls = env->FindClass(clsType);
1083 VerifyOrExit(cls != NULL, err = CHIP_JNI_ERROR_TYPE_NOT_FOUND);
1085 outCls = (jclass) env->NewGlobalRef((jobject) cls);
1086 VerifyOrExit(outCls != NULL, err = CHIP_JNI_ERROR_TYPE_NOT_FOUND);
1089 env->DeleteLocalRef(cls);
1093 CHIP_ERROR N2J_ByteArray(JNIEnv * env, const uint8_t * inArray, uint32_t inArrayLen, jbyteArray & outArray)
1095 CHIP_ERROR err = CHIP_NO_ERROR;
1097 outArray = env->NewByteArray((int) inArrayLen);
1098 VerifyOrExit(outArray != NULL, err = CHIP_ERROR_NO_MEMORY);
1100 env->ExceptionClear();
1101 env->SetByteArrayRegion(outArray, 0, inArrayLen, (jbyte *) inArray);
1102 VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
1108 CHIP_ERROR N2J_Error(JNIEnv * env, CHIP_ERROR inErr, jthrowable & outEx)
1110 CHIP_ERROR err = CHIP_NO_ERROR;
1111 const char * errStr = NULL;
1112 jstring errStrObj = NULL;
1113 jmethodID constructor;
1115 constructor = env->GetMethodID(sChipDeviceControllerExceptionCls, "<init>", "(ILjava/lang/String;)V");
1116 VerifyOrExit(constructor != NULL, err = CHIP_JNI_ERROR_METHOD_NOT_FOUND);
1120 case CHIP_JNI_ERROR_TYPE_NOT_FOUND:
1121 errStr = "CHIP Device Controller Error: JNI type not found";
1123 case CHIP_JNI_ERROR_METHOD_NOT_FOUND:
1124 errStr = "CHIP Device Controller Error: JNI method not found";
1126 case CHIP_JNI_ERROR_FIELD_NOT_FOUND:
1127 errStr = "CHIP Device Controller Error: JNI field not found";
1130 errStr = ErrorStr(inErr);
1133 errStrObj = (errStr != NULL) ? env->NewStringUTF(errStr) : NULL;
1135 env->ExceptionClear();
1136 outEx = (jthrowable) env->NewObject(sChipDeviceControllerExceptionCls, constructor, (jint) inErr, errStrObj);
1137 VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
1140 env->DeleteLocalRef(errStrObj);