Skip to content

Commit

Permalink
Surface a NetworkLocation on Android for ChipDeviceController (#13797)
Browse files Browse the repository at this point in the history
Currently there is a method to getIpAddress(), but we also need to know
the port. This adds a Java wrapper class that combines both properties,
and the JNI bindings to resolve.

Tested:
- Commissioned an m5stack, and verified that the resolved
  NetworkLocation on the Java side matched Addr 0 logged from DIS after
  mDNS discovery completed.
  • Loading branch information
g-coppock authored and pull[bot] committed Feb 6, 2024
1 parent 8b12e7c commit 3722189
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/controller/java/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ android_library("java") {
"src/chip/devicecontroller/ChipDeviceControllerException.java",
"src/chip/devicecontroller/GetConnectedDeviceCallbackJni.java",
"src/chip/devicecontroller/NetworkCredentials.java",
"src/chip/devicecontroller/NetworkLocation.java",
"src/chip/devicecontroller/PaseVerifierParams.java",
"zap-generated/chip/devicecontroller/ChipClusters.java",
"zap-generated/chip/devicecontroller/ChipStructs.java",
Expand Down
56 changes: 56 additions & 0 deletions src/controller/java/CHIPDeviceController-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ using namespace chip::Controller;
static void * IOThreadMain(void * arg);
static CHIP_ERROR N2J_PaseVerifierParams(JNIEnv * env, jlong setupPincode, jint passcodeId, jbyteArray pakeVerifier,
jobject & outParams);
static CHIP_ERROR N2J_NetworkLocation(JNIEnv * env, jstring ipAddress, jint port, jobject & outLocation);

namespace {

Expand Down Expand Up @@ -450,6 +451,40 @@ JNI_METHOD(jstring, getIpAddress)(JNIEnv * env, jobject self, jlong handle, jlon
return env->NewStringUTF(addrStr);
}

JNI_METHOD(jobject, getNetworkLocation)(JNIEnv * env, jobject self, jlong handle, jlong deviceId)
{
chip::DeviceLayer::StackLock lock;
AndroidDeviceControllerWrapper * wrapper = AndroidDeviceControllerWrapper::FromJNIHandle(handle);

chip::Inet::IPAddress addr;
uint16_t port;
jobject networkLocation;
char addrStr[50];

CHIP_ERROR err =
wrapper->Controller()->GetPeerAddressAndPort(PeerId()
.SetCompressedFabricId(wrapper->Controller()->GetCompressedFabricId())
.SetNodeId(static_cast<chip::NodeId>(deviceId)),
addr, port);

if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to get device address.");
JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err);
}

addr.ToString(addrStr);

err = N2J_NetworkLocation(env, env->NewStringUTF(addrStr), static_cast<jint>(port), networkLocation);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Controller, "Failed to create NetworkLocation");
JniReferences::GetInstance().ThrowError(env, sChipDeviceControllerExceptionCls, err);
}

return networkLocation;
}

JNI_METHOD(jlong, getCompressedFabricId)(JNIEnv * env, jobject self, jlong handle)
{
chip::DeviceLayer::StackLock lock;
Expand Down Expand Up @@ -621,3 +656,24 @@ CHIP_ERROR N2J_PaseVerifierParams(JNIEnv * env, jlong setupPincode, jint passcod
exit:
return err;
}

CHIP_ERROR N2J_NetworkLocation(JNIEnv * env, jstring ipAddress, jint port, jobject & outLocation)
{
CHIP_ERROR err = CHIP_NO_ERROR;
jmethodID constructor;
jclass locationClass;

err = JniReferences::GetInstance().GetClassRef(env, "chip/devicecontroller/NetworkLocation", locationClass);
JniClass networkLocationClass(locationClass);
SuccessOrExit(err);

env->ExceptionClear();
constructor = env->GetMethodID(locationClass, "<init>", "(Ljava/lang/String;I)V");
VerifyOrExit(constructor != nullptr, err = CHIP_JNI_ERROR_METHOD_NOT_FOUND);

outLocation = (jobject) env->NewObject(locationClass, constructor, ipAddress, port);

VerifyOrExit(!env->ExceptionCheck(), err = CHIP_JNI_ERROR_EXCEPTION_THROWN);
exit:
return err;
}
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,16 @@ public String getIpAddress(long deviceId) {
return getIpAddress(deviceControllerPtr, deviceId);
}

/**
* Returns the {@link NetworkLocation} at which the given {@code deviceId} has been found.
*
* @param deviceId the 64-bit node ID of the device
* @throws ChipDeviceControllerException if the device location could not be resolved
*/
public NetworkLocation getNetworkLocation(long deviceId) {
return getNetworkLocation(deviceControllerPtr, deviceId);
}

public long getCompressedFabricId() {
return getCompressedFabricId(deviceControllerPtr);
}
Expand Down Expand Up @@ -346,6 +356,8 @@ private native void getConnectedDevicePointer(

private native String getIpAddress(long deviceControllerPtr, long deviceId);

private native NetworkLocation getNetworkLocation(long deviceControllerPtr, long deviceId);

private native long getCompressedFabricId(long deviceControllerPtr);

private native void updateDevice(long deviceControllerPtr, long fabricId, long deviceId);
Expand Down
28 changes: 28 additions & 0 deletions src/controller/java/src/chip/devicecontroller/NetworkLocation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package chip.devicecontroller;

import java.util.Locale;

/** Represents a location on an operational network. */
public final class NetworkLocation {
private final String ipAddress;
private final int port;

public NetworkLocation(String ipAddress, int port) {
this.ipAddress = ipAddress;
this.port = port;
}

/** Returns the IP address (e.g. fe80::3e61:5ff:fe0c:89f8). */
public String getIpAddress() {
return ipAddress;
}

public int getPort() {
return port;
}

@Override
public String toString() {
return String.format(Locale.ROOT, "%s[%d]", ipAddress, port);
}
}

0 comments on commit 3722189

Please sign in to comment.