blob: 9f5d823f18ac18af7f73a904d51256c83781ef22 [file] [log] [blame]
/*
*
* Copyright (c) 2025 Project CHIP Authors
*
* 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.
*/
/**
* @file
* Provides an implementation of the NFCCommissioningManager singleton object
* for Android platforms.
*/
#include <platform/internal/CHIPDeviceLayerInternal.h>
#include <lib/support/CHIPJNIError.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/JniReferences.h>
#include <lib/support/SafeInt.h>
#include <platform/internal/NFCCommissioningManager.h>
#if CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING
using namespace chip;
using namespace ::nl;
using namespace ::chip::Nfc;
namespace chip {
namespace DeviceLayer {
namespace Internal {
namespace {} // namespace
NFCCommissioningManagerImpl NFCCommissioningManagerImpl::sInstance;
void NFCCommissioningManagerImpl::InitializeWithObject(jobject manager)
{
ChipLogProgress(DeviceLayer, "NFCCommissioningManagerImpl::InitializeWithObject()");
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturn(env != nullptr, ChipLogError(DeviceLayer, "Failed to GetEnvForCurrentThread for NFCCommissioningManager"));
// Initialize the JniGlobalReference with the manager object
VerifyOrReturn(mNFCCommissioningManagerObject.Init(manager) == CHIP_NO_ERROR,
ChipLogError(DeviceLayer, "Failed to init mNFCCommissioningManagerObject"));
jclass NFCCommissioningManagerClass = env->GetObjectClass(manager);
VerifyOrReturn(NFCCommissioningManagerClass != nullptr,
ChipLogError(DeviceLayer, "Failed to get NFCCommissioningManagerClass Java class"));
mInitMethod = env->GetMethodID(NFCCommissioningManagerClass, "init", "()I");
if (mInitMethod == nullptr)
{
ChipLogError(DeviceLayer, "Failed to access NFCCommissioningManager 'init' method");
env->ExceptionClear();
}
mShutdownMethod = env->GetMethodID(NFCCommissioningManagerClass, "shutdown", "()V");
if (mShutdownMethod == nullptr)
{
ChipLogError(DeviceLayer, "Failed to access NFCCommissioningManager 'shutdown' method");
env->ExceptionClear();
}
mSendToNfcTagCallback = env->GetMethodID(NFCCommissioningManagerClass, "sendToNfcTag", "([B)V");
if (mSendToNfcTagCallback == nullptr)
{
ChipLogError(Controller, "Failed to access callback 'sendToNfcTag' method");
env->ExceptionClear();
}
}
// ===== start impl of NFCCommissioningManager internal interface, ref NFCCommissioningManager.h
CHIP_ERROR NFCCommissioningManagerImpl::_Init()
{
ChipLogProgress(DeviceLayer, "NFCCommissioningManagerImpl::_Init()");
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturnError(env != nullptr, CHIP_ERROR_INTERNAL);
VerifyOrReturnError(mNFCCommissioningManagerObject.HasValidObjectRef(), CHIP_ERROR_INTERNAL);
VerifyOrReturnError(mInitMethod != nullptr, CHIP_ERROR_INTERNAL);
env->CallIntMethod(mNFCCommissioningManagerObject.ObjectRef(), mInitMethod);
if (env->ExceptionCheck())
{
env->ExceptionClear();
ChipLogError(DeviceLayer, "Failed to call init() Java method");
return CHIP_ERROR_INTERNAL;
}
return CHIP_NO_ERROR;
}
void NFCCommissioningManagerImpl::_Shutdown()
{
ChipLogProgress(DeviceLayer, "NFCCommissioningManagerImpl::_Shutdown()");
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturn(env != nullptr);
VerifyOrReturn(mNFCCommissioningManagerObject.HasValidObjectRef());
VerifyOrReturn(mShutdownMethod != nullptr);
env->CallVoidMethod(mNFCCommissioningManagerObject.ObjectRef(), mShutdownMethod);
if (env->ExceptionCheck())
{
env->ExceptionClear();
ChipLogError(DeviceLayer, "Failed to call shutdown() Java method");
return;
}
}
// ===== start implement virtual methods on NfcApplicationDelegate.
void NFCCommissioningManagerImpl::SetNFCBase(Transport::NFCBase * nfcBase)
{
mNFCBase = nfcBase;
}
bool NFCCommissioningManagerImpl::CanSendToPeer(const Transport::PeerAddress & address)
{
// on Android platform, a single NFC Tag can be used at a time so no need to use
// NFCshortId to determine to what NFC Tag the command should be sent
return true;
}
CHIP_ERROR NFCCommissioningManagerImpl::SendToNfcTag(const Transport::PeerAddress & address, System::PacketBufferHandle && msgBuf)
{
const uint8_t * buffer = msgBuf->Start();
uint32_t len = static_cast<uint32_t>(msgBuf->DataLength());
JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
VerifyOrReturnError(env != nullptr, CHIP_ERROR_INTERNAL);
// Create a JniLocalReferenceScope to manage local references
chip::JniLocalReferenceScope localRefScope(env);
jbyteArray jbArray = env->NewByteArray(static_cast<int>(len));
if (jbArray == nullptr)
{
ChipLogError(DeviceLayer, "Failed to create new Java byte array");
return CHIP_ERROR_NO_MEMORY;
}
env->SetByteArrayRegion(jbArray, 0, static_cast<int>(len), reinterpret_cast<const jbyte *>(buffer));
if (env->ExceptionCheck())
{
env->ExceptionClear();
ChipLogError(DeviceLayer, "Failed to set byte array region");
return CHIP_ERROR_INTERNAL;
}
VerifyOrReturnError(mNFCCommissioningManagerObject.HasValidObjectRef(), CHIP_ERROR_INTERNAL);
VerifyOrReturnError(mSendToNfcTagCallback != nullptr, CHIP_ERROR_INTERNAL);
env->CallVoidMethod(mNFCCommissioningManagerObject.ObjectRef(), mSendToNfcTagCallback, jbArray);
if (env->ExceptionCheck())
{
env->ExceptionClear();
ChipLogError(DeviceLayer, "Failed to call Java method sendToNfcTag");
return CHIP_ERROR_INTERNAL;
}
return CHIP_NO_ERROR;
}
CHIP_ERROR NFCCommissioningManagerImpl::OnNfcTagResponse(const Transport::PeerAddress & address,
System::PacketBufferHandle && buffer)
{
if (mNFCBase == NULL)
{
ChipLogError(DeviceLayer, "Error! mNFCBase is null!");
return CHIP_ERROR_INCORRECT_STATE;
}
mNFCBase->OnNfcTagResponse(address, std::move(buffer));
return CHIP_NO_ERROR;
}
CHIP_ERROR NFCCommissioningManagerImpl::OnNfcTagError(const Transport::PeerAddress & address)
{
if (mNFCBase == NULL)
{
ChipLogError(DeviceLayer, "Error! mNFCBase is null!");
return CHIP_ERROR_INCORRECT_STATE;
}
mNFCBase->OnNfcTagError(address);
return CHIP_NO_ERROR;
}
} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
#endif // CHIP_DEVICE_CONFIG_ENABLE_NFC_BASED_COMMISSIONING