Skip to content

Commit

Permalink
[Android] Implement remove ICD Client Info (project-chip#33843)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
joonhaengHeo and restyled-commits authored Jun 13, 2024
1 parent 540c991 commit 1d4ac45
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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 {
Expand Down
102 changes: 102 additions & 0 deletions src/controller/java/AndroidICDClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
#include "AndroidICDClient.h"

#include <app/icd/client/ICDClientInfo.h>
#include <lib/support/JniTypeWrappers.h>

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)
{
Expand Down Expand Up @@ -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<chip::NodeId>(jNodeId), static_cast<chip::FabricIndex>(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<jbyteArray>(env->CallObjectMethod(jIcdClientInfo, getIcdAesKeyMethod));
jbyteArray jIcdHmacKey = static_cast<jbyteArray>(env->CallObjectMethod(jIcdClientInfo, getIcdHmacKeyMethod));

chip::ScopedNodeId scopedNodeId(static_cast<chip::NodeId>(jPeerNodeId), static_cast<chip::FabricIndex>(jFabricIndex));
chip::JniByteArray jniIcdAesKey(env, jIcdAesKey);
chip::JniByteArray jniIcdHmacKey(env, jIcdHmacKey);

icdClientInfo.peer_node = scopedNodeId;
icdClientInfo.start_icd_counter = static_cast<uint32_t>(jStartCounter);
icdClientInfo.offset = static_cast<uint32_t>(jOffset);
icdClientInfo.monitored_subject = static_cast<uint64_t>(jMonitoredSubject);
memcpy(icdClientInfo.aes_key_handle.AsMutable<chip::Crypto::Symmetric128BitsKeyByteArray>(), jniIcdAesKey.data(),
sizeof(chip::Crypto::Symmetric128BitsKeyByteArray));
memcpy(icdClientInfo.hmac_key_handle.AsMutable<chip::Crypto::Symmetric128BitsKeyByteArray>(), jniIcdHmacKey.data(),
sizeof(chip::Crypto::Symmetric128BitsKeyByteArray));

return CHIP_NO_ERROR;
}

chip::app::DefaultICDClientStorage * getICDClientStorage()
{
return &sICDClientStorage;
Expand Down
6 changes: 6 additions & 0 deletions src/controller/java/AndroidICDClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
18 changes: 18 additions & 0 deletions src/controller/java/CHIPICDClient-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
18 changes: 18 additions & 0 deletions src/controller/java/MatterICDClient-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<ICDClientInfo> getICDClientInfo(int fabricIndex);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<ICDClientInfo>?
}

0 comments on commit 1d4ac45

Please sign in to comment.