[Android] Implement Java TLV Decoder API (#27586)
* Implement Android TLV Decoder
* Restyled by google-java-format
* Restyled by clang-format
* fix merge conflict
* restyle
---------
Co-authored-by: Restyled.io <commits@restyled.io>
Co-authored-by: Andrei Litvin <andy314@gmail.com>
diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt
index 734ce12..b14f4a5 100644
--- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt
+++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OpCredClientFragment.kt
@@ -8,6 +8,8 @@
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import chip.devicecontroller.ChipDeviceController
+import chip.devicecontroller.ChipStructs
+import chip.devicecontroller.ChipTLVValueDecoder
import chip.devicecontroller.ClusterIDMapping.OperationalCredentials
import chip.devicecontroller.InvokeCallback
import chip.devicecontroller.ReportCallback
@@ -120,8 +122,37 @@
?.getAttributeState(attributeId)
?.value
?: "null"
- Log.i(TAG, "OpCred $attributeName value: $value")
- showMessage("OpCred $attributeName value: $value")
+ val tlv =
+ nodeState
+ ?.getEndpointState(endpointId)
+ ?.getClusterState(clusterId)
+ ?.getAttributeState(attributeId)
+ ?.tlv
+
+ if (tlv == null) {
+ Log.i(TAG, "OpCred $attributeName value: $value")
+ showMessage("OpCred $attributeName value: $value")
+ return
+ }
+
+ val attributePath = ChipAttributePath.newInstance(endpointId, clusterId, attributeId)
+ when (attribute) {
+ OperationalCredentials.Attribute.Fabrics -> {
+ val ret =
+ ChipTLVValueDecoder.decodeAttributeValue<
+ List<ChipStructs.OperationalCredentialsClusterFabricDescriptorStruct>
+ >(
+ attributePath,
+ tlv
+ )
+ Log.i(TAG, "OpCred $attributeName value: $value")
+ showMessage(ret.toString())
+ }
+ else -> {
+ Log.i(TAG, "OpCred $attributeName value: $value")
+ showMessage("OpCred $attributeName value: $value")
+ }
+ }
}
},
devicePtr,
diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn
index 22e3cc4..d6c7819 100644
--- a/src/controller/java/BUILD.gn
+++ b/src/controller/java/BUILD.gn
@@ -56,6 +56,7 @@
"CHIPDefaultCallbacks.cpp",
"CHIPDefaultCallbacks.h",
"CHIPDeviceController-JNI.cpp",
+ "CHIPTLVValueDecoder-JNI.cpp",
"DeviceAttestationDelegateBridge.cpp",
"DeviceAttestationDelegateBridge.h",
"zap-generated/CHIPAttributeTLVValueDecoder.cpp",
@@ -328,6 +329,7 @@
"src/chip/devicecontroller/ChipDeviceController.java",
"src/chip/devicecontroller/ChipDeviceControllerException.java",
"src/chip/devicecontroller/ChipIdLookup.java",
+ "src/chip/devicecontroller/ChipTLVValueDecoder.java",
"src/chip/devicecontroller/ControllerParams.java",
"src/chip/devicecontroller/DeviceAttestationDelegate.java",
"src/chip/devicecontroller/DiscoveredDevice.java",
diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp
index 1e6fedc..64c7dac 100644
--- a/src/controller/java/CHIPDeviceController-JNI.cpp
+++ b/src/controller/java/CHIPDeviceController-JNI.cpp
@@ -81,11 +81,11 @@
static CHIP_ERROR GetChipPathIdValue(jobject chipPathId, uint32_t wildcardValue, uint32_t & outValue);
static CHIP_ERROR ParseAttributePathList(jobject attributePathList,
std::vector<app::AttributePathParams> & outAttributePathParamsList);
-static CHIP_ERROR ParseAttributePath(jobject attributePath, EndpointId & outEndpointId, ClusterId & outClusterId,
- AttributeId & outAttributeId);
+CHIP_ERROR ParseAttributePath(jobject attributePath, EndpointId & outEndpointId, ClusterId & outClusterId,
+ AttributeId & outAttributeId);
static CHIP_ERROR ParseEventPathList(jobject eventPathList, std::vector<app::EventPathParams> & outEventPathParamsList);
-static CHIP_ERROR ParseEventPath(jobject eventPath, EndpointId & outEndpointId, ClusterId & outClusterId, EventId & outEventId,
- bool & outIsUrgent);
+CHIP_ERROR ParseEventPath(jobject eventPath, EndpointId & outEndpointId, ClusterId & outClusterId, EventId & outEventId,
+ bool & outIsUrgent);
static CHIP_ERROR IsWildcardChipPathId(jobject chipPathId, bool & isWildcard);
namespace {
diff --git a/src/controller/java/CHIPTLVValueDecoder-JNI.cpp b/src/controller/java/CHIPTLVValueDecoder-JNI.cpp
new file mode 100644
index 0000000..26604b2
--- /dev/null
+++ b/src/controller/java/CHIPTLVValueDecoder-JNI.cpp
@@ -0,0 +1,83 @@
+#include "lib/core/CHIPError.h"
+#include "lib/support/JniTypeWrappers.h"
+
+// #include <lib/support/CHIPMem.h>
+// #include <lib/support/CodeUtils.h>
+#include <lib/support/JniReferences.h>
+#include <lib/support/logging/CHIPLogging.h>
+
+#include "CHIPAttributeTLVValueDecoder.h"
+#include "CHIPEventTLVValueDecoder.h"
+
+#include <jni.h>
+
+using namespace chip;
+
+#define JNI_METHOD(RETURN, METHOD_NAME) \
+ extern "C" JNIEXPORT RETURN JNICALL Java_chip_devicecontroller_ChipTLVValueDecoder_##METHOD_NAME
+
+extern CHIP_ERROR ParseAttributePath(jobject attributePath, EndpointId & outEndpointId, ClusterId & outClusterId,
+ AttributeId & outAttributeId);
+extern CHIP_ERROR ParseEventPath(jobject eventPath, EndpointId & outEndpointId, ClusterId & outClusterId, EventId & outEventId,
+ bool & outIsUrgent);
+
+JNI_METHOD(jobject, decodeAttributeValue)(JNIEnv * env, jclass clazz, jobject attributePath, jbyteArray jTlv)
+{
+ EndpointId endpointId;
+ ClusterId clusterId;
+ AttributeId attributeId;
+ CHIP_ERROR err = ParseAttributePath(attributePath, endpointId, clusterId, attributeId);
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogProgress(Controller, "decode error attributePath");
+ return nullptr;
+ }
+
+ JniByteArray tlv(env, jTlv);
+
+ chip::app::ConcreteAttributePath path(endpointId, clusterId, attributeId);
+
+ chip::TLV::TLVReader reader;
+ reader.Init(tlv.byteSpan());
+ reader.Next();
+
+ jobject ret = DecodeAttributeValue(path, reader, &err);
+
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogProgress(Controller, "decode error attributeValue");
+ return nullptr;
+ }
+
+ return ret;
+}
+
+JNI_METHOD(jobject, decodeEventValue)(JNIEnv * env, jclass clazz, jobject eventPath, jbyteArray jTlv)
+{
+ EndpointId endpointId;
+ ClusterId clusterId;
+ EventId eventId;
+ bool isUrgent;
+ CHIP_ERROR err = ParseEventPath(eventPath, endpointId, clusterId, eventId, isUrgent);
+ if (err != CHIP_NO_ERROR)
+ {
+ return nullptr;
+ }
+
+ JniByteArray tlv(env, jTlv);
+
+ chip::app::ConcreteEventPath path(endpointId, clusterId, eventId);
+ chip::TLV::TLVReader reader;
+
+ reader.Init(tlv.byteSpan());
+ reader.Next();
+
+ jobject ret = DecodeEventValue(path, reader, &err);
+
+ if (err != CHIP_NO_ERROR)
+ {
+ return nullptr;
+ }
+
+ return ret;
+}
diff --git a/src/controller/java/src/chip/devicecontroller/ChipTLVValueDecoder.java b/src/controller/java/src/chip/devicecontroller/ChipTLVValueDecoder.java
new file mode 100644
index 0000000..86c375b
--- /dev/null
+++ b/src/controller/java/src/chip/devicecontroller/ChipTLVValueDecoder.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020-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.devicecontroller;
+
+import chip.devicecontroller.model.ChipAttributePath;
+import chip.devicecontroller.model.ChipEventPath;
+
+public class ChipTLVValueDecoder {
+ public static native <T> T decodeAttributeValue(ChipAttributePath attributePath, byte[] tlv);
+
+ public static native <T> T decodeEventValue(ChipEventPath eventPath, byte[] tlv);
+}