From 2b76339faa2590a090281896c6dfd8222076749c Mon Sep 17 00:00:00 2001 From: chulspro Date: Fri, 28 Jul 2023 00:35:04 +0900 Subject: [PATCH] [Android] Apply 'AppDelegate' for android app server (#28286) * Apply 'AppDelegate' for android app server * Add 'starAppWithDelegate' api * Add 'ChipAppServerDelegate' interface Signed-off-by: Jaehoon You Signed-off-by: Charles Kim * Restyled by whitespace * Restyled by google-java-format * Restyled by clang-format Signed-off-by: Charles Kim * Restyled by google-java-format Signed-off-by: Charles Kim --------- Signed-off-by: Jaehoon You Signed-off-by: Charles Kim Co-authored-by: Jaehoon You Co-authored-by: Restyled.io --- .../device/app/core/matter/MatterApp.kt | 48 ++++++ .../server/java/AndroidAppServerWrapper.cpp | 7 +- src/app/server/java/AndroidAppServerWrapper.h | 3 +- src/app/server/java/BUILD.gn | 3 + src/app/server/java/CHIPAppServer-JNI.cpp | 25 +++ src/app/server/java/ChipAppServerDelegate.cpp | 159 ++++++++++++++++++ src/app/server/java/ChipAppServerDelegate.h | 44 +++++ .../src/chip/appserver/ChipAppServer.java | 2 + .../chip/appserver/ChipAppServerDelegate.java | 32 ++++ 9 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 examples/virtual-device-app/android/App/core/matter/src/main/java/com/matter/virtual/device/app/core/matter/MatterApp.kt create mode 100644 src/app/server/java/ChipAppServerDelegate.cpp create mode 100644 src/app/server/java/ChipAppServerDelegate.h create mode 100644 src/app/server/java/src/chip/appserver/ChipAppServerDelegate.java diff --git a/examples/virtual-device-app/android/App/core/matter/src/main/java/com/matter/virtual/device/app/core/matter/MatterApp.kt b/examples/virtual-device-app/android/App/core/matter/src/main/java/com/matter/virtual/device/app/core/matter/MatterApp.kt new file mode 100644 index 00000000000000..19d73cced0f04b --- /dev/null +++ b/examples/virtual-device-app/android/App/core/matter/src/main/java/com/matter/virtual/device/app/core/matter/MatterApp.kt @@ -0,0 +1,48 @@ +package com.matter.virtual.device.app.core.matter + +import chip.appserver.ChipAppServer +import chip.appserver.ChipAppServerDelegate +import javax.inject.Inject +import javax.inject.Singleton +import timber.log.Timber + +@Singleton +class MatterApp @Inject constructor() { + + private var chipAppServer: ChipAppServer? = null + + fun start() { + chipAppServer = ChipAppServer() + chipAppServer?.startAppWithDelegate( + object : ChipAppServerDelegate { + override fun onCommissioningSessionEstablishmentStarted() { + Timber.d("onCommissioningSessionEstablishmentStarted()") + } + + override fun onCommissioningSessionStarted() { + Timber.d("onCommissioningSessionStarted()") + } + + override fun onCommissioningSessionEstablishmentError(errorCode: Int) { + Timber.d("onCommissioningSessionEstablishmentError():$errorCode") + } + + override fun onCommissioningSessionStopped() { + Timber.d("onCommissioningSessionStopped()") + } + + override fun onCommissioningWindowOpened() { + Timber.d("onCommissioningWindowOpened()") + } + + override fun onCommissioningWindowClosed() { + Timber.d("onCommissioningWindowClosed()") + } + } + ) + } + + fun stop() { + chipAppServer?.stopApp() + } +} diff --git a/src/app/server/java/AndroidAppServerWrapper.cpp b/src/app/server/java/AndroidAppServerWrapper.cpp index 58eaa76bcbb7fb..ab88729d6f1d9b 100644 --- a/src/app/server/java/AndroidAppServerWrapper.cpp +++ b/src/app/server/java/AndroidAppServerWrapper.cpp @@ -38,7 +38,7 @@ using namespace chip::Inet; using namespace chip::Transport; using namespace chip::DeviceLayer; -CHIP_ERROR ChipAndroidAppInit(void) +CHIP_ERROR ChipAndroidAppInit(AppDelegate * appDelegate) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -50,6 +50,11 @@ CHIP_ERROR ChipAndroidAppInit(void) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + if (appDelegate != nullptr) + { + initParams.appDelegate = appDelegate; + } + initParams.operationalServicePort = CHIP_PORT; initParams.userDirectedCommissioningPort = CHIP_UDC_PORT; diff --git a/src/app/server/java/AndroidAppServerWrapper.h b/src/app/server/java/AndroidAppServerWrapper.h index ef530de60e232c..19088b9913ada1 100644 --- a/src/app/server/java/AndroidAppServerWrapper.h +++ b/src/app/server/java/AndroidAppServerWrapper.h @@ -17,10 +17,11 @@ */ #pragma once +#include #include #include -CHIP_ERROR ChipAndroidAppInit(void); +CHIP_ERROR ChipAndroidAppInit(AppDelegate * appDelegate = nullptr); void ChipAndroidAppShutdown(void); diff --git a/src/app/server/java/BUILD.gn b/src/app/server/java/BUILD.gn index a99d98ebb842fd..c25548eb112549 100644 --- a/src/app/server/java/BUILD.gn +++ b/src/app/server/java/BUILD.gn @@ -27,6 +27,8 @@ static_library("jni") { "AndroidAppServerWrapper.cpp", "AndroidAppServerWrapper.h", "CHIPAppServer-JNI.cpp", + "ChipAppServerDelegate.cpp", + "ChipAppServerDelegate.h", "ChipFabricProvider-JNI.cpp", "ChipFabricProvider-JNI.h", "ChipThreadWork.cpp", @@ -62,6 +64,7 @@ android_library("java") { sources = [ "src/chip/appserver/ChipAppServer.java", + "src/chip/appserver/ChipAppServerDelegate.java", "src/chip/appserver/ChipAppServerException.java", "src/chip/appserver/ChipFabricProvider.java", "src/chip/appserver/Fabric.java", diff --git a/src/app/server/java/CHIPAppServer-JNI.cpp b/src/app/server/java/CHIPAppServer-JNI.cpp index de7109a7245165..1b486f1bd3ac82 100644 --- a/src/app/server/java/CHIPAppServer-JNI.cpp +++ b/src/app/server/java/CHIPAppServer-JNI.cpp @@ -22,6 +22,7 @@ * */ #include "AndroidAppServerWrapper.h" +#include "ChipAppServerDelegate.h" #include "ChipFabricProvider-JNI.h" #include "ChipThreadWork.h" #include @@ -53,6 +54,7 @@ namespace { JavaVM * sJVM; pthread_t sIOThread = PTHREAD_NULL; jclass sChipAppServerExceptionCls = NULL; +ChipAppServerDelegate sChipAppServerDelegate; } // namespace jint AndroidAppServerJNI_OnLoad(JavaVM * jvm, void * reserved) @@ -134,6 +136,29 @@ JNI_METHOD(jboolean, startApp)(JNIEnv * env, jobject self) return JNI_TRUE; } +JNI_METHOD(jboolean, startAppWithDelegate)(JNIEnv * env, jobject self, jobject appDelegate) +{ + chip::DeviceLayer::StackLock lock; + + CHIP_ERROR err = sChipAppServerDelegate.InitializeWithObjects(appDelegate); + SuccessOrExit(err); + + err = ChipAndroidAppInit(&sChipAppServerDelegate); + SuccessOrExit(err); + + if (sIOThread == PTHREAD_NULL) + { + pthread_create(&sIOThread, NULL, IOThreadAppMain, NULL); + } + +exit: + if (err != CHIP_NO_ERROR) + { + return JNI_FALSE; + } + return JNI_TRUE; +} + JNI_METHOD(jboolean, stopApp)(JNIEnv * env, jobject self) { chip::ThreadWork::ChipMainThreadScheduleAndWait([] { ChipAndroidAppShutdown(); }); diff --git a/src/app/server/java/ChipAppServerDelegate.cpp b/src/app/server/java/ChipAppServerDelegate.cpp new file mode 100644 index 00000000000000..50d76c63d59423 --- /dev/null +++ b/src/app/server/java/ChipAppServerDelegate.cpp @@ -0,0 +1,159 @@ +/* + * + * Copyright (c) 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 "ChipAppServerDelegate.h" +#include +#include + +using namespace chip; + +void ChipAppServerDelegate::OnCommissioningSessionEstablishmentStarted() +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(AppServer, "JNIEnv is nullptr")); + VerifyOrReturn(mOnCommissioningSessionEstablishmentStartedMethod != nullptr, + ChipLogError(AppServer, "mOnCommissioningSessionEstablishmentStartedMethod is nullptr")); + + env->ExceptionClear(); + env->CallVoidMethod(mChipAppServerDelegateObject, mOnCommissioningSessionEstablishmentStartedMethod); + if (env->ExceptionCheck()) + { + ChipLogError(AppServer, "Java exception in OnCommissioningSessionEstablishmentStartedMethod"); + env->ExceptionDescribe(); + env->ExceptionClear(); + } +} + +void ChipAppServerDelegate::OnCommissioningSessionStarted() +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(AppServer, "JNIEnv is nullptr")); + VerifyOrReturn(mOnCommissioningSessionStartedMethod != nullptr, + ChipLogError(AppServer, "mOnCommissioningSessionStartedMethod is nullptr")); + + env->ExceptionClear(); + env->CallVoidMethod(mChipAppServerDelegateObject, mOnCommissioningSessionStartedMethod); + if (env->ExceptionCheck()) + { + ChipLogError(AppServer, "Java exception in OnCommissioningSessionStartedMethod"); + env->ExceptionDescribe(); + env->ExceptionClear(); + } +} + +void ChipAppServerDelegate::OnCommissioningSessionEstablishmentError(CHIP_ERROR err) +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(AppServer, "JNIEnv is nullptr")); + VerifyOrReturn(mOnCommissioningSessionEstablishmentErrorMethod != nullptr, + ChipLogError(AppServer, "mOnCommissioningSessionEstablishmentErrorMethod is nullptr")); + + env->ExceptionClear(); + env->CallVoidMethod(mChipAppServerDelegateObject, mOnCommissioningSessionEstablishmentErrorMethod, + static_cast(err.AsInteger())); + if (env->ExceptionCheck()) + { + ChipLogError(AppServer, "Java exception in OnCommissioningSessionEstablishmentErrorMethod"); + env->ExceptionDescribe(); + env->ExceptionClear(); + } +} + +void ChipAppServerDelegate::OnCommissioningSessionStopped() +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(AppServer, "JNIEnv is nullptr")); + VerifyOrReturn(mOnCommissioningSessionStoppedMethod != nullptr, + ChipLogError(AppServer, "mOnCommissioningSessionStoppedMethod is nullptr")); + + env->ExceptionClear(); + env->CallVoidMethod(mChipAppServerDelegateObject, mOnCommissioningSessionStoppedMethod); + if (env->ExceptionCheck()) + { + ChipLogError(AppServer, "Java exception in OnCommissioningSessionStoppedMethod"); + env->ExceptionDescribe(); + env->ExceptionClear(); + } +} + +void ChipAppServerDelegate::OnCommissioningWindowOpened() +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(AppServer, "JNIEnv is nullptr")); + VerifyOrReturn(mOnCommissioningWindowOpenedMethod != nullptr, + ChipLogError(AppServer, "mOnCommissioningWindowOpenedMethod is nullptr")); + + env->ExceptionClear(); + env->CallVoidMethod(mChipAppServerDelegateObject, mOnCommissioningWindowOpenedMethod); + if (env->ExceptionCheck()) + { + ChipLogError(AppServer, "Java exception in OnCommissioningWindowOpenedMethod"); + env->ExceptionDescribe(); + env->ExceptionClear(); + } +} + +void ChipAppServerDelegate::OnCommissioningWindowClosed() +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturn(env != nullptr, ChipLogError(AppServer, "JNIEnv is nullptr")); + VerifyOrReturn(mOnCommissioningWindowClosedMethod != nullptr, + ChipLogError(AppServer, "mOnCommissioningWindowClosedMethod is nullptr")); + + env->ExceptionClear(); + env->CallVoidMethod(mChipAppServerDelegateObject, mOnCommissioningWindowClosedMethod); + if (env->ExceptionCheck()) + { + ChipLogError(AppServer, "Java exception in OnCommissioningWindowClosedMethod"); + env->ExceptionDescribe(); + env->ExceptionClear(); + } +} + +CHIP_ERROR ChipAppServerDelegate::InitializeWithObjects(jobject appDelegateObject) +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + VerifyOrReturnLogError(env != nullptr, CHIP_JNI_ERROR_NO_ENV); + + mChipAppServerDelegateObject = env->NewGlobalRef(appDelegateObject); + VerifyOrReturnLogError(mChipAppServerDelegateObject != nullptr, CHIP_JNI_ERROR_NULL_OBJECT); + + jclass chipAppServerDelegateClass = env->GetObjectClass(mChipAppServerDelegateObject); + VerifyOrReturnLogError(chipAppServerDelegateClass != nullptr, CHIP_JNI_ERROR_JAVA_ERROR); + + mOnCommissioningSessionEstablishmentStartedMethod = + env->GetMethodID(chipAppServerDelegateClass, "onCommissioningSessionEstablishmentStarted", "()V"); + VerifyOrReturnLogError(mOnCommissioningSessionEstablishmentStartedMethod != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND); + + mOnCommissioningSessionStartedMethod = env->GetMethodID(chipAppServerDelegateClass, "onCommissioningSessionStarted", "()V"); + VerifyOrReturnLogError(mOnCommissioningSessionStartedMethod != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND); + + mOnCommissioningSessionEstablishmentErrorMethod = + env->GetMethodID(chipAppServerDelegateClass, "onCommissioningSessionEstablishmentError", "(I)V"); + VerifyOrReturnLogError(mOnCommissioningSessionEstablishmentErrorMethod != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND); + + mOnCommissioningSessionStoppedMethod = env->GetMethodID(chipAppServerDelegateClass, "onCommissioningSessionStopped", "()V"); + VerifyOrReturnLogError(mOnCommissioningSessionStoppedMethod != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND); + + mOnCommissioningWindowOpenedMethod = env->GetMethodID(chipAppServerDelegateClass, "onCommissioningWindowOpened", "()V"); + VerifyOrReturnLogError(mOnCommissioningWindowOpenedMethod != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND); + + mOnCommissioningWindowClosedMethod = env->GetMethodID(chipAppServerDelegateClass, "onCommissioningWindowClosed", "()V"); + VerifyOrReturnLogError(mOnCommissioningWindowClosedMethod != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND); + + return CHIP_NO_ERROR; +} diff --git a/src/app/server/java/ChipAppServerDelegate.h b/src/app/server/java/ChipAppServerDelegate.h new file mode 100644 index 00000000000000..42df60605de39a --- /dev/null +++ b/src/app/server/java/ChipAppServerDelegate.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (c) 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. + */ + +#pragma once + +#include +#include +#include + +class ChipAppServerDelegate : public AppDelegate +{ +public: + void OnCommissioningSessionEstablishmentStarted() override; + void OnCommissioningSessionStarted() override; + void OnCommissioningSessionEstablishmentError(CHIP_ERROR err) override; + void OnCommissioningSessionStopped() override; + void OnCommissioningWindowOpened() override; + void OnCommissioningWindowClosed() override; + + CHIP_ERROR InitializeWithObjects(jobject appDelegateObject); + +private: + jobject mChipAppServerDelegateObject = nullptr; + jmethodID mOnCommissioningSessionEstablishmentStartedMethod = nullptr; + jmethodID mOnCommissioningSessionStartedMethod = nullptr; + jmethodID mOnCommissioningSessionEstablishmentErrorMethod = nullptr; + jmethodID mOnCommissioningSessionStoppedMethod = nullptr; + jmethodID mOnCommissioningWindowOpenedMethod = nullptr; + jmethodID mOnCommissioningWindowClosedMethod = nullptr; +}; diff --git a/src/app/server/java/src/chip/appserver/ChipAppServer.java b/src/app/server/java/src/chip/appserver/ChipAppServer.java index 4b414070a12fcf..e501329085522f 100644 --- a/src/app/server/java/src/chip/appserver/ChipAppServer.java +++ b/src/app/server/java/src/chip/appserver/ChipAppServer.java @@ -36,5 +36,7 @@ public ChipFabricProvider getFabricProvider() { public native boolean startApp(); + public native boolean startAppWithDelegate(ChipAppServerDelegate appDelegate); + public native boolean stopApp(); } diff --git a/src/app/server/java/src/chip/appserver/ChipAppServerDelegate.java b/src/app/server/java/src/chip/appserver/ChipAppServerDelegate.java new file mode 100644 index 00000000000000..28daed388331c9 --- /dev/null +++ b/src/app/server/java/src/chip/appserver/ChipAppServerDelegate.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ +package chip.appserver; + +public interface ChipAppServerDelegate { + void onCommissioningSessionEstablishmentStarted(); + + void onCommissioningSessionStarted(); + + void onCommissioningSessionEstablishmentError(int errorCode); + + void onCommissioningSessionStopped(); + + void onCommissioningWindowOpened(); + + void onCommissioningWindowClosed(); +}