Skip to content

Commit

Permalink
[Android] Implement for supporting ICD device (project-chip#31055)
Browse files Browse the repository at this point in the history
* Implement for supporting ICD device in Android Controller

* Add exception TooManyFunctions

* Restyled by google-java-format

* Restyled by clang-format

* Add comment

* Modify typo, use static_cast

* Modify comments

* Add default parameter for ICD

* Add java test for ICD

* Remove 'p'

* Restyled by google-java-format

* Update comment

* Restyled by google-java-format

---------

Co-authored-by: Restyled.io <commits@restyled.io>
  • Loading branch information
joonhaengHeo and restyled-commits authored Dec 22, 2023
1 parent 0aa3a0c commit 6484d4d
Show file tree
Hide file tree
Showing 14 changed files with 452 additions and 12 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/java-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ jobs:
"./scripts/build/build_examples.py \
--target linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test \
--target linux-x64-java-matter-controller \
--target linux-x64-lit-icd-ipv6only \
build \
"
- name: Build Kotlin Matter Controller
Expand Down Expand Up @@ -210,6 +211,17 @@ jobs:
--tool-args "code --nodeid 1 --setup-payload 34970112332 --discover-once 1 --use-only-onnetwork-discovery 0 -t 1000" \
--factoryreset \
'
- name: Run Pairing ICD Onnetwork Test
run: |
scripts/run_in_python_env.sh out/venv \
'./scripts/tests/run_java_test.py \
--app out/linux-x64-lit-icd-ipv6only/lit-icd-app \
--app-args "--discriminator 3840 --interface-id -1" \
--tool-path out/linux-x64-java-matter-controller \
--tool-cluster "pairing" \
--tool-args "onnetwork-long --nodeid 1 --setup-pin-code 20202021 --discriminator 3840 -t 1000" \
--factoryreset \
'
- name: Run Pairing Onnetwork Test
run: |
scripts/run_in_python_env.sh out/venv \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,12 @@ open class GenericChipDeviceListener : ChipDeviceController.CompletionListener {
override fun onOpCSRGenerationComplete(csr: ByteArray) {
// No op
}

override fun onICDRegistrationInfoRequired() {
// No op
}

override fun onICDRegistrationComplete(icdNodeId: Long, icdCounter: Long) {
// No op
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import androidx.lifecycle.lifecycleScope
import chip.devicecontroller.AttestationInfo
import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.DeviceAttestationDelegate
import chip.devicecontroller.ICDRegistrationInfo
import chip.devicecontroller.NetworkCredentials
import com.google.chip.chiptool.ChipClient
import com.google.chip.chiptool.GenericChipDeviceListener
Expand Down Expand Up @@ -284,6 +285,17 @@ class DeviceProvisioningFragment : Fragment() {
override fun onError(error: Throwable?) {
Log.d(TAG, "onError: $error")
}

override fun onICDRegistrationInfoRequired() {
Log.d(TAG, "onICDRegistrationInfoRequired")
deviceController.updateCommissioningICDRegistrationInfo(
ICDRegistrationInfo.newBuilder().build()
)
}

override fun onICDRegistrationComplete(icdNodeId: Long, icdCounter: Long) {
Log.d(TAG, "onICDRegistrationComplete - icdNodeId : $icdNodeId, icdCounter : $icdCounter")
}
}

/** Callback from [DeviceProvisioningFragment] notifying any registered listeners. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.matter.controller.commands.pairing

import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.ICDRegistrationInfo
import chip.devicecontroller.NetworkCredentials
import com.matter.controller.commands.common.CredentialsIssuer
import com.matter.controller.commands.common.IPAddress
Expand Down Expand Up @@ -178,6 +179,19 @@ abstract class PairingCommand(
}
}

override fun onICDRegistrationInfoRequired() {
logger.log(Level.INFO, "onICDRegistrationInfoRequired")
currentCommissioner()
.updateCommissioningICDRegistrationInfo(ICDRegistrationInfo.newBuilder().build())
}

override fun onICDRegistrationComplete(icdNodeId: Long, icdCounter: Long) {
logger.log(
Level.INFO,
"onICDRegistrationComplete with icdNodeId: $icdNodeId, icdCounter: $icdCounter"
)
}

fun getNodeId(): Long {
return nodeId.get()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ abstract class PairingCommand(
}
}

override fun onICDRegistrationInfoRequired() {
logger.log(Level.INFO, "onICDRegistrationInfoRequired")
}

override fun onICDRegistrationComplete(icdNodeId: Long, icdCounter: Long) {
logger.log(
Level.INFO,
"onICDRegistrationComplete with icdNodeId: $icdNodeId, icdCounter: $icdCounter"
)
}

fun getNodeId(): Long {
return nodeId.get()
}
Expand Down
1 change: 1 addition & 0 deletions kotlin-detect-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ complexity:
- "**/src/controller/java/src/matter/tlv/TlvWriter.kt"
- "**/src/controller/java/src/matter/controller/MatterControllerImpl.kt"
- "**/src/controller/java/src/matter/controller/CompletionListenerAdapter.kt"
- "**/src/controller/java/src/matter/controller/MatterController.kt"
- "**/src/controller/java/tests/matter/jsontlv/JsonToTlvToJsonTest.kt"
- "**/src/controller/java/tests/matter/onboardingpayload/ManualCodeTest.kt"
- "**/src/controller/java/tests/matter/onboardingpayload/QRCodeTest.kt"
Expand Down
85 changes: 85 additions & 0 deletions src/controller/java/AndroidDeviceControllerWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,66 @@ CHIP_ERROR AndroidDeviceControllerWrapper::ApplyNetworkCredentials(chip::Control
return err;
}

CHIP_ERROR AndroidDeviceControllerWrapper::ApplyICDRegistrationInfo(chip::Controller::CommissioningParameters & params,
jobject icdRegistrationInfo)
{
chip::DeviceLayer::StackUnlock unlock;
CHIP_ERROR err = CHIP_NO_ERROR;

VerifyOrReturnError(icdRegistrationInfo != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread();
jmethodID getCheckInNodeIdMethod;
err = chip::JniReferences::GetInstance().FindMethod(env, icdRegistrationInfo, "getCheckInNodeId", "()Ljava/lang/Long;",
&getCheckInNodeIdMethod);
VerifyOrReturnError(err == CHIP_NO_ERROR, err);
jobject jCheckInNodeId = env->CallObjectMethod(icdRegistrationInfo, getCheckInNodeIdMethod);

jmethodID getMonitoredSubjectMethod;
err = chip::JniReferences::GetInstance().FindMethod(env, icdRegistrationInfo, "getMonitoredSubject", "()Ljava/lang/Long;",
&getMonitoredSubjectMethod);
VerifyOrReturnError(err == CHIP_NO_ERROR, err);
jobject jMonitoredSubject = env->CallObjectMethod(icdRegistrationInfo, getMonitoredSubjectMethod);

jmethodID getSymmetricKeyMethod;
err =
chip::JniReferences::GetInstance().FindMethod(env, icdRegistrationInfo, "getSymmetricKey", "()[B", &getSymmetricKeyMethod);
VerifyOrReturnError(err == CHIP_NO_ERROR, err);
jbyteArray jSymmetricKey = static_cast<jbyteArray>(env->CallObjectMethod(icdRegistrationInfo, getSymmetricKeyMethod));

chip::NodeId checkInNodeId = chip::kUndefinedNodeId;
if (jCheckInNodeId != nullptr)
{
checkInNodeId = static_cast<chip::NodeId>(chip::JniReferences::GetInstance().LongToPrimitive(jCheckInNodeId));
}
else
{
checkInNodeId = mController->GetNodeId();
}
params.SetICDCheckInNodeId(checkInNodeId);

uint64_t monitoredSubject = static_cast<uint64_t>(checkInNodeId);
if (jMonitoredSubject != nullptr)
{
monitoredSubject = static_cast<uint64_t>(chip::JniReferences::GetInstance().LongToPrimitive(jMonitoredSubject));
}
params.SetICDMonitoredSubject(monitoredSubject);

if (jSymmetricKey != nullptr)
{
JniByteArray jniSymmetricKey(env, jSymmetricKey);
VerifyOrReturnError(jniSymmetricKey.size() == sizeof(mICDSymmetricKey), CHIP_ERROR_INVALID_ARGUMENT);
memcpy(mICDSymmetricKey, jniSymmetricKey.data(), sizeof(mICDSymmetricKey));
}
else
{
chip::Crypto::DRBG_get_bytes(mICDSymmetricKey, sizeof(mICDSymmetricKey));
}
params.SetICDSymmetricKey(chip::ByteSpan(mICDSymmetricKey));

return err;
}

CHIP_ERROR AndroidDeviceControllerWrapper::UpdateCommissioningParameters(const chip::Controller::CommissioningParameters & params)
{
// this will wipe out any custom attestationNonce and csrNonce that was being used.
Expand Down Expand Up @@ -814,6 +874,31 @@ void AndroidDeviceControllerWrapper::OnScanNetworksFailure(CHIP_ERROR error)
CallJavaMethod("onScanNetworksFailure", static_cast<jint>(error.AsInteger()));
}

void AndroidDeviceControllerWrapper::OnICDRegistrationInfoRequired()
{
chip::DeviceLayer::StackUnlock unlock;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
jmethodID onICDRegistrationInfoRequiredMethod;
CHIP_ERROR err = JniReferences::GetInstance().FindMethod(env, mJavaObjectRef, "onICDRegistrationInfoRequired", "()V",
&onICDRegistrationInfoRequiredMethod);
VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Error finding Java method: %" CHIP_ERROR_FORMAT, err.Format()));

env->CallVoidMethod(mJavaObjectRef, onICDRegistrationInfoRequiredMethod);
}

void AndroidDeviceControllerWrapper::OnICDRegistrationComplete(chip::NodeId icdNodeId, uint32_t icdCounter)
{
chip::DeviceLayer::StackUnlock unlock;
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
jmethodID onICDRegistrationCompleteMethod;
CHIP_ERROR err = JniReferences::GetInstance().FindMethod(env, mJavaObjectRef, "onICDRegistrationComplete", "(JJ)V",
&onICDRegistrationCompleteMethod);
VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(Controller, "Error finding Java method: %" CHIP_ERROR_FORMAT, err.Format()));

env->CallVoidMethod(mJavaObjectRef, onICDRegistrationCompleteMethod, static_cast<jlong>(icdNodeId),
static_cast<jlong>(icdCounter));
}

CHIP_ERROR AndroidDeviceControllerWrapper::SyncGetKeyValue(const char * key, void * value, uint16_t & size)
{
ChipLogProgress(chipTool, "KVS: Getting key %s", StringOrNullMarker(key));
Expand Down
8 changes: 8 additions & 0 deletions src/controller/java/AndroidDeviceControllerWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel
*/
CHIP_ERROR ApplyNetworkCredentials(chip::Controller::CommissioningParameters & params, jobject networkCredentials);

/**
* Convert ICD Registration Infomations from Java, and apply them to the commissioning parameters object.
*/
CHIP_ERROR ApplyICDRegistrationInfo(chip::Controller::CommissioningParameters & params, jobject icdRegistrationInfo);

/**
* Update the CommissioningParameters used by the active device commissioner
*/
Expand All @@ -103,6 +108,8 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel
void OnScanNetworksSuccess(
const chip::app::Clusters::NetworkCommissioning::Commands::ScanNetworksResponse::DecodableType & dataResponse) override;
void OnScanNetworksFailure(CHIP_ERROR error) override;
void OnICDRegistrationInfoRequired() override;
void OnICDRegistrationComplete(chip::NodeId icdNodeId, uint32_t icdCounter) override;

// PersistentStorageDelegate implementation
CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override;
Expand Down Expand Up @@ -242,6 +249,7 @@ class AndroidDeviceControllerWrapper : public chip::Controller::DevicePairingDel
#if CHIP_DEVICE_CONFIG_DYNAMIC_SERVER
OTAProviderDelegateBridge * mOtaProviderBridge = nullptr;
#endif
uint8_t mICDSymmetricKey[chip::Crypto::kAES_CCM128_Key_Length];

AndroidDeviceControllerWrapper(ChipDeviceControllerPtr controller,
#ifdef JAVA_MATTER_CONTROLLER_TEST
Expand Down
1 change: 1 addition & 0 deletions src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ android_library("java") {
"src/chip/devicecontroller/DiscoveredDevice.java",
"src/chip/devicecontroller/GetConnectedDeviceCallbackJni.java",
"src/chip/devicecontroller/GroupKeySecurityPolicy.java",
"src/chip/devicecontroller/ICDRegistrationInfo.java",
"src/chip/devicecontroller/InvokeCallback.java",
"src/chip/devicecontroller/InvokeCallbackJni.java",
"src/chip/devicecontroller/KeypairDelegate.java",
Expand Down
61 changes: 58 additions & 3 deletions src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ JNI_METHOD(void, commissionDevice)

JNI_METHOD(void, pairDevice)
(JNIEnv * env, jobject self, jlong handle, jlong deviceId, jint connObj, jlong pinCode, jbyteArray csrNonce,
jobject networkCredentials)
jobject networkCredentials, jobject icdRegistrationInfo)
{
chip::DeviceLayer::StackLock lock;
CHIP_ERROR err = CHIP_NO_ERROR;
Expand Down Expand Up @@ -656,6 +656,13 @@ JNI_METHOD(void, pairDevice)
JniByteArray jniCsrNonce(env, csrNonce);
commissioningParams.SetCSRNonce(jniCsrNonce.byteSpan());
}

commissioningParams.SetICDRegistrationStrategy(ICDRegistrationStrategy::kBeforeComplete);
if (icdRegistrationInfo != nullptr)
{
wrapper->ApplyICDRegistrationInfo(commissioningParams, icdRegistrationInfo);
}

if (wrapper->GetDeviceAttestationDelegateBridge() != nullptr)
{
commissioningParams.SetDeviceAttestationDelegate(wrapper->GetDeviceAttestationDelegateBridge());
Expand All @@ -671,7 +678,7 @@ JNI_METHOD(void, pairDevice)

JNI_METHOD(void, pairDeviceWithAddress)
(JNIEnv * env, jobject self, jlong handle, jlong deviceId, jstring address, jint port, jint discriminator, jlong pinCode,
jbyteArray csrNonce)
jbyteArray csrNonce, jobject icdRegistrationInfo)
{
chip::DeviceLayer::StackLock lock;
CHIP_ERROR err = CHIP_NO_ERROR;
Expand Down Expand Up @@ -699,6 +706,13 @@ JNI_METHOD(void, pairDeviceWithAddress)
JniByteArray jniCsrNonce(env, csrNonce);
commissioningParams.SetCSRNonce(jniCsrNonce.byteSpan());
}

commissioningParams.SetICDRegistrationStrategy(ICDRegistrationStrategy::kBeforeComplete);
if (icdRegistrationInfo != nullptr)
{
wrapper->ApplyICDRegistrationInfo(commissioningParams, icdRegistrationInfo);
}

if (wrapper->GetDeviceAttestationDelegateBridge() != nullptr)
{
commissioningParams.SetDeviceAttestationDelegate(wrapper->GetDeviceAttestationDelegateBridge());
Expand All @@ -714,7 +728,7 @@ JNI_METHOD(void, pairDeviceWithAddress)

JNI_METHOD(void, pairDeviceWithCode)
(JNIEnv * env, jobject self, jlong handle, jlong deviceId, jstring setUpCode, jboolean discoverOnce,
jboolean useOnlyOnNetworkDiscovery, jbyteArray csrNonce, jobject networkCredentials)
jboolean useOnlyOnNetworkDiscovery, jbyteArray csrNonce, jobject networkCredentials, jobject icdRegistrationInfo)
{
chip::DeviceLayer::StackLock lock;
CHIP_ERROR err = CHIP_NO_ERROR;
Expand Down Expand Up @@ -748,6 +762,12 @@ JNI_METHOD(void, pairDeviceWithCode)
wrapper->ApplyNetworkCredentials(commissioningParams, networkCredentials);
}

commissioningParams.SetICDRegistrationStrategy(ICDRegistrationStrategy::kBeforeComplete);
if (icdRegistrationInfo != nullptr)
{
wrapper->ApplyICDRegistrationInfo(commissioningParams, icdRegistrationInfo);
}

if (wrapper->GetDeviceAttestationDelegateBridge() != nullptr)
{
commissioningParams.SetDeviceAttestationDelegate(wrapper->GetDeviceAttestationDelegateBridge());
Expand Down Expand Up @@ -899,6 +919,41 @@ JNI_METHOD(void, updateCommissioningNetworkCredentials)
}
}

JNI_METHOD(void, updateCommissioningICDRegistrationInfo)
(JNIEnv * env, jobject self, jlong handle, jobject icdRegistrationInfo)
{
ChipLogProgress(Controller, "updateCommissioningICDRegistrationInfo() called");
chip::DeviceLayer::StackLock lock;
AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);

CommissioningParameters commissioningParams = wrapper->GetCommissioningParameters();
CHIP_ERROR err = wrapper->ApplyICDRegistrationInfo(commissioningParams, icdRegistrationInfo);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "ApplyICDRegistrationInfo failed. Err = %" CHIP_ERROR_FORMAT, err.Format());
JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err);
return;
}
err = wrapper->UpdateCommissioningParameters(commissioningParams);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "UpdateCommissioningParameters failed. Err = %" CHIP_ERROR_FORMAT, err.Format());
JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err);
return;
}

// Only invoke ICDRegistrationInfoReady when called in ICDRegistartionInfo stage.
if (wrapper->Controller()->GetCommissioningStage() == CommissioningStage::kICDGetRegistrationInfo)
{
err = wrapper->Controller()->ICDRegistrationInfoReady();
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "ICDRegistrationInfoReady failed. Err = %" CHIP_ERROR_FORMAT, err.Format());
JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err);
}
}
}

jint GetCalendarFieldID(JNIEnv * env, const char * method)
{
jclass calendarCls = env->FindClass("java/util/Calendar");
Expand Down
Loading

0 comments on commit 6484d4d

Please sign in to comment.