From 1d4ac4563aeaac7a0e2c7dd6eba66b563d24fe4c Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Fri, 14 Jun 2024 03:15:41 +0900 Subject: [PATCH] [Android] Implement remove ICD Client Info (#33843) * Implement remove ICD Client Info in Android platform * Add store, delete ICDClientinfo method * Restyled by whitespace * Restyled by google-java-format * Restyled by clang-format --------- Co-authored-by: Restyled.io --- .../provisioning/UnpairDeviceFragment.kt | 14 +++ src/controller/java/AndroidICDClient.cpp | 102 ++++++++++++++++++ src/controller/java/AndroidICDClient.h | 6 ++ src/controller/java/CHIPICDClient-JNI.cpp | 18 ++++ src/controller/java/MatterICDClient-JNI.cpp | 18 ++++ .../chip/devicecontroller/ChipICDClient.java | 7 ++ .../matter/controller/MatterICDClientImpl.kt | 6 ++ 7 files changed, 171 insertions(+) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/UnpairDeviceFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/UnpairDeviceFragment.kt index f01e43d85fc174..585386dca7eda9 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/UnpairDeviceFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/provisioning/UnpairDeviceFragment.kt @@ -8,11 +8,13 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import chip.devicecontroller.ChipDeviceController +import chip.devicecontroller.ChipICDClient import chip.devicecontroller.UnpairDeviceCallback import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.R import com.google.chip.chiptool.clusterclient.AddressUpdateFragment import com.google.chip.chiptool.databinding.UnpairDeviceFragmentBinding +import com.google.chip.chiptool.util.DeviceIdUtil import kotlinx.coroutines.* class UnpairDeviceFragment : Fragment() { @@ -63,6 +65,18 @@ class UnpairDeviceFragment : Fragment() { addressUpdateFragment.deviceId, ChipUnpairDeviceCallback() ) + + // Remove ICD Client info + if (addressUpdateFragment.isICDDevice()) { + ChipICDClient.clearICDClientInfo(deviceController.fabricIndex, addressUpdateFragment.deviceId) + + Log.d(TAG, "ICDClientInfo : ${ChipICDClient.getICDClientInfo(deviceController.fabricIndex)}") + } + requireActivity().runOnUiThread { + Log.d(TAG, "remove : ${addressUpdateFragment.deviceId}") + DeviceIdUtil.removeCommissionedNodeId(requireContext(), addressUpdateFragment.deviceId) + addressUpdateFragment.updateDeviceIdSpinner() + } } companion object { diff --git a/src/controller/java/AndroidICDClient.cpp b/src/controller/java/AndroidICDClient.cpp index 83cb5222576049..036d92bcf107b7 100644 --- a/src/controller/java/AndroidICDClient.cpp +++ b/src/controller/java/AndroidICDClient.cpp @@ -25,8 +25,11 @@ #include "AndroidICDClient.h" #include +#include chip::app::DefaultICDClientStorage sICDClientStorage; +static CHIP_ERROR ParseICDClientInfo(JNIEnv * env, jint jFabricIndex, jobject jIcdClientInfo, + chip::app::ICDClientInfo & icdClientInfo); jobject getICDClientInfo(JNIEnv * env, const char * icdClientInfoSign, jint jFabricIndex) { @@ -93,6 +96,105 @@ jobject getICDClientInfo(JNIEnv * env, const char * icdClientInfoSign, jint jFab return jInfo; } +CHIP_ERROR StoreICDEntryWithKey(JNIEnv * env, jint jFabricIndex, jobject jicdClientInfo, jbyteArray jKey) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + chip::app::ICDClientInfo clientInfo; + chip::JniByteArray jniKey(env, jKey); + + err = ParseICDClientInfo(env, jFabricIndex, jicdClientInfo, clientInfo); + VerifyOrReturnValue(err == CHIP_NO_ERROR, err, + ChipLogError(Controller, "Failed to parse ICD Client info: %" CHIP_ERROR_FORMAT, err.Format())); + + err = getICDClientStorage()->SetKey(clientInfo, jniKey.byteSpan()); + + if (err == CHIP_NO_ERROR) + { + err = getICDClientStorage()->StoreEntry(clientInfo); + } + else + { + getICDClientStorage()->RemoveKey(clientInfo); + ChipLogError(Controller, "Failed to persist symmetric key with error: %" CHIP_ERROR_FORMAT, err.Format()); + } + + return err; +} + +CHIP_ERROR RemoveICDEntryWithKey(JNIEnv * env, jint jFabricIndex, jobject jicdClientInfo) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + chip::app::ICDClientInfo info; + err = ParseICDClientInfo(env, jFabricIndex, jicdClientInfo, info); + VerifyOrReturnValue(err == CHIP_NO_ERROR, err, + ChipLogError(Controller, "Failed to parse ICD Client info: %" CHIP_ERROR_FORMAT, err.Format())); + + getICDClientStorage()->RemoveKey(info); + + return err; +} + +CHIP_ERROR ClearICDClientInfo(JNIEnv * env, jint jFabricIndex, jlong jNodeId) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + chip::ScopedNodeId scopedNodeId(static_cast(jNodeId), static_cast(jFabricIndex)); + err = getICDClientStorage()->DeleteEntry(scopedNodeId); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "ClearICDClientInfo error!: %" CHIP_ERROR_FORMAT, err.Format()); + } + return err; +} + +CHIP_ERROR ParseICDClientInfo(JNIEnv * env, jint jFabricIndex, jobject jIcdClientInfo, chip::app::ICDClientInfo & icdClientInfo) +{ + VerifyOrReturnError(jIcdClientInfo != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + jmethodID getPeerNodeIdMethod = nullptr; + jmethodID getStartCounterMethod = nullptr; + jmethodID getOffsetMethod = nullptr; + jmethodID getMonitoredSubjectMethod = nullptr; + jmethodID getIcdAesKeyMethod = nullptr; + jmethodID getIcdHmacKeyMethod = nullptr; + + ReturnErrorOnFailure( + chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getPeerNodeId", "()J", &getPeerNodeIdMethod)); + ReturnErrorOnFailure( + chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getStartCounter", "()J", &getStartCounterMethod)); + ReturnErrorOnFailure(chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getOffset", "()J", &getOffsetMethod)); + ReturnErrorOnFailure(chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getMonitoredSubject", "()J", + &getMonitoredSubjectMethod)); + ReturnErrorOnFailure( + chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getIcdAesKey", "()[B", &getIcdAesKeyMethod)); + ReturnErrorOnFailure( + chip::JniReferences::GetInstance().FindMethod(env, jIcdClientInfo, "getIcdHmacKey", "()[B", &getIcdHmacKeyMethod)); + + jlong jPeerNodeId = env->CallLongMethod(jIcdClientInfo, getPeerNodeIdMethod); + jlong jStartCounter = env->CallLongMethod(jIcdClientInfo, getStartCounterMethod); + jlong jOffset = env->CallLongMethod(jIcdClientInfo, getOffsetMethod); + jlong jMonitoredSubject = env->CallLongMethod(jIcdClientInfo, getMonitoredSubjectMethod); + jbyteArray jIcdAesKey = static_cast(env->CallObjectMethod(jIcdClientInfo, getIcdAesKeyMethod)); + jbyteArray jIcdHmacKey = static_cast(env->CallObjectMethod(jIcdClientInfo, getIcdHmacKeyMethod)); + + chip::ScopedNodeId scopedNodeId(static_cast(jPeerNodeId), static_cast(jFabricIndex)); + chip::JniByteArray jniIcdAesKey(env, jIcdAesKey); + chip::JniByteArray jniIcdHmacKey(env, jIcdHmacKey); + + icdClientInfo.peer_node = scopedNodeId; + icdClientInfo.start_icd_counter = static_cast(jStartCounter); + icdClientInfo.offset = static_cast(jOffset); + icdClientInfo.monitored_subject = static_cast(jMonitoredSubject); + memcpy(icdClientInfo.aes_key_handle.AsMutable(), jniIcdAesKey.data(), + sizeof(chip::Crypto::Symmetric128BitsKeyByteArray)); + memcpy(icdClientInfo.hmac_key_handle.AsMutable(), jniIcdHmacKey.data(), + sizeof(chip::Crypto::Symmetric128BitsKeyByteArray)); + + return CHIP_NO_ERROR; +} + chip::app::DefaultICDClientStorage * getICDClientStorage() { return &sICDClientStorage; diff --git a/src/controller/java/AndroidICDClient.h b/src/controller/java/AndroidICDClient.h index e5b929e2a9c5f6..29cc07789d2c03 100644 --- a/src/controller/java/AndroidICDClient.h +++ b/src/controller/java/AndroidICDClient.h @@ -29,4 +29,10 @@ jobject getICDClientInfo(JNIEnv * env, const char * icdClientInfoSign, jint jFabricIndex); +CHIP_ERROR StoreICDEntryWithKey(JNIEnv * env, jint jFabricIndex, jobject jicdClientInfo, jbyteArray jKey); + +CHIP_ERROR RemoveICDEntryWithKey(JNIEnv * env, jint jFabricIndex, jobject jicdClientInfo); + +CHIP_ERROR ClearICDClientInfo(JNIEnv * env, jint jFabricIndex, jlong jNodeId); + chip::app::DefaultICDClientStorage * getICDClientStorage(); diff --git a/src/controller/java/CHIPICDClient-JNI.cpp b/src/controller/java/CHIPICDClient-JNI.cpp index b1fb2574c84465..f975a8e3b13810 100644 --- a/src/controller/java/CHIPICDClient-JNI.cpp +++ b/src/controller/java/CHIPICDClient-JNI.cpp @@ -27,3 +27,21 @@ JNI_METHOD(jobject, getICDClientInfo)(JNIEnv * env, jobject self, jint jFabricIn return getICDClientInfo(env, "chip/devicecontroller/ICDClientInfo", jFabricIndex); } + +JNI_METHOD(void, storeICDEntryWithKey)(JNIEnv * env, jobject self, jint jFabricIndex, jobject jicdClientInfo, jbyteArray jKey) +{ + chip::DeviceLayer::StackLock lock; + StoreICDEntryWithKey(env, jFabricIndex, jicdClientInfo, jKey); +} + +JNI_METHOD(void, removeICDEntryWithKey)(JNIEnv * env, jobject self, jint jFabricIndex, jobject jicdClientInfo) +{ + chip::DeviceLayer::StackLock lock; + RemoveICDEntryWithKey(env, jFabricIndex, jicdClientInfo); +} + +JNI_METHOD(void, clearICDClientInfo)(JNIEnv * env, jobject self, jint jFabricIndex, jlong jNodeId) +{ + chip::DeviceLayer::StackLock lock; + ClearICDClientInfo(env, jFabricIndex, jNodeId); +} diff --git a/src/controller/java/MatterICDClient-JNI.cpp b/src/controller/java/MatterICDClient-JNI.cpp index 45ed4d96c241cb..ece46bdac2d402 100644 --- a/src/controller/java/MatterICDClient-JNI.cpp +++ b/src/controller/java/MatterICDClient-JNI.cpp @@ -27,3 +27,21 @@ JNI_METHOD(jobject, getICDClientInfo)(JNIEnv * env, jobject self, jint jFabricIn return getICDClientInfo(env, "matter/controller/ICDClientInfo", jFabricIndex); } + +JNI_METHOD(void, storeICDEntryWithKey)(JNIEnv * env, jobject self, jint jFabricIndex, jobject jicdClientInfo, jbyteArray jKey) +{ + chip::DeviceLayer::StackLock lock; + StoreICDEntryWithKey(env, jFabricIndex, jicdClientInfo, jKey); +} + +JNI_METHOD(void, removeICDEntryWithKey)(JNIEnv * env, jobject self, jint jFabricIndex, jobject jicdClientInfo) +{ + chip::DeviceLayer::StackLock lock; + RemoveICDEntryWithKey(env, jFabricIndex, jicdClientInfo); +} + +JNI_METHOD(void, clearICDClientInfo)(JNIEnv * env, jobject self, jint jFabricIndex, jlong jNodeId) +{ + chip::DeviceLayer::StackLock lock; + ClearICDClientInfo(env, jFabricIndex, jNodeId); +} diff --git a/src/controller/java/src/chip/devicecontroller/ChipICDClient.java b/src/controller/java/src/chip/devicecontroller/ChipICDClient.java index 4d95a095f010f7..fb1d66923a14d4 100644 --- a/src/controller/java/src/chip/devicecontroller/ChipICDClient.java +++ b/src/controller/java/src/chip/devicecontroller/ChipICDClient.java @@ -30,5 +30,12 @@ public static boolean isPeerICDClient(int fabricIndex, long deviceId) { return clientInfo.stream().anyMatch(info -> info.getPeerNodeId() == deviceId); } + public static native void storeICDEntryWithKey( + int fabricIndex, ICDClientInfo icdClientInfo, byte[] key); + + public static native void removeICDEntryWithKey(int fabricIndex, ICDClientInfo icdClientInfo); + + public static native void clearICDClientInfo(int fabricIndex, long deviceId); + public static native List getICDClientInfo(int fabricIndex); } diff --git a/src/controller/java/src/matter/controller/MatterICDClientImpl.kt b/src/controller/java/src/matter/controller/MatterICDClientImpl.kt index ae91e341904f08..2930574f2c0044 100644 --- a/src/controller/java/src/matter/controller/MatterICDClientImpl.kt +++ b/src/controller/java/src/matter/controller/MatterICDClientImpl.kt @@ -24,5 +24,11 @@ object MatterICDClientImpl { return clientInfo.firstOrNull { it.peerNodeId == deviceId } != null } + external fun storeICDEntryWithKey(fabricIndex: Int, icdClientInfo: ICDClientInfo, key: ByteArray) + + external fun removeICDEntryWithKey(fabricIndex: Int, icdClientInfo: ICDClientInfo) + + external fun clearICDClientInfo(fabricIndex: Int, deviceId: Long) + external fun getICDClientInfo(fabricIndex: Int): List? }