From 2f2312e5046c7da1c0e5a461189bc56399a79263 Mon Sep 17 00:00:00 2001 From: Joonhaeng Heo Date: Thu, 22 Dec 2022 15:54:02 +0900 Subject: [PATCH] Modify from reviewer comments --- .../provisioning/UnpairDeviceFragment.kt | 18 +- .../commands/pairing/PairingCommand.cpp | 21 +- .../commands/pairing/PairingCommand.h | 9 +- src/controller/BUILD.gn | 4 +- src/controller/CHIPDeviceController.cpp | 24 +-- src/controller/CHIPDeviceController.h | 9 +- src/controller/CurrentFabricRemover.cpp | 190 +++++++++++++++++ src/controller/CurrentFabricRemover.h | 107 ++++++++++ src/controller/DeviceUnpair.cpp | 195 ------------------ src/controller/DeviceUnpair.h | 95 --------- .../java/AndroidCurrentFabricRemover.cpp | 103 +++++++++ .../java/AndroidCurrentFabricRemover.h | 49 +++++ src/controller/java/BUILD.gn | 3 + .../java/CHIPDeviceController-JNI.cpp | 18 ++ .../ChipDeviceController.java | 7 + .../UnpairDeviceCallback.java | 24 +++ 16 files changed, 546 insertions(+), 330 deletions(-) create mode 100644 src/controller/CurrentFabricRemover.cpp create mode 100644 src/controller/CurrentFabricRemover.h delete mode 100644 src/controller/DeviceUnpair.cpp delete mode 100644 src/controller/DeviceUnpair.h create mode 100644 src/controller/java/AndroidCurrentFabricRemover.cpp create mode 100644 src/controller/java/AndroidCurrentFabricRemover.h create mode 100644 src/controller/java/src/chip/devicecontroller/UnpairDeviceCallback.java 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 5194f8d3e8361c..801d4fc1272836 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 @@ -7,11 +7,9 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope -import chip.devicecontroller.ChipClusters import chip.devicecontroller.ChipDeviceController -import chip.devicecontroller.OpenCommissioningCallback +import chip.devicecontroller.UnpairDeviceCallback import com.google.chip.chiptool.ChipClient -import com.google.chip.chiptool.GenericChipDeviceListener import com.google.chip.chiptool.R import com.google.chip.chiptool.clusterclient.AddressUpdateFragment import kotlinx.android.synthetic.main.unpair_device_fragment.view.unpairDeviceBtn @@ -33,8 +31,6 @@ class UnpairDeviceFragment : Fragment() { scope = viewLifecycleOwner.lifecycleScope return inflater.inflate(R.layout.unpair_device_fragment, container, false).apply { - deviceController.setCompletionListener(ChipControllerCallback()) - addressUpdateFragment = childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment @@ -42,14 +38,18 @@ class UnpairDeviceFragment : Fragment() { } } - inner class ChipControllerCallback : GenericChipDeviceListener() { - override fun onPairingDeleted(code: Int) { - Log.d(TAG, "onPairingDeleted : $code") + inner class ChipUnpairDeviceCallback : UnpairDeviceCallback { + override fun onError(status: Int, remoteDeviceId: Long) { + Log.d(TAG, "onError : $remoteDeviceId, $status") + } + + override fun onSuccess(remoteDeviceId: Long) { + Log.d(TAG, "onSuccess : $remoteDeviceId") } } private fun unpairDeviceClick() { - deviceController.unpairDevice(addressUpdateFragment.deviceId) + deviceController.unpairDeviceCallback(addressUpdateFragment.deviceId, ChipUnpairDeviceCallback()) } diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp index 91a4a6ced4dc51..e80b11c7d22525 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.cpp +++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp @@ -161,8 +161,8 @@ CHIP_ERROR PairingCommand::PairWithMdns(NodeId remoteId) CHIP_ERROR PairingCommand::Unpair(NodeId remoteId) { - CHIP_ERROR err = CurrentCommissioner().UnpairDevice(remoteId); - return err; + mCurrentFabricRemover = Platform::MakeUnique(&CurrentCommissioner()); + return mCurrentFabricRemover->CurrentFabricRemove(remoteId, &mCurrentFabricRemoveCallback); } void PairingCommand::OnStatusUpdate(DevicePairingDelegate::Status status) @@ -264,3 +264,20 @@ void PairingCommand::OnDiscoveredDevice(const chip::Dnssd::DiscoveredNodeData & SetCommandExitStatus(err); } } + +void PairingCommand::OnCurrentFabricRemove(void * context, NodeId remoteDeviceId, CHIP_ERROR err) +{ + PairingCommand * command = reinterpret_cast(context); + VerifyOrReturn(command != nullptr, ChipLogError(chipTool, "OnOpenCommissioningWindowCommand: context is null")); + + if (err == CHIP_NO_ERROR) + { + ChipLogProgress(chipTool, "Device unpair completed with success: " ChipLogFormatX64, ChipLogValueX64(remoteDeviceId)); + } + else + { + ChipLogProgress(chipTool, "Device unpair Failure: " ChipLogFormatX64 " %s", ChipLogValueX64(remoteDeviceId), ErrorStr(err)); + } + + command->SetCommandExitStatus(err); +} diff --git a/examples/chip-tool/commands/pairing/PairingCommand.h b/examples/chip-tool/commands/pairing/PairingCommand.h index 3edd1cfd9e3f4e..2fd6f1acac7a0b 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.h +++ b/examples/chip-tool/commands/pairing/PairingCommand.h @@ -55,7 +55,8 @@ class PairingCommand : public CHIPCommand, chip::Dnssd::DiscoveryFilterType filterType = chip::Dnssd::DiscoveryFilterType::kNone) : CHIPCommand(commandName, credIssuerCmds), mPairingMode(mode), mNetworkType(networkType), - mFilterType(filterType), mRemoteAddr{ IPAddress::Any, chip::Inet::InterfaceId::Null() } + mFilterType(filterType), mRemoteAddr{ IPAddress::Any, chip::Inet::InterfaceId::Null() }, + mCurrentFabricRemoveCallback(OnCurrentFabricRemove, this) { AddArgument("node-id", 0, UINT64_MAX, &mNodeId); @@ -184,4 +185,10 @@ class PairingCommand : public CHIPCommand, char * mOnboardingPayload; uint64_t mDiscoveryFilterCode; char * mDiscoveryFilterInstanceName; + + // For unpair + chip::Platform::UniquePtr mCurrentFabricRemover; + chip::Callback::Callback mCurrentFabricRemoveCallback; + + static void OnCurrentFabricRemove(void * context, NodeId remoteDeviceId, CHIP_ERROR status); }; diff --git a/src/controller/BUILD.gn b/src/controller/BUILD.gn index fb9d00ff1009ac..cdb5726c338d53 100644 --- a/src/controller/BUILD.gn +++ b/src/controller/BUILD.gn @@ -46,10 +46,10 @@ static_library("controller") { "CommissioningDelegate.cpp", "CommissioningWindowOpener.cpp", "CommissioningWindowOpener.h", + "CurrentFabricRemover.cpp", + "CurrentFabricRemover.h", "DeviceDiscoveryDelegate.h", "DevicePairingDelegate.h", - "DeviceUnpair.cpp", - "DeviceUnpair.h", "EmptyDataModelHandler.cpp", "ExampleOperationalCredentialsIssuer.cpp", "ExampleOperationalCredentialsIssuer.h", diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 0f6a6c3f8eb040..02b6c3f9fe4774 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -896,35 +896,19 @@ CHIP_ERROR DeviceCommissioner::UnpairDevice(NodeId remoteDeviceId) { CHIP_ERROR err = CHIP_NO_ERROR; MATTER_TRACE_EVENT_SCOPE("UnpairDevice", "DeviceCommissioner"); - VerifyOrReturnError(mDeviceUnpair == nullptr, CHIP_ERROR_INCORRECT_STATE); - Platform::UniquePtr deviceUnpair(new DeviceUnpair()); - deviceUnpair->RegisterCallback(this); - CommissioneeDeviceProxy * commissioneeDeviceProxy = nullptr; - if (CHIP_NO_ERROR == GetDeviceBeingCommissioned(remoteDeviceId, &commissioneeDeviceProxy)) + if (mState == State::Initialized) { - deviceUnpair->UnpairDevice(commissioneeDeviceProxy, remoteDeviceId); + err = AutoCurrentFabricRemover::RemoveCurrentFabric(this, remoteDeviceId); } - else + else // the device is currently being paired { - err = GetConnectedDevice(remoteDeviceId, &deviceUnpair->GetConnectedCallback(), - &deviceUnpair->GetConnectionFailureCallback()); + err = StopPairing(remoteDeviceId); } - mDeviceUnpair = std::move(deviceUnpair); - return err; } -void DeviceCommissioner::OnDeviceUnpair(NodeId remoteDeviceId, CHIP_ERROR err) -{ - mDeviceUnpair = nullptr; - if (mPairingDelegate != nullptr) - { - mPairingDelegate->OnPairingDeleted(err); - } -} - void DeviceCommissioner::RendezvousCleanup(CHIP_ERROR status) { if (mDeviceInPASEEstablishment != nullptr) diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index f15bfb652ff210..758e72f1a38735 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -39,8 +39,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -371,8 +371,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, public Protocols::UserDirectedCommissioning::InstanceNameResolver, #endif public SessionEstablishmentDelegate, - public app::ClusterStateCache::Callback, - public DeviceUnpair::Callback + public app::ClusterStateCache::Callback { public: DeviceCommissioner(); @@ -532,8 +531,6 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, */ CHIP_ERROR UnpairDevice(NodeId remoteDeviceId); - void OnDeviceUnpair(NodeId remoteDeviceId, CHIP_ERROR err) override; - //////////// SessionEstablishmentDelegate Implementation /////////////// void OnSessionEstablishmentError(CHIP_ERROR error) override; void OnSessionEstablished(const SessionHandle & session) override; @@ -917,7 +914,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, Platform::UniquePtr mAttestationDeviceInfo; Credentials::DeviceAttestationVerifier * mDeviceAttestationVerifier = nullptr; - Platform::UniquePtr mDeviceUnpair; + // Platform::UniquePtr mDeviceUnpair; }; } // namespace Controller diff --git a/src/controller/CurrentFabricRemover.cpp b/src/controller/CurrentFabricRemover.cpp new file mode 100644 index 00000000000000..2e5f04b69e40f3 --- /dev/null +++ b/src/controller/CurrentFabricRemover.cpp @@ -0,0 +1,190 @@ +/* + * + * Copyright (c) 2021 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. + */ + +#include + +#include +#include + +using namespace chip::app::Clusters; + +namespace chip { +namespace Controller { + +CHIP_ERROR CurrentFabricRemover::CurrentFabricRemove(NodeId remoteDeviceId, Callback::Callback * callback) +{ + mRemoteDeviceId = remoteDeviceId; + mCurrentFabricRemoveCallback = callback; + mNextStep = Step::kReadCurrentFabricIndex; + + return mCommissioner->GetConnectedDevice(remoteDeviceId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); +} + +CHIP_ERROR CurrentFabricRemover::ReadCurrentFabricIndex(Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle) +{ + using TypeInfo = chip::app::Clusters::OperationalCredentials::Attributes::CurrentFabricIndex::TypeInfo; + OperationalCredentialsCluster cluster(exchangeMgr, sessionHandle, kRootEndpointId); + + return cluster.ReadAttribute(this, OnSuccessReadCurrentFabricIndex, OnReadAttributeFailure); +} + +CHIP_ERROR CurrentFabricRemover::SendRemoveFabricIndex(Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle) +{ + if (mFabricIndex == kUndefinedFabricIndex) + { + return CHIP_ERROR_INVALID_FABRIC_INDEX; + } + ChipLogProgress(Controller, "SendRemoveFabricIndex : %u", mFabricIndex); + + OperationalCredentials::Commands::RemoveFabric::Type request; + request.fabricIndex = mFabricIndex; + + OperationalCredentialsCluster cluster(exchangeMgr, sessionHandle, 0); + + return cluster.InvokeCommand(request, this, OnSuccessRemoveFabric, OnCommandFailure); +} + +void CurrentFabricRemover::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr, + SessionHandle & sessionHandle) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + auto * self = static_cast(context); + VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); + + switch (self->mNextStep) + { + case Step::kReadCurrentFabricIndex: { + err = self->ReadCurrentFabricIndex(exchangeMgr, sessionHandle); + break; + } + case Step::kSendRemoveFabric: { + err = self->SendRemoveFabricIndex(exchangeMgr, sessionHandle); + break; + } + default: + err = CHIP_ERROR_INCORRECT_STATE; + break; + } + + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "%" CHIP_ERROR_FORMAT, err.Format()); + FinishRemoveCurrentFabric(context, err); + } + + return; +} + +void CurrentFabricRemover::OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR err) +{ + ChipLogProgress(Controller, "OnDeviceConnectionFailureFn: %s", err.AsString()); + + auto * self = static_cast(context); + VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); + + FinishRemoveCurrentFabric(context, err); + return; +} + +void CurrentFabricRemover::OnSuccessReadCurrentFabricIndex(void * context, uint8_t fabricIndex) +{ + auto * self = static_cast(context); + VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); + self->mFabricIndex = fabricIndex; + self->mNextStep = Step::kSendRemoveFabric; + CHIP_ERROR err = self->mCommissioner->GetConnectedDevice(self->mRemoteDeviceId, &self->mOnDeviceConnectedCallback, + &self->mOnDeviceConnectionFailureCallback); + if (err != CHIP_NO_ERROR) + { + FinishRemoveCurrentFabric(context, err); + } + return; +} + +void CurrentFabricRemover::OnReadAttributeFailure(void * context, CHIP_ERROR err) +{ + ChipLogProgress(Controller, "OnReadAttributeFailure %s", err.AsString()); + + auto * self = static_cast(context); + VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); + + FinishRemoveCurrentFabric(context, err); + return; +} + +void CurrentFabricRemover::OnSuccessRemoveFabric(void * context, + const OperationalCredentials::Commands::NOCResponse::DecodableType & data) +{ + auto * self = static_cast(context); + VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); + + FinishRemoveCurrentFabric(context, CHIP_NO_ERROR); + return; +} + +void CurrentFabricRemover::OnCommandFailure(void * context, CHIP_ERROR err) +{ + ChipLogProgress(Controller, "OnCommandFailure %s", err.AsString()); + + auto * self = static_cast(context); + VerifyOrReturn(self != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); + + FinishRemoveCurrentFabric(context, err); + return; +} + +void CurrentFabricRemover::FinishRemoveCurrentFabric(void * context, CHIP_ERROR err) +{ + ChipLogError(Controller, "Remove Current Fabric Result : %" CHIP_ERROR_FORMAT, err.Format()); + auto * self = static_cast(context); + self->mNextStep = Step::kAcceptRemoveFabricStart; + if (self->mCurrentFabricRemoveCallback != nullptr) + { + self->mCurrentFabricRemoveCallback->mCall(self->mCurrentFabricRemoveCallback->mContext, self->mRemoteDeviceId, err); + } +} + +AutoCurrentFabricRemover::AutoCurrentFabricRemover(DeviceCommissioner * commissioner) : + CurrentFabricRemover(commissioner), mOnRemoveCurrentFabricCallback(OnRemoveCurrentFabric, this) +{} + +CHIP_ERROR AutoCurrentFabricRemover::RemoveCurrentFabric(DeviceCommissioner * commissoner, NodeId remoteDeviceId) +{ + // Not using Platform::New because we want to keep our constructor private. + auto * remover = new (std::nothrow) AutoCurrentFabricRemover(commissoner); + if (remover == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + + CHIP_ERROR err = remover->CurrentFabricRemover::CurrentFabricRemove(remoteDeviceId, &remover->mOnRemoveCurrentFabricCallback); + if (err != CHIP_NO_ERROR) + { + delete remover; + } + // Else will clean up when the callback is called. + return err; +} + +void AutoCurrentFabricRemover::OnRemoveCurrentFabric(void * context, NodeId remoteDeviceId, CHIP_ERROR status) +{ + auto * self = static_cast(context); + delete self; +} +} // namespace Controller +} // namespace chip diff --git a/src/controller/CurrentFabricRemover.h b/src/controller/CurrentFabricRemover.h new file mode 100644 index 00000000000000..a9f2c7cd72b117 --- /dev/null +++ b/src/controller/CurrentFabricRemover.h @@ -0,0 +1,107 @@ +/* + * + * Copyright (c) 2021 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 +#include +#include + +namespace chip { +namespace Controller { + +typedef void (*OnCurrentFabricRemove)(void * context, NodeId remoteDeviceId, CHIP_ERROR status); + +/** + * A helper class to remove fabric given some parameters. + */ +class CurrentFabricRemover +{ +public: + CurrentFabricRemover(DeviceCommissioner * commissioner) : + mCommissioner(commissioner), mOnDeviceConnectedCallback(&OnDeviceConnectedFn, this), + mOnDeviceConnectionFailureCallback(&OnDeviceConnectionFailureFn, this) + {} + + enum class Step : uint8_t + { + // Ready to start removing a fabric. + kAcceptRemoveFabricStart = 0, + // Need to get Current Fabric Index. + kReadCurrentFabricIndex, + // Need to send Remove Fabric Command. + kSendRemoveFabric, + }; + + /* + * @brief + * Try to look up the device attached to our controller with the given + * remote device id and ask it to remove Fabric. + * + * @param[in] remoteDeviceId The remote device Id + * @param[in] callback The callback to call once the remote fabric is completed or not. + */ + CHIP_ERROR CurrentFabricRemove(NodeId remoteDeviceId, Callback::Callback * callback); + +private: + DeviceCommissioner * mCommissioner; + + chip::Callback::Callback mOnDeviceConnectedCallback; + chip::Callback::Callback mOnDeviceConnectionFailureCallback; + chip::Callback::Callback * mCurrentFabricRemoveCallback; + + NodeId mRemoteDeviceId; + FabricIndex mFabricIndex = kUndefinedFabricIndex; + Step mNextStep = Step::kAcceptRemoveFabricStart; + + CHIP_ERROR ReadCurrentFabricIndex(Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle); + CHIP_ERROR SendRemoveFabricIndex(Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle); + + static void OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle); + static void OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error); + + static void OnSuccessReadCurrentFabricIndex(void * context, uint8_t fabricIndex); + static void OnReadAttributeFailure(void * context, CHIP_ERROR error); + + static void + OnSuccessRemoveFabric(void * context, + const chip::app::Clusters::OperationalCredentials::Commands::NOCResponse::DecodableType & data); + static void OnCommandFailure(void * context, CHIP_ERROR error); + + static void FinishRemoveCurrentFabric(void * context, CHIP_ERROR err); +}; + +/** + * A helper class that can be used by consumers that don't care about the callback from the + * remove fabric process and just want automatic cleanup of the CurrentFabricRemover when done + * with it. + */ +class AutoCurrentFabricRemover : private CurrentFabricRemover +{ +public: + // Takes the same arguments as CurrentFabricRemover::RemoveCurrentFabric except without the callback. + static CHIP_ERROR RemoveCurrentFabric(DeviceCommissioner * commissoner, NodeId remoteDeviceId); + +private: + AutoCurrentFabricRemover(DeviceCommissioner * commissioner); + static void OnRemoveCurrentFabric(void * context, NodeId remoteDeviceId, CHIP_ERROR status); + chip::Callback::Callback mOnRemoveCurrentFabricCallback; +}; + +} // namespace Controller +} // namespace chip diff --git a/src/controller/DeviceUnpair.cpp b/src/controller/DeviceUnpair.cpp deleted file mode 100644 index 8377e62e523f54..00000000000000 --- a/src/controller/DeviceUnpair.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * - * Copyright (c) 2021 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. - */ - -#include - -#include -#include - -using namespace chip::app::Clusters; - -namespace chip { -namespace Controller { - -DeviceUnpair::DeviceUnpair() : - mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this) -{} - -void DeviceUnpair::RegisterCallback(Callback * callback) -{ - mCallback = callback; -} -void DeviceUnpair::UnpairDevice(DeviceProxy * proxy, NodeId remoteDeviceId) -{ - mRemoteDeviceId = remoteDeviceId; - RegisterDeviceProxy(proxy); - PerformDeviceUnpairStep(UnpairDeviceStage::kReadCurrentFabricIndex); -} - -void DeviceUnpair::PerformDeviceUnpairStep(UnpairDeviceStage stage) -{ - if (mProxy == nullptr) - { - mLastError = CHIP_ERROR_INCORRECT_STATE; - } - - if (mLastError != CHIP_NO_ERROR) - { - stage = UnpairDeviceStage::kUnpairError; - } - - mStage = stage; - - switch (stage) - { - case kReadCurrentFabricIndex: { - ReadCurrentFabricIndex(); - break; - } - case kSendRemoveFabric: { - SendRemoveFabricIndex(mFabricIndex); - break; - } - case kUnpairError: - case kUnpairCleanUp: - default: { - FinishUnpairDevice(mLastError); - break; - } - } -} - -void DeviceUnpair::ReadCurrentFabricIndex() -{ - using TypeInfo = chip::app::Clusters::OperationalCredentials::Attributes::CurrentFabricIndex::TypeInfo; - OperationalCredentialsCluster cluster(*mProxy->GetExchangeManager(), mProxy->GetSecureSession().Value(), 0); - - CHIP_ERROR err = cluster.ReadAttribute(this, OnSuccessCurrentFabricIndex, OnReadAttributeFailure); - - if (err != CHIP_NO_ERROR) - { - SetLastError(err); - PerformDeviceUnpairStep(UnpairDeviceStage::kUnpairError); - return; - } - - return; -} - -void DeviceUnpair::SendRemoveFabricIndex(FabricIndex fabricIndex) -{ - if (fabricIndex == kUndefinedFabricIndex) - { - SetLastError(CHIP_ERROR_INVALID_FABRIC_INDEX); - PerformDeviceUnpairStep(UnpairDeviceStage::kUnpairError); - return; - } - ChipLogProgress(Controller, "SendRemoveFabricIndex : %u", fabricIndex); - - OperationalCredentials::Commands::RemoveFabric::Type request; - request.fabricIndex = fabricIndex; - - OperationalCredentialsCluster cluster(*mProxy->GetExchangeManager(), mProxy->GetSecureSession().Value(), 0); - - CHIP_ERROR err = cluster.InvokeCommand(request, this, OnRemoveFabric, OnCommandFailure); - if (err != CHIP_NO_ERROR) - { - SetLastError(err); - PerformDeviceUnpairStep(UnpairDeviceStage::kUnpairError); - return; - } -} - -void DeviceUnpair::FinishUnpairDevice(CHIP_ERROR err) -{ - mProxy = nullptr; - mOperationalDeviceProxy = nullptr; - - if (mCallback != nullptr) - { - mCallback->OnDeviceUnpair(mRemoteDeviceId, err); - } -} - -void DeviceUnpair::GenerateOperationalDeviceProxy(Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle) -{ - auto proxy = Platform::MakeShared(&exchangeMgr, sessionHandle); - mOperationalDeviceProxy = std::move(proxy); - RegisterDeviceProxy(mOperationalDeviceProxy.get()); -} - -void DeviceUnpair::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle) -{ - DeviceUnpair * deviceUnpair = static_cast(context); - VerifyOrReturn(deviceUnpair != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); - - deviceUnpair->GenerateOperationalDeviceProxy(exchangeMgr, sessionHandle); - deviceUnpair->PerformDeviceUnpairStep(UnpairDeviceStage::kReadCurrentFabricIndex); -} - -void DeviceUnpair::OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR err) -{ - ChipLogProgress(Controller, "OnDeviceConnectionFailureFn %s", err.AsString()); - - DeviceUnpair * deviceUnpair = static_cast(context); - VerifyOrReturn(deviceUnpair != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); - - deviceUnpair->SetLastError(err); - deviceUnpair->PerformDeviceUnpairStep(UnpairDeviceStage::kUnpairError); -} - -void DeviceUnpair::OnSuccessCurrentFabricIndex(void * context, uint8_t fabricIndex) -{ - DeviceUnpair * deviceUnpair = static_cast(context); - VerifyOrReturn(deviceUnpair != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); - deviceUnpair->mFabricIndex = fabricIndex; - - deviceUnpair->PerformDeviceUnpairStep(UnpairDeviceStage::kSendRemoveFabric); -} - -void DeviceUnpair::OnReadAttributeFailure(void * context, CHIP_ERROR err) -{ - ChipLogProgress(Controller, "OnCommandFailure %s", err.AsString()); - - DeviceUnpair * deviceUnpair = static_cast(context); - VerifyOrReturn(deviceUnpair != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); - - deviceUnpair->SetLastError(err); - deviceUnpair->PerformDeviceUnpairStep(UnpairDeviceStage::kUnpairError); -} - -void DeviceUnpair::OnRemoveFabric(void * context, const OperationalCredentials::Commands::NOCResponse::DecodableType & data) -{ - DeviceUnpair * deviceUnpair = static_cast(context); - VerifyOrReturn(deviceUnpair != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); - - deviceUnpair->PerformDeviceUnpairStep(UnpairDeviceStage::kUnpairCleanUp); -} - -void DeviceUnpair::OnCommandFailure(void * context, CHIP_ERROR err) -{ - ChipLogProgress(Controller, "OnCommandFailure %s", err.AsString()); - - DeviceUnpair * deviceUnpair = static_cast(context); - VerifyOrReturn(deviceUnpair != nullptr, ChipLogProgress(Controller, "Device connected callback with null context. Ignoring")); - - deviceUnpair->SetLastError(err); - deviceUnpair->PerformDeviceUnpairStep(UnpairDeviceStage::kUnpairError); -} -} // namespace Controller -} // namespace chip diff --git a/src/controller/DeviceUnpair.h b/src/controller/DeviceUnpair.h deleted file mode 100644 index 38667626cb792a..00000000000000 --- a/src/controller/DeviceUnpair.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * - * Copyright (c) 2021 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 -#include - -namespace chip { -namespace Controller { - -enum UnpairDeviceStage : uint8_t -{ - kUnpairError, - kReadCurrentFabricIndex, - kSendRemoveFabric, - kUnpairCleanUp, -}; - -class DLL_EXPORT DeviceUnpair -{ -public: - class Callback - { - public: - virtual ~Callback(){}; - virtual void OnDeviceUnpair(NodeId remoteDeviceId, CHIP_ERROR err){}; - }; - - DeviceUnpair(); - ~DeviceUnpair() {} - - void RegisterCallback(Callback * callback); - void UnpairDevice(DeviceProxy * proxy, NodeId remoteDeviceId); - -private: - CHIP_ERROR mLastError = CHIP_NO_ERROR; - Callback * mCallback = nullptr; - - chip::Callback::Callback mOnDeviceConnectedCallback; - chip::Callback::Callback mOnDeviceConnectionFailureCallback; - - DeviceProxy * mProxy = nullptr; - Platform::SharedPtr mOperationalDeviceProxy; - NodeId mRemoteDeviceId; - FabricIndex mFabricIndex = kUndefinedFabricIndex; - UnpairDeviceStage mStage = UnpairDeviceStage::kUnpairError; - - void RegisterDeviceProxy(DeviceProxy * proxy) { mProxy = proxy; } - void SetLastError(CHIP_ERROR err) { mLastError = err; } - - void GenerateOperationalDeviceProxy(Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle); - - void PerformDeviceUnpairStep(UnpairDeviceStage stage); - - void ReadCurrentFabricIndex(); - void SendRemoveFabricIndex(FabricIndex fabricIndex); - void FinishUnpairDevice(CHIP_ERROR err); - - static void OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle); - static void OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error); - - static void OnSuccessCurrentFabricIndex(void * context, uint8_t fabricIndex); - static void OnReadAttributeFailure(void * context, CHIP_ERROR error); - - static void OnRemoveFabric(void * context, - const chip::app::Clusters::OperationalCredentials::Commands::NOCResponse::DecodableType & data); - - static void OnCommandFailure(void * context, CHIP_ERROR error); - -public: - chip::Callback::Callback & GetConnectedCallback() { return mOnDeviceConnectedCallback; } - chip::Callback::Callback & GetConnectionFailureCallback() - { - return mOnDeviceConnectionFailureCallback; - } -}; - -} // namespace Controller -} // namespace chip diff --git a/src/controller/java/AndroidCurrentFabricRemover.cpp b/src/controller/java/AndroidCurrentFabricRemover.cpp new file mode 100644 index 00000000000000..1ba6a67f1121cc --- /dev/null +++ b/src/controller/java/AndroidCurrentFabricRemover.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022 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. + */ + +#include "AndroidCurrentFabricRemover.h" + +#include +#include + +namespace chip { +namespace Controller { + +AndroidCurrentFabricRemover::AndroidCurrentFabricRemover(DeviceCommissioner * commissioner, jobject jCallbackObject) : + CurrentFabricRemover(commissioner), mOnRemoveCurrentFabricCallback(OnRemoveCurrentFabric, this) +{ + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + mJavaCallback = env->NewGlobalRef(jCallbackObject); + + jclass callbackClass = env->GetObjectClass(jCallbackObject); + + mOnSuccessMethod = env->GetMethodID(callbackClass, "onSuccess", "(J)V"); + if (mOnSuccessMethod == nullptr) + { + ChipLogError(Controller, "Failed to access callback 'onSuccess' method"); + env->ExceptionClear(); + } + + mOnErrorMethod = env->GetMethodID(callbackClass, "onError", "(IJ)V"); + if (mOnErrorMethod == nullptr) + { + ChipLogError(Controller, "Failed to access callback 'onError' method"); + env->ExceptionClear(); + } +} + +AndroidCurrentFabricRemover::~AndroidCurrentFabricRemover() +{ + ChipLogError(Controller, "Delete AndroidCurrentFabricRemover"); + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + env->DeleteGlobalRef(mJavaCallback); +} + +CHIP_ERROR AndroidCurrentFabricRemover::RemoveCurrentFabric(DeviceCommissioner * controller, NodeId remoteDeviceId, + jobject jcallback) +{ + // Not using Platform::New because we want to keep our constructor private. + auto * remover = new AndroidCurrentFabricRemover(controller, jcallback); + if (remover == nullptr) + { + return CHIP_ERROR_NO_MEMORY; + } + + CHIP_ERROR err = remover->CurrentFabricRemover::CurrentFabricRemove(remoteDeviceId, &remover->mOnRemoveCurrentFabricCallback); + if (err != CHIP_NO_ERROR) + { + delete remover; + } + // Else will clean up when the callback is called. + return err; +} + +void AndroidCurrentFabricRemover::OnRemoveCurrentFabric(void * context, NodeId remoteDeviceId, CHIP_ERROR err) +{ + auto * self = static_cast(context); + + if (self->mJavaCallback != nullptr) + { + JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); + if (err == CHIP_NO_ERROR) + { + if (self->mOnSuccessMethod != nullptr) + { + env->CallVoidMethod(self->mJavaCallback, self->mOnSuccessMethod, static_cast(remoteDeviceId)); + } + } + else + { + if (self->mOnErrorMethod != nullptr) + { + env->CallVoidMethod(self->mJavaCallback, self->mOnErrorMethod, static_cast(err.GetValue()), + static_cast(remoteDeviceId)); + } + } + } + + delete self; +} + +} // namespace Controller +} // namespace chip diff --git a/src/controller/java/AndroidCurrentFabricRemover.h b/src/controller/java/AndroidCurrentFabricRemover.h new file mode 100644 index 00000000000000..b890c9f51a53b6 --- /dev/null +++ b/src/controller/java/AndroidCurrentFabricRemover.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 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 +#include + +namespace chip { +namespace Controller { + +/** + * A helper class that can be used by consumers that don't care about the callback from the + * remove Fabric process and just want automatic cleanup of the CurrentFabricRemover when done + * with it. + */ +class AndroidCurrentFabricRemover : private CurrentFabricRemover +{ +public: + static CHIP_ERROR RemoveCurrentFabric(DeviceCommissioner * controller, NodeId remoteDeviceId, jobject jcallback); + +private: + AndroidCurrentFabricRemover(DeviceCommissioner * commissioner, jobject javaCallbackObject); + ~AndroidCurrentFabricRemover(); + + static void OnRemoveCurrentFabric(void * context, NodeId remoteDeviceId, CHIP_ERROR status); + chip::Callback::Callback mOnRemoveCurrentFabricCallback; + + jobject mJavaCallback; + jmethodID mOnSuccessMethod = nullptr; + jmethodID mOnErrorMethod = nullptr; +}; + +} // Namespace Controller +} // namespace chip diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index d7c68afd518800..979f69122bf3ab 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -32,6 +32,8 @@ shared_library("jni") { "AndroidClusterExceptions.h", "AndroidCommissioningWindowOpener.cpp", "AndroidCommissioningWindowOpener.h", + "AndroidCurrentFabricRemover.cpp", + "AndroidCurrentFabricRemover.h", "AndroidDeviceControllerWrapper.cpp", "AndroidDeviceControllerWrapper.h", "AndroidOperationalCredentialsIssuer.cpp", @@ -120,6 +122,7 @@ android_library("java") { "src/chip/devicecontroller/ReportEventCallbackJni.java", "src/chip/devicecontroller/ResubscriptionAttemptCallback.java", "src/chip/devicecontroller/SubscriptionEstablishedCallback.java", + "src/chip/devicecontroller/UnpairDeviceCallback.java", "src/chip/devicecontroller/model/AttributeState.java", "src/chip/devicecontroller/model/ChipAttributePath.java", "src/chip/devicecontroller/model/ChipEventPath.java", diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index bed3ffda5f0c42..a6d1f2717c6128 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -23,6 +23,7 @@ */ #include "AndroidCallbacks.h" #include "AndroidCommissioningWindowOpener.h" +#include "AndroidCurrentFabricRemover.h" #include "AndroidDeviceControllerWrapper.h" #include #include @@ -689,6 +690,23 @@ JNI_METHOD(void, unpairDevice)(JNIEnv * env, jobject self, jlong handle, jlong d } } +JNI_METHOD(void, unpairDeviceCallback)(JNIEnv * env, jobject self, jlong handle, jlong deviceId, jobject callback) +{ + chip::DeviceLayer::StackLock lock; + CHIP_ERROR err = CHIP_NO_ERROR; + AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle); + + ChipLogProgress(Controller, "unpairDeviceCallback() called with device ID and callback object"); + + err = AndroidCurrentFabricRemover::RemoveCurrentFabric(wrapper->Controller(), static_cast(deviceId), callback); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Failed to unpair the device."); + JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err); + } +} + JNI_METHOD(void, stopDevicePairing)(JNIEnv * env, jobject self, jlong handle, jlong deviceId) { chip::DeviceLayer::StackLock lock; diff --git a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java index 7004fac4e177a9..bc1b66838efcf1 100644 --- a/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java +++ b/src/controller/java/src/chip/devicecontroller/ChipDeviceController.java @@ -238,6 +238,10 @@ public void unpairDevice(long deviceId) { unpairDevice(deviceControllerPtr, deviceId); } + public void unpairDeviceCallback(long deviceId, UnpairDeviceCallback callback) { + unpairDeviceCallback(deviceControllerPtr, deviceId, callback); + } + /** * Returns a pointer to a device currently being commissioned. This should be used before the * device is operationally available. @@ -643,6 +647,9 @@ private native void commissionDevice( private native void unpairDevice(long deviceControllerPtr, long deviceId); + private native void unpairDeviceCallback( + long deviceControllerPtr, long deviceId, UnpairDeviceCallback callback); + private native long getDeviceBeingCommissionedPointer(long deviceControllerPtr, long nodeId); private native void getConnectedDevicePointer( diff --git a/src/controller/java/src/chip/devicecontroller/UnpairDeviceCallback.java b/src/controller/java/src/chip/devicecontroller/UnpairDeviceCallback.java new file mode 100644 index 00000000000000..7e533b64338841 --- /dev/null +++ b/src/controller/java/src/chip/devicecontroller/UnpairDeviceCallback.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 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; + +public interface UnpairDeviceCallback { + public void onError(int status, long remoteDeviceId); + + public void onSuccess(long remoteDeviceId); +}