| /* |
| * |
| * Copyright (c) 2021 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. |
| */ |
| #include "ConversionUtils.h" |
| |
| #include <controller/CHIPCluster.h> |
| #include <jni.h> |
| #include <lib/core/CHIPError.h> |
| #include <lib/support/JniReferences.h> |
| #include <lib/support/JniTypeWrappers.h> |
| #include <string.h> |
| #include <system/SystemClock.h> |
| |
| CHIP_ERROR convertJAppParametersToCppAppParams(jobject appParameters, AppParams & outAppParams) |
| { |
| ChipLogProgress(AppServer, "convertJAppParametersToCppAppParams called"); |
| JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); |
| VerifyOrReturnError(appParameters != nullptr, CHIP_ERROR_INVALID_ARGUMENT); |
| |
| jclass jAppParametersClass; |
| ReturnErrorOnFailure( |
| chip::JniReferences::GetInstance().GetLocalClassRef(env, "com/chip/casting/AppParameters", jAppParametersClass)); |
| |
| jmethodID getRotatingDeviceIdUniqueIdMethod = env->GetMethodID(jAppParametersClass, "getRotatingDeviceIdUniqueId", "()[B"); |
| if (getRotatingDeviceIdUniqueIdMethod == nullptr) |
| { |
| ChipLogError(Zcl, "Failed to access AppParameters 'getRotatingDeviceIdUniqueId' method"); |
| env->ExceptionClear(); |
| } |
| |
| jobject jRotatingDeviceIdUniqueId = (jobject) env->CallObjectMethod(appParameters, getRotatingDeviceIdUniqueIdMethod); |
| if (env->ExceptionCheck()) |
| { |
| ChipLogError(Zcl, "Java exception in AppParameters::getRotatingDeviceIdUniqueId"); |
| env->ExceptionDescribe(); |
| env->ExceptionClear(); |
| return CHIP_ERROR_INCORRECT_STATE; |
| } |
| |
| if (jRotatingDeviceIdUniqueId != nullptr) |
| { |
| chip::JniByteArray * jniRotatingDeviceIdUniqueIdByteArray = |
| new chip::JniByteArray(env, static_cast<jbyteArray>(jRotatingDeviceIdUniqueId)); |
| outAppParams.SetRotatingDeviceIdUniqueId(MakeOptional(jniRotatingDeviceIdUniqueIdByteArray->byteSpan())); |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR convertJContentAppToTargetEndpointInfo(jobject contentApp, TargetEndpointInfo & outTargetEndpointInfo) |
| { |
| ChipLogProgress(AppServer, "convertJContentAppToTargetEndpointInfo called"); |
| VerifyOrReturnError(contentApp != nullptr, CHIP_ERROR_INVALID_ARGUMENT); |
| JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); |
| |
| jclass jContentAppClass; |
| ReturnErrorOnFailure(chip::JniReferences::GetInstance().GetLocalClassRef(env, "com/chip/casting/ContentApp", jContentAppClass)); |
| |
| jfieldID jEndpointIdField = env->GetFieldID(jContentAppClass, "endpointId", "S"); |
| jshort jEndpointId = env->GetShortField(contentApp, jEndpointIdField); |
| outTargetEndpointInfo.Initialize(static_cast<chip::EndpointId>(jEndpointId)); |
| |
| jfieldID jclusterIdsField = env->GetFieldID(jContentAppClass, "clusterIds", "Ljava/util/List;"); |
| jobject jClusterIds = env->GetObjectField(contentApp, jclusterIdsField); |
| if (jClusterIds == nullptr) |
| { |
| return CHIP_NO_ERROR; |
| } |
| |
| jobject jIterator = env->CallObjectMethod( |
| jClusterIds, env->GetMethodID(env->GetObjectClass(jClusterIds), "iterator", "()Ljava/util/Iterator;")); |
| jmethodID jNextMid = env->GetMethodID(env->GetObjectClass(jIterator), "next", "()Ljava/lang/Object;"); |
| jmethodID jHasNextMid = env->GetMethodID(env->GetObjectClass(jIterator), "hasNext", "()Z"); |
| |
| while (env->CallBooleanMethod(jIterator, jHasNextMid)) |
| { |
| jobject jClusterId = env->CallObjectMethod(jIterator, jNextMid); |
| jclass jIntegerClass = env->FindClass("java/lang/Integer"); |
| jmethodID jIntValueMid = env->GetMethodID(jIntegerClass, "intValue", "()I"); |
| outTargetEndpointInfo.AddCluster(static_cast<chip::ClusterId>(env->CallIntMethod(jClusterId, jIntValueMid))); |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR convertTargetEndpointInfoToJContentApp(TargetEndpointInfo * targetEndpointInfo, jobject & outContentApp) |
| { |
| ChipLogProgress(AppServer, "convertTargetEndpointInfoToJContentApp called"); |
| if (targetEndpointInfo != nullptr && targetEndpointInfo->IsInitialized()) |
| { |
| JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); |
| |
| jclass jContentAppClass; |
| ReturnErrorOnFailure( |
| chip::JniReferences::GetInstance().GetLocalClassRef(env, "com/chip/casting/ContentApp", jContentAppClass)); |
| jmethodID jContentAppConstructor = env->GetMethodID(jContentAppClass, "<init>", "(SLjava/util/List;)V"); |
| chip::ClusterId * clusters = targetEndpointInfo->GetClusters(); |
| jobject jClustersArrayList = nullptr; |
| if (clusters != nullptr) |
| { |
| chip::JniReferences::GetInstance().CreateArrayList(jClustersArrayList); |
| for (size_t i = 0; i < kMaxNumberOfClustersPerEndpoint && clusters[i] != chip::kInvalidClusterId; i++) |
| { |
| jobject jCluster = nullptr; |
| jint jniclusterId = static_cast<jint>(clusters[i]); |
| chip::JniReferences::GetInstance().CreateBoxedObject<jint>("java/lang/Integer", "(I)V", jniclusterId, jCluster); |
| chip::JniReferences::GetInstance().AddToList(jClustersArrayList, jCluster); |
| } |
| } |
| outContentApp = |
| env->NewObject(jContentAppClass, jContentAppConstructor, targetEndpointInfo->GetEndpointId(), jClustersArrayList); |
| } |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR convertJVideoPlayerToTargetVideoPlayerInfo(jobject videoPlayer, TargetVideoPlayerInfo & outTargetVideoPlayerInfo) |
| { |
| ChipLogProgress(AppServer, "convertJVideoPlayerToTargetVideoPlayerInfo called"); |
| VerifyOrReturnError(videoPlayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); |
| JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); |
| |
| jclass jVideoPlayerClass; |
| ReturnErrorOnFailure( |
| chip::JniReferences::GetInstance().GetLocalClassRef(env, "com/chip/casting/VideoPlayer", jVideoPlayerClass)); |
| |
| jfieldID jNodeIdField = env->GetFieldID(jVideoPlayerClass, "nodeId", "J"); |
| chip::NodeId nodeId = static_cast<chip::NodeId>(env->GetLongField(videoPlayer, jNodeIdField)); |
| |
| jfieldID jFabricIndexField = env->GetFieldID(jVideoPlayerClass, "fabricIndex", "B"); |
| chip::FabricIndex fabricIndex = static_cast<chip::FabricIndex>(env->GetByteField(videoPlayer, jFabricIndexField)); |
| |
| jfieldID jVendorIdField = env->GetFieldID(jVideoPlayerClass, "vendorId", "I"); |
| uint16_t vendorId = static_cast<uint16_t>(env->GetIntField(videoPlayer, jVendorIdField)); |
| |
| jfieldID jProductIdField = env->GetFieldID(jVideoPlayerClass, "productId", "I"); |
| uint16_t productId = static_cast<uint16_t>(env->GetIntField(videoPlayer, jProductIdField)); |
| |
| jfieldID jDeviceType = env->GetFieldID(jVideoPlayerClass, "deviceType", "I"); |
| uint16_t deviceType = static_cast<uint16_t>(env->GetIntField(videoPlayer, jDeviceType)); |
| |
| jfieldID getDeviceNameField = env->GetFieldID(jVideoPlayerClass, "deviceName", "Ljava/lang/String;"); |
| jstring jDeviceName = static_cast<jstring>(env->GetObjectField(videoPlayer, getDeviceNameField)); |
| const char * deviceName = env->GetStringUTFChars(jDeviceName, 0); |
| |
| jfieldID getHostNameField = env->GetFieldID(jVideoPlayerClass, "hostName", "Ljava/lang/String;"); |
| jstring jHostName = static_cast<jstring>(env->GetObjectField(videoPlayer, getHostNameField)); |
| const char * hostName = env->GetStringUTFChars(jHostName, 0); |
| |
| jfieldID jPort = env->GetFieldID(jVideoPlayerClass, "port", "I"); |
| uint16_t port = static_cast<uint16_t>(env->GetIntField(videoPlayer, jPort)); |
| |
| jfieldID getInstanceNameField = env->GetFieldID(jVideoPlayerClass, "instanceName", "Ljava/lang/String;"); |
| jstring jInstanceName = static_cast<jstring>(env->GetObjectField(videoPlayer, getInstanceNameField)); |
| const char * instanceName = {}; |
| if (jInstanceName != nullptr) |
| { |
| instanceName = env->GetStringUTFChars(jInstanceName, 0); |
| } |
| |
| jfieldID jLastDiscoveredMs = env->GetFieldID(jVideoPlayerClass, "lastDiscoveredMs", "J"); |
| long lastDiscoveredMs = static_cast<long>(env->GetLongField(videoPlayer, jLastDiscoveredMs)); |
| |
| jfieldID getMACAddressField = env->GetFieldID(jVideoPlayerClass, "MACAddress", "Ljava/lang/String;"); |
| jstring jMACAddress = static_cast<jstring>(env->GetObjectField(videoPlayer, getMACAddressField)); |
| const char * MACAddress = jMACAddress == nullptr ? nullptr : env->GetStringUTFChars(jMACAddress, 0); |
| |
| jfieldID jIsAsleep = env->GetFieldID(jVideoPlayerClass, "isAsleep", "Z"); |
| bool isAsleep = static_cast<bool>(env->GetBooleanField(videoPlayer, jIsAsleep)); |
| |
| outTargetVideoPlayerInfo.Initialize(nodeId, fabricIndex, nullptr, nullptr, vendorId, productId, deviceType, deviceName, |
| hostName, 0, nullptr, port, instanceName, chip::System::Clock::Timestamp(lastDiscoveredMs)); |
| |
| if (MACAddress != nullptr) |
| { |
| chip::CharSpan MACAddressSpan(MACAddress, 2 * 2 * chip::DeviceLayer::ConfigurationManager::kPrimaryMACAddressLength); |
| outTargetVideoPlayerInfo.SetMACAddress(MACAddressSpan); |
| } |
| |
| outTargetVideoPlayerInfo.SetIsAsleep(isAsleep); |
| |
| jfieldID jContentAppsField = env->GetFieldID(jVideoPlayerClass, "contentApps", "Ljava/util/List;"); |
| jobject jContentApps = env->GetObjectField(videoPlayer, jContentAppsField); |
| if (jContentApps == nullptr) |
| { |
| return CHIP_NO_ERROR; |
| } |
| |
| jobject jIterator = env->CallObjectMethod( |
| jContentApps, env->GetMethodID(env->GetObjectClass(jContentApps), "iterator", "()Ljava/util/Iterator;")); |
| jmethodID jNextMid = env->GetMethodID(env->GetObjectClass(jIterator), "next", "()Ljava/lang/Object;"); |
| jmethodID jHasNextMid = env->GetMethodID(env->GetObjectClass(jIterator), "hasNext", "()Z"); |
| |
| while (env->CallBooleanMethod(jIterator, jHasNextMid)) |
| { |
| jobject jContentApp = env->CallObjectMethod(jIterator, jNextMid); |
| |
| jclass jContentAppClass; |
| ReturnErrorOnFailure( |
| chip::JniReferences::GetInstance().GetLocalClassRef(env, "com/chip/casting/ContentApp", jContentAppClass)); |
| jfieldID jEndpointIdField = env->GetFieldID(jContentAppClass, "endpointId", "S"); |
| chip::EndpointId endpointId = static_cast<chip::EndpointId>(env->GetShortField(jContentApp, jEndpointIdField)); |
| TargetEndpointInfo * endpoint = outTargetVideoPlayerInfo.GetOrAddEndpoint(endpointId); |
| |
| ReturnErrorOnFailure(convertJContentAppToTargetEndpointInfo(jContentApp, *endpoint)); |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR convertTargetVideoPlayerInfoToJVideoPlayer(TargetVideoPlayerInfo * targetVideoPlayerInfo, jobject & outVideoPlayer) |
| { |
| ChipLogProgress(AppServer, "convertTargetVideoPlayerInfoToJVideoPlayer called"); |
| if (targetVideoPlayerInfo != nullptr && targetVideoPlayerInfo->IsInitialized()) |
| { |
| JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); |
| |
| jclass jVideoPlayerClass; |
| ReturnErrorOnFailure( |
| chip::JniReferences::GetInstance().GetLocalClassRef(env, "com/chip/casting/VideoPlayer", jVideoPlayerClass)); |
| jmethodID jVideoPlayerConstructor = env->GetMethodID(jVideoPlayerClass, "<init>", |
| "(JBLjava/lang/String;IIILjava/util/List;ILjava/util/List;Ljava/lang/" |
| "String;Ljava/lang/String;IJLjava/lang/String;ZZ)V"); |
| |
| jobject jContentAppList = nullptr; |
| TargetEndpointInfo * endpoints = targetVideoPlayerInfo->GetEndpoints(); |
| if (endpoints != nullptr) |
| { |
| chip::JniReferences::GetInstance().CreateArrayList(jContentAppList); |
| for (size_t i = 0; i < kMaxNumberOfEndpoints && endpoints[i].IsInitialized(); i++) |
| { |
| jobject contentApp = nullptr; |
| ReturnErrorOnFailure(convertTargetEndpointInfoToJContentApp(&endpoints[i], contentApp)); |
| chip::JniReferences::GetInstance().AddToList(jContentAppList, contentApp); |
| } |
| } |
| |
| jstring deviceName = |
| targetVideoPlayerInfo->GetDeviceName() == nullptr ? nullptr : env->NewStringUTF(targetVideoPlayerInfo->GetDeviceName()); |
| |
| jstring hostName = |
| targetVideoPlayerInfo->GetHostName() == nullptr ? nullptr : env->NewStringUTF(targetVideoPlayerInfo->GetHostName()); |
| |
| jstring instanceName = targetVideoPlayerInfo->GetInstanceName() == nullptr |
| ? nullptr |
| : env->NewStringUTF(targetVideoPlayerInfo->GetInstanceName()); |
| |
| jstring MACAddress = nullptr; |
| if (targetVideoPlayerInfo->GetMACAddress() != nullptr && targetVideoPlayerInfo->GetMACAddress()->data() != nullptr) |
| { |
| char MACAddressWithNil[2 * chip::DeviceLayer::ConfigurationManager::kPrimaryMACAddressLength + 1]; |
| memcpy(MACAddressWithNil, targetVideoPlayerInfo->GetMACAddress()->data(), |
| targetVideoPlayerInfo->GetMACAddress()->size()); |
| MACAddressWithNil[targetVideoPlayerInfo->GetMACAddress()->size()] = '\0'; |
| MACAddress = env->NewStringUTF(MACAddressWithNil); |
| } |
| |
| jobject jIPAddressList = nullptr; |
| const chip::Inet::IPAddress * ipAddresses = targetVideoPlayerInfo->GetIpAddresses(); |
| if (ipAddresses != nullptr) |
| { |
| chip::JniReferences::GetInstance().CreateArrayList(jIPAddressList); |
| for (size_t i = 0; i < targetVideoPlayerInfo->GetNumIPs() && i < chip::Dnssd::CommonResolutionData::kMaxIPAddresses; |
| i++) |
| { |
| char addrCString[chip::Inet::IPAddress::kMaxStringLength]; |
| ipAddresses[i].ToString(addrCString, chip::Inet::IPAddress::kMaxStringLength); |
| jstring jIPAddressStr = env->NewStringUTF(addrCString); |
| |
| jclass jIPAddressClass; |
| ReturnErrorOnFailure( |
| chip::JniReferences::GetInstance().GetLocalClassRef(env, "java/net/InetAddress", jIPAddressClass)); |
| jmethodID jGetByNameMid = |
| env->GetStaticMethodID(jIPAddressClass, "getByName", "(Ljava/lang/String;)Ljava/net/InetAddress;"); |
| jobject jIPAddress = env->CallStaticObjectMethod(jIPAddressClass, jGetByNameMid, jIPAddressStr); |
| |
| chip::JniReferences::GetInstance().AddToList(jIPAddressList, jIPAddress); |
| } |
| } |
| |
| outVideoPlayer = env->NewObject( |
| jVideoPlayerClass, jVideoPlayerConstructor, targetVideoPlayerInfo->GetNodeId(), targetVideoPlayerInfo->GetFabricIndex(), |
| deviceName, targetVideoPlayerInfo->GetVendorId(), targetVideoPlayerInfo->GetProductId(), |
| targetVideoPlayerInfo->GetDeviceType(), jContentAppList, targetVideoPlayerInfo->GetNumIPs(), jIPAddressList, hostName, |
| instanceName, targetVideoPlayerInfo->GetPort(), targetVideoPlayerInfo->GetLastDiscovered().count(), MACAddress, |
| targetVideoPlayerInfo->IsAsleep(), targetVideoPlayerInfo->GetOperationalDeviceProxy() != nullptr); |
| } |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR convertJDiscoveredNodeDataToCppDiscoveredNodeData(jobject jDiscoveredNodeData, |
| chip::Dnssd::DiscoveredNodeData & outCppDiscoveredNodeData) |
| { |
| ChipLogProgress(AppServer, "convertJDiscoveredNodeDataToCppDiscoveredNodeData called"); |
| VerifyOrReturnError(jDiscoveredNodeData != nullptr, CHIP_ERROR_INVALID_ARGUMENT); |
| |
| JNIEnv * env = chip::JniReferences::GetInstance().GetEnvForCurrentThread(); |
| |
| jclass jDiscoveredNodeDataClass; |
| ReturnErrorOnFailure( |
| chip::JniReferences::GetInstance().GetLocalClassRef(env, "com/chip/casting/DiscoveredNodeData", jDiscoveredNodeDataClass)); |
| |
| jfieldID getHostNameField = env->GetFieldID(jDiscoveredNodeDataClass, "hostName", "Ljava/lang/String;"); |
| jstring jHostName = static_cast<jstring>(env->GetObjectField(jDiscoveredNodeData, getHostNameField)); |
| if (jHostName != nullptr) |
| { |
| chip::Platform::CopyString(outCppDiscoveredNodeData.resolutionData.hostName, chip::Dnssd::kHostNameMaxLength + 1, |
| env->GetStringUTFChars(jHostName, 0)); |
| } |
| |
| jfieldID getInstanceNameField = env->GetFieldID(jDiscoveredNodeDataClass, "instanceName", "Ljava/lang/String;"); |
| jstring jInstanceName = static_cast<jstring>(env->GetObjectField(jDiscoveredNodeData, getInstanceNameField)); |
| if (jInstanceName != nullptr) |
| { |
| chip::Platform::CopyString(outCppDiscoveredNodeData.nodeData.instanceName, |
| chip::Dnssd::Commission::kInstanceNameMaxLength + 1, env->GetStringUTFChars(jInstanceName, 0)); |
| } |
| |
| jfieldID jLongDiscriminatorField = env->GetFieldID(jDiscoveredNodeDataClass, "longDiscriminator", "J"); |
| outCppDiscoveredNodeData.nodeData.vendorId = |
| static_cast<uint16_t>(env->GetLongField(jDiscoveredNodeData, jLongDiscriminatorField)); |
| |
| jfieldID jVendorIdField = env->GetFieldID(jDiscoveredNodeDataClass, "vendorId", "J"); |
| outCppDiscoveredNodeData.nodeData.vendorId = static_cast<uint16_t>(env->GetLongField(jDiscoveredNodeData, jVendorIdField)); |
| |
| jfieldID jProductIdField = env->GetFieldID(jDiscoveredNodeDataClass, "productId", "J"); |
| outCppDiscoveredNodeData.nodeData.productId = static_cast<uint16_t>(env->GetLongField(jDiscoveredNodeData, jProductIdField)); |
| |
| jfieldID jCommissioningModeField = env->GetFieldID(jDiscoveredNodeDataClass, "commissioningMode", "B"); |
| outCppDiscoveredNodeData.nodeData.commissioningMode = |
| static_cast<uint8_t>(env->GetByteField(jDiscoveredNodeData, jCommissioningModeField)); |
| |
| jfieldID jDeviceTypeField = env->GetFieldID(jDiscoveredNodeDataClass, "deviceType", "J"); |
| outCppDiscoveredNodeData.nodeData.deviceType = static_cast<uint16_t>(env->GetLongField(jDiscoveredNodeData, jDeviceTypeField)); |
| |
| jfieldID getDeviceNameField = env->GetFieldID(jDiscoveredNodeDataClass, "deviceName", "Ljava/lang/String;"); |
| jstring jDeviceName = static_cast<jstring>(env->GetObjectField(jDiscoveredNodeData, getDeviceNameField)); |
| if (jDeviceName != nullptr) |
| { |
| chip::Platform::CopyString(outCppDiscoveredNodeData.nodeData.deviceName, chip::Dnssd::kMaxDeviceNameLen + 1, |
| env->GetStringUTFChars(jDeviceName, 0)); |
| } |
| |
| // TODO: map rotating ID |
| jfieldID jRotatingIdLenField = env->GetFieldID(jDiscoveredNodeDataClass, "rotatingIdLen", "I"); |
| outCppDiscoveredNodeData.nodeData.rotatingIdLen = |
| static_cast<size_t>(env->GetIntField(jDiscoveredNodeData, jRotatingIdLenField)); |
| |
| jfieldID jPairingHintField = env->GetFieldID(jDiscoveredNodeDataClass, "pairingHint", "S"); |
| outCppDiscoveredNodeData.nodeData.pairingHint = |
| static_cast<uint16_t>(env->GetShortField(jDiscoveredNodeData, jPairingHintField)); |
| |
| jfieldID getPairingInstructionField = env->GetFieldID(jDiscoveredNodeDataClass, "pairingInstruction", "Ljava/lang/String;"); |
| jstring jPairingInstruction = static_cast<jstring>(env->GetObjectField(jDiscoveredNodeData, getPairingInstructionField)); |
| if (jPairingInstruction != nullptr) |
| { |
| chip::Platform::CopyString(outCppDiscoveredNodeData.nodeData.pairingInstruction, chip::Dnssd::kMaxPairingInstructionLen + 1, |
| env->GetStringUTFChars(jPairingInstruction, 0)); |
| } |
| |
| jfieldID jPortField = env->GetFieldID(jDiscoveredNodeDataClass, "port", "I"); |
| outCppDiscoveredNodeData.resolutionData.port = static_cast<uint16_t>(env->GetIntField(jDiscoveredNodeData, jPortField)); |
| |
| jfieldID jNumIpsField = env->GetFieldID(jDiscoveredNodeDataClass, "numIPs", "I"); |
| outCppDiscoveredNodeData.resolutionData.numIPs = static_cast<size_t>(env->GetIntField(jDiscoveredNodeData, jNumIpsField)); |
| |
| jfieldID jIPAddressesField = env->GetFieldID(jDiscoveredNodeDataClass, "ipAddresses", "Ljava/util/List;"); |
| jobject jIPAddresses = env->GetObjectField(jDiscoveredNodeData, jIPAddressesField); |
| if (jIPAddresses == nullptr && outCppDiscoveredNodeData.resolutionData.numIPs > 0) |
| { |
| return CHIP_ERROR_INVALID_ARGUMENT; |
| } |
| |
| jobject jIterator = env->CallObjectMethod( |
| jIPAddresses, env->GetMethodID(env->GetObjectClass(jIPAddresses), "iterator", "()Ljava/util/Iterator;")); |
| jmethodID jNextMid = env->GetMethodID(env->GetObjectClass(jIterator), "next", "()Ljava/lang/Object;"); |
| jmethodID jHasNextMid = env->GetMethodID(env->GetObjectClass(jIterator), "hasNext", "()Z"); |
| |
| size_t ipAddressCount = 0; |
| while (env->CallBooleanMethod(jIterator, jHasNextMid)) |
| { |
| jobject jIPAddress = env->CallObjectMethod(jIterator, jNextMid); |
| jclass jIPAddressClass; |
| ReturnErrorOnFailure(chip::JniReferences::GetInstance().GetLocalClassRef(env, "java/net/InetAddress", jIPAddressClass)); |
| jmethodID jGetHostAddressMid = env->GetMethodID(jIPAddressClass, "getHostAddress", "()Ljava/lang/String;"); |
| jstring jIPAddressStr = static_cast<jstring>(env->CallObjectMethod(jIPAddress, jGetHostAddressMid)); |
| |
| chip::Inet::IPAddress addressInet; |
| chip::JniUtfString addressJniString(env, jIPAddressStr); |
| VerifyOrReturnError(chip::Inet::IPAddress::FromString(addressJniString.c_str(), addressInet), CHIP_ERROR_INVALID_ARGUMENT); |
| outCppDiscoveredNodeData.resolutionData.ipAddress[ipAddressCount] = addressInet; |
| |
| if (ipAddressCount == 0) |
| { |
| outCppDiscoveredNodeData.resolutionData.interfaceId = chip::Inet::InterfaceId::FromIPAddress(addressInet); |
| } |
| ipAddressCount++; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |