virtual-device-app: Add DoorLock/PowerSource Manager for DoorLock (#28784)
Signed-off-by: Jaehoon You <jaehoon.you@samsung.com>
Signed-off-by: Charles Kim <chulspro.kim@samsung.com>
diff --git a/examples/virtual-device-app/android/BUILD.gn b/examples/virtual-device-app/android/BUILD.gn
index 61b29e9..8ff5677 100644
--- a/examples/virtual-device-app/android/BUILD.gn
+++ b/examples/virtual-device-app/android/BUILD.gn
@@ -30,10 +30,14 @@
"java/ColorControlManager.cpp",
"java/ColorControlManager.h",
"java/DeviceApp-JNI.cpp",
+ "java/DoorLockManager.cpp",
+ "java/DoorLockManager.h",
"java/JNIDACProvider.cpp",
"java/JNIDACProvider.h",
"java/OnOffManager.cpp",
"java/OnOffManager.h",
+ "java/PowerSourceManager.cpp",
+ "java/PowerSourceManager.h",
]
deps = [
@@ -72,7 +76,9 @@
"java/src/com/matter/virtual/device/app/DeviceApp.java",
"java/src/com/matter/virtual/device/app/DeviceAppCallback.java",
"java/src/com/matter/virtual/device/app/DeviceEventType.java",
+ "java/src/com/matter/virtual/device/app/DoorLockManager.java",
"java/src/com/matter/virtual/device/app/OnOffManager.java",
+ "java/src/com/matter/virtual/device/app/PowerSourceManager.java",
]
javac_flags = [ "-Xlint:deprecation" ]
diff --git a/examples/virtual-device-app/android/java/ClusterChangeAttribute.cpp b/examples/virtual-device-app/android/java/ClusterChangeAttribute.cpp
index 721f468..edb373b 100644
--- a/examples/virtual-device-app/android/java/ClusterChangeAttribute.cpp
+++ b/examples/virtual-device-app/android/java/ClusterChangeAttribute.cpp
@@ -17,6 +17,7 @@
*/
#include "ColorControlManager.h"
+#include "DoorLockManager.h"
#include "OnOffManager.h"
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/ids/Attributes.h>
@@ -89,6 +90,19 @@
}
}
+static void DoorLockClusterAttributeChangeCallback(const app::ConcreteAttributePath & attributePath, uint16_t size, uint8_t * value)
+{
+ if (attributePath.mAttributeId == DoorLock::Attributes::LockState::Id)
+ {
+ uint8_t lockState = *value;
+
+ ChipLogProgress(Zcl, "Received lock state command endpoint %d value = %d", static_cast<int>(attributePath.mEndpointId),
+ lockState);
+
+ DoorLockManager().PostLockStateChanged(attributePath.mEndpointId, lockState);
+ }
+}
+
void MatterPostAttributeChangeCallback(const app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
uint8_t * value)
{
@@ -103,6 +117,9 @@
case ColorControl::Id:
ColorControlClusterAttributeChangeCallback(attributePath, size, value);
break;
+ case DoorLock::Id:
+ DoorLockClusterAttributeChangeCallback(attributePath, size, value);
+ break;
default:
break;
diff --git a/examples/virtual-device-app/android/java/DeviceApp-JNI.cpp b/examples/virtual-device-app/android/java/DeviceApp-JNI.cpp
index 02998bb..cb80a1d 100644
--- a/examples/virtual-device-app/android/java/DeviceApp-JNI.cpp
+++ b/examples/virtual-device-app/android/java/DeviceApp-JNI.cpp
@@ -21,7 +21,9 @@
#include "JNIDACProvider.h"
#include "ColorControlManager.h"
+#include "DoorLockManager.h"
#include "OnOffManager.h"
+#include "PowerSourceManager.h"
#include "credentials/DeviceAttestationCredsProvider.h"
#include <app/app-platform/ContentAppPlatform.h>
#include <app/server/Dnssd.h>
@@ -166,3 +168,67 @@
{
ColorControlManager::NewManager(endpoint, manager);
}
+
+/*
+ * Door Lock Manager
+ */
+JNI_METHOD(void, setDoorLockManager)(JNIEnv *, jobject, jint endpoint, jobject manager)
+{
+ DoorLockManager::NewManager(endpoint, manager);
+}
+
+JNI_METHOD(jboolean, setLockType)(JNIEnv *, jobject, jint endpoint, jint value)
+{
+ return DeviceLayer::SystemLayer().ScheduleLambda([endpoint, value] { DoorLockManager::SetLockType(endpoint, value); }) ==
+ CHIP_NO_ERROR;
+}
+
+JNI_METHOD(jboolean, setLockState)(JNIEnv *, jobject, jint endpoint, jint value)
+{
+ return DeviceLayer::SystemLayer().ScheduleLambda([endpoint, value] { DoorLockManager::SetLockState(endpoint, value); }) ==
+ CHIP_NO_ERROR;
+}
+
+JNI_METHOD(jboolean, setActuatorEnabled)(JNIEnv *, jobject, jint endpoint, jboolean value)
+{
+ return DeviceLayer::SystemLayer().ScheduleLambda([endpoint, value] { DoorLockManager::SetActuatorEnabled(endpoint, value); }) ==
+ CHIP_NO_ERROR;
+}
+
+JNI_METHOD(jboolean, setAutoRelockTime)(JNIEnv *, jobject, jint endpoint, jint value)
+{
+ return DeviceLayer::SystemLayer().ScheduleLambda([endpoint, value] { DoorLockManager::SetAutoRelockTime(endpoint, value); }) ==
+ CHIP_NO_ERROR;
+}
+
+JNI_METHOD(jboolean, setOperatingMode)(JNIEnv *, jobject, jint endpoint, jint value)
+{
+ return DeviceLayer::SystemLayer().ScheduleLambda([endpoint, value] { DoorLockManager::SetOperatingMode(endpoint, value); }) ==
+ CHIP_NO_ERROR;
+}
+
+JNI_METHOD(jboolean, setSupportedOperatingModes)(JNIEnv *, jobject, jint endpoint, jint value)
+{
+ return DeviceLayer::SystemLayer().ScheduleLambda(
+ [endpoint, value] { DoorLockManager::SetSupportedOperatingModes(endpoint, value); }) == CHIP_NO_ERROR;
+}
+
+JNI_METHOD(jboolean, sendLockAlarmEvent)(JNIEnv *, jobject, jint endpoint)
+{
+ return DeviceLayer::SystemLayer().ScheduleLambda([endpoint] { DoorLockManager::SendLockAlarmEvent(endpoint); }) ==
+ CHIP_NO_ERROR;
+}
+
+/*
+ * Power Source Manager
+ */
+JNI_METHOD(void, setPowerSourceManager)(JNIEnv *, jobject, jint endpoint, jobject manager)
+{
+ PowerSourceManager::NewManager(endpoint, manager);
+}
+
+JNI_METHOD(jboolean, setBatPercentRemaining)(JNIEnv *, jobject, jint endpoint, jint value)
+{
+ return DeviceLayer::SystemLayer().ScheduleLambda(
+ [endpoint, value] { PowerSourceManager::SetBatPercentRemaining(endpoint, value); }) == CHIP_NO_ERROR;
+}
diff --git a/examples/virtual-device-app/android/java/DoorLockManager.cpp b/examples/virtual-device-app/android/java/DoorLockManager.cpp
new file mode 100644
index 0000000..9a2c574
--- /dev/null
+++ b/examples/virtual-device-app/android/java/DoorLockManager.cpp
@@ -0,0 +1,195 @@
+/**
+ *
+ * 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 "DoorLockManager.h"
+#include "DeviceApp-JNI.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <app/ConcreteAttributePath.h>
+#include <app/clusters/door-lock-server/door-lock-server.h>
+#include <app/reporting/reporting.h>
+#include <app/util/af.h>
+#include <jni.h>
+#include <lib/support/CHIPJNIError.h>
+#include <lib/support/JniReferences.h>
+#include <lib/support/JniTypeWrappers.h>
+#include <lib/support/ZclString.h>
+#include <platform/PlatformManager.h>
+#include <vector>
+
+using namespace chip;
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::DoorLock;
+using namespace chip::DeviceLayer;
+
+static constexpr size_t kDoorLockManagerTableSize =
+ EMBER_AF_DOOR_LOCK_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT;
+
+namespace {
+
+DoorLockManager * gDoorLockManagerTable[kDoorLockManagerTableSize] = { nullptr };
+
+}
+
+void emberAfDoorLockClusterInitCallback(EndpointId endpoint)
+{
+ ChipLogProgress(Zcl, "Device App::DoorLock::PostClusterInit");
+ DeviceAppJNIMgr().PostClusterInit(chip::app::Clusters::DoorLock::Id, endpoint);
+ DoorLockServer::Instance().InitServer(endpoint);
+ EmberAfStatus status = DoorLock::Attributes::FeatureMap::Set(endpoint, 0);
+ if (status != EMBER_ZCL_STATUS_SUCCESS)
+ {
+ ChipLogProgress(Zcl, "Device App::DoorLock::emberAfDoorLockClusterInitCallback()::Updating feature map %x", status);
+ }
+}
+
+bool emberAfPluginDoorLockOnDoorLockCommand(EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx,
+ const Nullable<chip::NodeId> & nodeId, const Optional<ByteSpan> & pinCode,
+ OperationErrorEnum & err)
+{
+ ChipLogProgress(Zcl, "Device App::DoorLock::emberAfPluginDoorLockOnDoorLockCommand");
+ return DoorLockServer::Instance().SetLockState(endpointId, DlLockState::kLocked);
+}
+
+bool emberAfPluginDoorLockOnDoorUnlockCommand(EndpointId endpointId, const Nullable<chip::FabricIndex> & fabricIdx,
+ const Nullable<chip::NodeId> & nodeId, const Optional<ByteSpan> & pinCode,
+ OperationErrorEnum & err)
+{
+ ChipLogProgress(Zcl, "Device App::DoorLock::emberAfPluginDoorLockOnDoorUnlockCommand");
+ return DoorLockServer::Instance().SetLockState(endpointId, DlLockState::kUnlocked);
+}
+
+void DoorLockManager::NewManager(jint endpoint, jobject manager)
+{
+ ChipLogProgress(Zcl, "Device App: DoorLockManager::NewManager");
+ uint16_t ep = emberAfGetClusterServerEndpointIndex(static_cast<chip::EndpointId>(endpoint), app::Clusters::DoorLock::Id,
+ EMBER_AF_DOOR_LOCK_CLUSTER_SERVER_ENDPOINT_COUNT);
+ VerifyOrReturn(ep < kDoorLockManagerTableSize,
+ ChipLogError(Zcl, "Device App::DoorLock::NewManager: endpoint %d not found", endpoint));
+
+ VerifyOrReturn(gDoorLockManagerTable[ep] == nullptr,
+ ChipLogError(Zcl, "Device App::DoorLock::NewManager: endpoint %d already has a manager", endpoint));
+ DoorLockManager * mgr = new DoorLockManager();
+ CHIP_ERROR err = mgr->InitializeWithObjects(manager);
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(Zcl, "Device App::DoorLock::NewManager: failed to initialize manager for endpoint %d", endpoint);
+ delete mgr;
+ }
+ else
+ {
+ gDoorLockManagerTable[ep] = mgr;
+ }
+}
+
+DoorLockManager * GetDoorLockManager(EndpointId endpoint)
+{
+ uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, app::Clusters::DoorLock::Id,
+ EMBER_AF_DOOR_LOCK_CLUSTER_SERVER_ENDPOINT_COUNT);
+ return ((ep >= kDoorLockManagerTableSize) ? nullptr : gDoorLockManagerTable[ep]);
+}
+
+jboolean DoorLockManager::SetLockType(jint endpoint, jint value)
+{
+ EmberAfStatus status = app::Clusters::DoorLock::Attributes::LockType::Set(
+ static_cast<chip::EndpointId>(endpoint), static_cast<app::Clusters::DoorLock::DlLockType>(value));
+ return status == EMBER_ZCL_STATUS_SUCCESS;
+}
+
+jboolean DoorLockManager::SetLockState(jint endpoint, jint value)
+{
+ return DoorLockServer::Instance().SetLockState(static_cast<chip::EndpointId>(endpoint),
+ static_cast<app::Clusters::DoorLock::DlLockState>(value));
+}
+
+jboolean DoorLockManager::SetActuatorEnabled(jint endpoint, jboolean value)
+{
+ return DoorLockServer::Instance().SetActuatorEnabled(static_cast<chip::EndpointId>(endpoint), value);
+}
+
+jboolean DoorLockManager::SetAutoRelockTime(jint endpoint, jint value)
+{
+ return DoorLockServer::Instance().SetAutoRelockTime(static_cast<chip::EndpointId>(endpoint), static_cast<uint32_t>(value));
+}
+
+jboolean DoorLockManager::SetOperatingMode(jint endpoint, jint value)
+{
+ EmberAfStatus status = app::Clusters::DoorLock::Attributes::OperatingMode::Set(
+ static_cast<chip::EndpointId>(endpoint), static_cast<app::Clusters::DoorLock::OperatingModeEnum>(value));
+ return status == EMBER_ZCL_STATUS_SUCCESS;
+}
+
+jboolean DoorLockManager::SetSupportedOperatingModes(jint endpoint, jint value)
+{
+ EmberAfStatus status = app::Clusters::DoorLock::Attributes::SupportedOperatingModes::Set(
+ static_cast<chip::EndpointId>(endpoint), static_cast<app::Clusters::DoorLock::DlSupportedOperatingModes>(value));
+ return status == EMBER_ZCL_STATUS_SUCCESS;
+}
+
+jboolean DoorLockManager::SendLockAlarmEvent(jint endpoint)
+{
+ return DoorLockServer::Instance().SendLockAlarmEvent(static_cast<chip::EndpointId>(endpoint), AlarmCodeEnum::kDoorForcedOpen);
+}
+
+void DoorLockManager::PostLockStateChanged(chip::EndpointId endpoint, int value)
+{
+ ChipLogProgress(Zcl, "Device App: DoorLockManager::PostLockStateChanged:%d", value);
+ DoorLockManager * mgr = GetDoorLockManager(endpoint);
+ VerifyOrReturn(mgr != nullptr, ChipLogError(Zcl, "DoorLockManager null"));
+
+ mgr->HandleLockStateChanged(static_cast<int>(endpoint), value);
+}
+
+CHIP_ERROR DoorLockManager::InitializeWithObjects(jobject managerObject)
+{
+ JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
+ VerifyOrReturnLogError(env != nullptr, CHIP_ERROR_INCORRECT_STATE);
+
+ mDoorLockManagerObject = env->NewGlobalRef(managerObject);
+ VerifyOrReturnLogError(mDoorLockManagerObject != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ jclass DoorLockManagerClass = env->GetObjectClass(managerObject);
+ VerifyOrReturnLogError(DoorLockManagerClass != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ mHandleLockStateChangedMethod = env->GetMethodID(DoorLockManagerClass, "handleLockStateChanged", "(I)V");
+ if (mHandleLockStateChangedMethod == nullptr)
+ {
+ ChipLogError(Zcl, "Failed to access DoorLockManager 'handleLockStateChanged' method");
+ env->ExceptionClear();
+ return CHIP_ERROR_INVALID_ARGUMENT;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+void DoorLockManager::HandleLockStateChanged(jint endpoint, jint value)
+{
+ ChipLogProgress(Zcl, "DoorLockManager::HandleLockStateChanged:%d", value);
+
+ JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
+ VerifyOrReturn(env != NULL, ChipLogProgress(Zcl, "env null"));
+ VerifyOrReturn(mDoorLockManagerObject != nullptr, ChipLogProgress(Zcl, "mDoorLockManagerObject null"));
+ VerifyOrReturn(mHandleLockStateChangedMethod != nullptr, ChipLogProgress(Zcl, "mHandleLockStateChangedMethod null"));
+
+ env->ExceptionClear();
+ env->CallVoidMethod(mDoorLockManagerObject, mHandleLockStateChangedMethod, value);
+ if (env->ExceptionCheck())
+ {
+ ChipLogError(AppServer, "Java exception in DoorLockManager::HandleLockStateChanged");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+}
diff --git a/examples/virtual-device-app/android/java/DoorLockManager.h b/examples/virtual-device-app/android/java/DoorLockManager.h
new file mode 100644
index 0000000..d6dac14
--- /dev/null
+++ b/examples/virtual-device-app/android/java/DoorLockManager.h
@@ -0,0 +1,67 @@
+/*
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <app-common/zap-generated/cluster-objects.h>
+#include <app/clusters/door-lock-server/door-lock-server.h>
+#include <app/util/attribute-storage.h>
+#include <jni.h>
+
+/**
+ * @brief Handles interfacing between java code and C++ code for the purposes of DoorLock clusters.
+ */
+class DoorLockManager
+{
+public:
+ // installed a bridege for a DoorLock cluster endpoint and java object
+ static void NewManager(jint endpoint, jobject manager);
+
+ // helps for java to set attributes::LockType of DoorLock cluster
+ static jboolean SetLockType(jint endpoint, jint value);
+
+ // helps for java to set attributes::LockState of DoorLock cluster
+ static jboolean SetLockState(jint endpoint, jint value);
+
+ // helps for java to set attributes::ActuatorEnabled of DoorLock cluster
+ static jboolean SetActuatorEnabled(jint endpoint, jboolean value);
+
+ // helps for java to set attributes::AutoRelockTime of DoorLock cluster
+ static jboolean SetAutoRelockTime(jint endpoint, jint value);
+
+ // helps for java to set attributes::OperatingMode of DoorLock cluster
+ static jboolean SetOperatingMode(jint endpoint, jint value);
+
+ // helps for java to set attributes::SupportedOperatingMode of DoorLock cluster
+ static jboolean SetSupportedOperatingModes(jint endpoint, jint value);
+
+ // helps for java to send LockAlarmEvent of DoorLock cluster
+ static jboolean SendLockAlarmEvent(jint endpoint);
+
+ // posts a LockStateChanged event to suitable DoorLockManager
+ static void PostLockStateChanged(chip::EndpointId endpoint, int value);
+
+ // handles `Changed` callbacks by calling the java `void HandleLockStateChanged()` method
+ void HandleLockStateChanged(int endpoint, int value);
+
+private:
+ // init with java objects
+ CHIP_ERROR InitializeWithObjects(jobject managerObject);
+ jobject mDoorLockManagerObject = nullptr;
+ jmethodID mHandleLockStateChangedMethod = nullptr;
+};
diff --git a/examples/virtual-device-app/android/java/PowerSourceManager.cpp b/examples/virtual-device-app/android/java/PowerSourceManager.cpp
new file mode 100644
index 0000000..0d56b58
--- /dev/null
+++ b/examples/virtual-device-app/android/java/PowerSourceManager.cpp
@@ -0,0 +1,107 @@
+/**
+ *
+ * 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 "PowerSourceManager.h"
+#include "DeviceApp-JNI.h"
+#include <app-common/zap-generated/attributes/Accessors.h>
+#include <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <app/ConcreteAttributePath.h>
+#include <app/clusters/door-lock-server/door-lock-server.h>
+#include <app/reporting/reporting.h>
+#include <app/util/af.h>
+#include <jni.h>
+#include <lib/support/CHIPJNIError.h>
+#include <lib/support/JniReferences.h>
+#include <lib/support/JniTypeWrappers.h>
+#include <lib/support/ZclString.h>
+#include <platform/PlatformManager.h>
+
+using namespace chip;
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::PowerSource;
+
+static constexpr size_t kPowerSourceManagerTableSize =
+ EMBER_AF_POWER_SOURCE_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT;
+
+namespace {
+
+PowerSourceManager * gPowerSourceManagerTable[kPowerSourceManagerTableSize] = { nullptr };
+
+}
+
+void emberAfPowerSourceClusterInitCallback(EndpointId endpoint)
+{
+ ChipLogProgress(Zcl, "Device App::PowerSource::PostClusterInit");
+ DeviceAppJNIMgr().PostClusterInit(chip::app::Clusters::PowerSource::Id, endpoint);
+}
+
+void PowerSourceManager::NewManager(jint endpoint, jobject manager)
+{
+ ChipLogProgress(Zcl, "Device App: PowerSourceManager::NewManager");
+ uint16_t ep = emberAfGetClusterServerEndpointIndex(static_cast<chip::EndpointId>(endpoint), app::Clusters::PowerSource::Id,
+ EMBER_AF_POWER_SOURCE_CLUSTER_SERVER_ENDPOINT_COUNT);
+ VerifyOrReturn(ep < kPowerSourceManagerTableSize,
+ ChipLogError(Zcl, "Device App::PowerSource::NewManager: endpoint %d not found", endpoint));
+
+ VerifyOrReturn(gPowerSourceManagerTable[ep] == nullptr,
+ ChipLogError(Zcl, "Device App::PowerSource::NewManager: endpoint %d already has a manager", endpoint));
+ PowerSourceManager * mgr = new PowerSourceManager();
+ CHIP_ERROR err = mgr->InitializeWithObjects(manager);
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(Zcl, "Device App::PowerSource::NewManager: failed to initialize manager for endpoint %d", endpoint);
+ delete mgr;
+ }
+ else
+ {
+ gPowerSourceManagerTable[ep] = mgr;
+ }
+}
+
+PowerSourceManager * GetPowerSourceManager(EndpointId endpoint)
+{
+ uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, app::Clusters::PowerSource::Id,
+ EMBER_AF_POWER_SOURCE_CLUSTER_SERVER_ENDPOINT_COUNT);
+ return ((ep >= kPowerSourceManagerTableSize) ? nullptr : gPowerSourceManagerTable[ep]);
+}
+
+jboolean PowerSourceManager::SetBatPercentRemaining(jint endpoint, jint value)
+{
+ using namespace chip::app::Clusters;
+ using namespace chip::DeviceLayer;
+ EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS;
+
+ status =
+ PowerSource::Attributes::BatPercentRemaining::Set(static_cast<chip::EndpointId>(endpoint), static_cast<uint8_t>(value * 2));
+
+ ChipLogDetail(Zcl, "Device App::PowerSource::SetBatPercentRemaining: endpoint:%d, percent:%d", endpoint, value);
+ return status == EMBER_ZCL_STATUS_SUCCESS;
+}
+
+CHIP_ERROR PowerSourceManager::InitializeWithObjects(jobject managerObject)
+{
+ JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
+ VerifyOrReturnLogError(env != nullptr, CHIP_ERROR_INCORRECT_STATE);
+
+ mPowerSourceManagerObject = env->NewGlobalRef(managerObject);
+ VerifyOrReturnLogError(mPowerSourceManagerObject != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ jclass PowerSourceManagerClass = env->GetObjectClass(managerObject);
+ VerifyOrReturnLogError(PowerSourceManagerClass != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+ return CHIP_NO_ERROR;
+}
diff --git a/examples/virtual-device-app/android/java/PowerSourceManager.h b/examples/virtual-device-app/android/java/PowerSourceManager.h
new file mode 100644
index 0000000..54b2c68
--- /dev/null
+++ b/examples/virtual-device-app/android/java/PowerSourceManager.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <app-common/zap-generated/cluster-objects.h>
+#include <app/util/attribute-storage.h>
+#include <jni.h>
+
+/**
+ * @brief Handles interfacing between java code and C++ code for the purposes of PowerSource clusters.
+ */
+class PowerSourceManager
+{
+public:
+ // installed a bridege for a PowerSource cluster endpoint and java object
+ static void NewManager(jint endpoint, jobject manager);
+ static jboolean SetBatPercentRemaining(jint endpoint, jint value);
+
+private:
+ // init with java objects
+ CHIP_ERROR InitializeWithObjects(jobject managerObject);
+ jobject mPowerSourceManagerObject = nullptr;
+};
diff --git a/examples/virtual-device-app/android/java/src/com/matter/virtual/device/app/DeviceApp.java b/examples/virtual-device-app/android/java/src/com/matter/virtual/device/app/DeviceApp.java
index 3df52b0..feb9f91 100644
--- a/examples/virtual-device-app/android/java/src/com/matter/virtual/device/app/DeviceApp.java
+++ b/examples/virtual-device-app/android/java/src/com/matter/virtual/device/app/DeviceApp.java
@@ -53,11 +53,31 @@
// called after Matter server is initiated
public native void postServerInit(int deviceTypeId);
+ public native void setDACProvider(DACProvider provider);
+
public native void setOnOffManager(int endpoint, OnOffManager manager);
public native boolean setOnOff(int endpoint, boolean value);
- public native void setDACProvider(DACProvider provider);
+ public native void setDoorLockManager(int endpoint, DoorLockManager manager);
+
+ public native boolean setLockType(int endpoint, int value);
+
+ public native boolean setLockState(int endpoint, int value);
+
+ public native boolean setActuatorEnabled(int endpoint, boolean value);
+
+ public native boolean setAutoRelockTime(int endpoint, int value);
+
+ public native boolean setOperatingMode(int endpoint, int value);
+
+ public native boolean setSupportedOperatingModes(int endpoint, int value);
+
+ public native boolean sendLockAlarmEvent(int endpoint);
+
+ public native void setPowerSourceManager(int endpoint, PowerSourceManager manager);
+
+ public native boolean setBatPercentRemaining(int endpoint, int value);
static {
System.loadLibrary("DeviceApp");
diff --git a/examples/virtual-device-app/android/java/src/com/matter/virtual/device/app/DoorLockManager.java b/examples/virtual-device-app/android/java/src/com/matter/virtual/device/app/DoorLockManager.java
new file mode 100644
index 0000000..6e03667
--- /dev/null
+++ b/examples/virtual-device-app/android/java/src/com/matter/virtual/device/app/DoorLockManager.java
@@ -0,0 +1,39 @@
+package com.matter.virtual.device.app;
+
+public interface DoorLockManager {
+
+ int DlLockState_kNotFullyLocked = 0;
+ int DlLockState_kLocked = 1;
+ int DlLockState_kUnlocked = 2;
+ int DlLockState_kUnlatched = 3;
+
+ int DlLockType_kDeadBolt = 0;
+ int DlLockType_kMagnetic = 1;
+ int DlLockType_kOther = 2;
+ int DlLockType_kMortise = 3;
+ int DlLockType_kRim = 4;
+ int DlLockType_kLatchBolt = 5;
+ int DlLockType_kCylindricalLock = 6;
+ int DlLockType_kTubularLock = 7;
+ int DlLockType_kInterconnectedLock = 8;
+ int DlLockType_kDeadLatch = 9;
+ int DlLockType_kDoorFurniture = 10;
+ int DlLockType_kEurocylinder = 11;
+
+ int OperatingModeEnum_kNormal = 0;
+ int OperatingModeEnum_kVacation = 1;
+ int OperatingModeEnum_kPrivacy = 2;
+ int OperatingModeEnum_kNoRemoteLockUnlock = 3;
+ int OperatingModeEnum_kPassage = 4;
+
+ int DlSupportedOperatingModes_kNormal = 0x1;
+ int DlSupportedOperatingModes_kVacation = 0x2;
+ int DlSupportedOperatingModes_kPrivacy = 0x4;
+ int DlSupportedOperatingModes_kNoRemoteLockUnlock = 0x8;
+ int DlSupportedOperatingModes_kPassage = 0x10;
+
+ /** initialize attribute by DeviceApp */
+ void initAttributeValue();
+
+ void handleLockStateChanged(int value);
+}
diff --git a/examples/virtual-device-app/android/java/src/com/matter/virtual/device/app/PowerSourceManager.java b/examples/virtual-device-app/android/java/src/com/matter/virtual/device/app/PowerSourceManager.java
new file mode 100644
index 0000000..5245b49
--- /dev/null
+++ b/examples/virtual-device-app/android/java/src/com/matter/virtual/device/app/PowerSourceManager.java
@@ -0,0 +1,6 @@
+package com.matter.virtual.device.app;
+
+public interface PowerSourceManager {
+
+ void initAttributeValue();
+}