Add GetInfo for the Java API
authorSung-jae Park <nicesj.park@samsung.com>
Mon, 27 Sep 2021 01:56:40 +0000 (10:56 +0900)
committerYoungjae Shin <yj99.shin@samsung.com>
Thu, 28 Oct 2021 10:20:50 +0000 (19:20 +0900)
[Problem] There is no way to get the automatically allocated port number from the peer
[Solution] Add GetInfo method to the peer class

 * Create the information class to get and set the peer information

Change-Id: I40f71e8b3c5a595d4df10e7e5d7b03d8d4e1dac1
Signed-off-by: Sung-jae Park <nicesj.park@samsung.com>
subprojects/libbeyond-android/src/androidTest/java/com/samsung/android/beyond/InferenceUnitTest/InferenceHandlerUnitTest.java
subprojects/libbeyond-android/src/androidTest/java/com/samsung/android/beyond/InferenceUnitTest/InferencePeerUnitTest.java
subprojects/libbeyond-android/src/androidTest/java/com/samsung/android/beyond/InferenceUnitTest/TensorHandlerUnitTest.java
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/inference/Peer.java
subprojects/libbeyond-android/src/main/jni/authenticator/beyond-authenticator_jni.cc
subprojects/libbeyond-android/src/main/jni/inference/beyond-peer_jni.cc
subprojects/libbeyond-android/src/main/jni/inference/beyond-peer_jni.h

index f02e8b9f8aa2c1bed5b010250a0eafc38669fb05..fda655a791f3f00b0ca658cd6cefd5479292a141 100644 (file)
@@ -79,7 +79,11 @@ public class InferenceHandlerUnitTest {
 
         inferencePeer = InferenceModuleFactory.createPeerClient(context, NNModule.NAME);
         assertNotNull(inferencePeer);
-        assertTrue(inferencePeer.setInfo(TEST_SERVER_IP, TEST_SERVER_PORT, "NoUUID"));
+
+        Peer.Info info = new Peer.Info();
+        info.host = TEST_SERVER_IP;
+        info.port = TEST_SERVER_PORT;
+        assertTrue(inferencePeer.setInfo(info));
     }
 
     @Test
index 8a741384e0672887cdfe35b9d14331d392810a34..661e9282b44ddf8d563c5b916896da3bed94aa0d 100644 (file)
@@ -28,8 +28,6 @@ import com.samsung.android.beyond.module.peer.NN.NNModule;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import java.util.UUID;
-
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 import static com.samsung.android.beyond.TestUtils.*;
 import static org.junit.Assert.assertEquals;
@@ -54,12 +52,23 @@ public class InferencePeerUnitTest {
     }
 
     @Test
-    public void testPeerServerSetIpPort() {
+    public void testPeerServerSetInfo() {
         inferencePeer = InferenceModuleFactory.createPeerServer(context, NNModule.NAME);
 
         assertEquals(true, inferencePeer.setInfo());
     }
 
+    @Test
+    public void testPeerServerGetInfo() {
+        inferencePeer = InferenceModuleFactory.createPeerServer(context, NNModule.NAME);
+        inferencePeer.setInfo();
+
+        Peer.Info info = inferencePeer.getInfo();
+        assertNotNull(info);
+        assertEquals(info.port, 3000);
+        assertEquals(info.host, "0.0.0.0");
+    }
+
     @Test
     public void testPeerServerActivateControlChannel() {
         inferencePeer = InferenceModuleFactory.createPeerServer(context, NNModule.NAME);
@@ -111,16 +120,21 @@ public class InferencePeerUnitTest {
     }
 
     @Test
-    public void testPeerClientSetIpPort() {
+    public void testPeerClientSetInfo() {
         inferencePeer = InferenceModuleFactory.createPeerClient(context, NNModule.NAME);
-
-        assertEquals(true, inferencePeer.setInfo(TEST_SERVER_IP, TEST_SERVER_PORT, "NoUUID"));
+        Peer.Info info = new Peer.Info();
+        info.host = TEST_SERVER_IP;
+        info.port = TEST_SERVER_PORT;
+        assertEquals(true, inferencePeer.setInfo(info));
     }
 
     @Test
     public void testPeerClientActivateControlChannel() {
         inferencePeer = InferenceModuleFactory.createPeerClient(context, NNModule.NAME);
-        inferencePeer.setInfo(TEST_SERVER_IP, TEST_SERVER_PORT, "NoUUID");
+        Peer.Info info = new Peer.Info();
+        info.host = TEST_SERVER_IP;
+        info.port = TEST_SERVER_PORT;
+        inferencePeer.setInfo(info);
 
         assertEquals(true, inferencePeer.activateControlChannel());
     }
index 6adadcc72b98695f58403228143063aa8edd7b99..1651e6476252701efc36f02a5cad4c3b867468aa 100644 (file)
@@ -80,7 +80,11 @@ public class TensorHandlerUnitTest {
 
         inferencePeer = InferenceModuleFactory.createPeerClient(context, NNModule.NAME);
         assertNotNull(inferencePeer);
-        assertTrue(inferencePeer.setInfo(TEST_SERVER_IP, TEST_SERVER_PORT, "NoUUID"));
+
+        Peer.Info info = new Peer.Info();
+        info.host = TEST_SERVER_IP;
+        info.port = TEST_SERVER_PORT;
+        assertTrue(inferencePeer.setInfo(info));
         assertTrue(inferenceHandler.addInferencePeer(inferencePeer));   // Cover activateControlChannel()
 
         tensorHandler = new TensorHandler(inferenceHandler);
index c829f19651df0574c03bf2b0a25fdb660656f253..e4582ae2746aeee809e66c53c6b2c72a6083de3c 100644 (file)
@@ -23,6 +23,17 @@ import com.samsung.android.beyond.NativeInstance;
 import static com.samsung.android.beyond.inference.Option.TAG;
 
 public class Peer extends NativeInstance {
+    static {
+        initialize();
+    }
+
+    public static class Info {
+        public String name;
+        public String host;
+        public int port;
+        public String uuid;
+    }
+
     public Peer(Context context, String peerType, NodeType nodeType) {
         switch (nodeType) {
             case SERVER:
@@ -55,11 +66,19 @@ public class Peer extends NativeInstance {
     }
 
     public boolean setInfo() {
-        return setInfo(instance, "0.0.0.0", 3000, "N/A");
+        Info info = new Info();
+        info.host = "0.0.0.0";
+        info.port = 3000;
+        info.uuid = "N/A";
+        return setInfo(instance, info);
     }
 
-    public boolean setInfo(String peerIP, int peerPort, String uuid) {
-        return setInfo(instance, peerIP, peerPort, uuid);
+    public boolean setInfo(Info info) {
+        return setInfo(instance, info);
+    }
+
+    public Info getInfo() {
+        return getInfo(instance);
     }
 
     public boolean activateControlChannel() {
@@ -74,9 +93,13 @@ public class Peer extends NativeInstance {
         return deactivate(instance);
     }
 
+    private static native void initialize();
+
     private native long create(Context context, String[] args);
 
-    private native boolean setInfo(long handle, String peerIP, int peerPort, String uuid);
+    private native boolean setInfo(long handle, Info info);
+
+    private native Info getInfo(long handle);
 
     private native boolean activate(long handle);
 
index dba124b847c8c5efaf9a6fcfcb6f9cfef9daf36f..38270695aed25a7532ee6f9e8a9cbcd3a08aeac2 100644 (file)
@@ -185,6 +185,12 @@ void AuthenticatorNativeInterface::Java_com_samsung_android_beyond_Authenticator
         eventObject.klass = nullptr;
         return;
     }
+    if (eventObject.eventData == nullptr) {
+        ErrPrint("Unable to get the event data field");
+        env->DeleteGlobalRef(eventObject.klass);
+        eventObject.klass = nullptr;
+        return;
+    }
 
     eventObject.constructor = env->GetMethodID(eventObject.klass,
                                                BEYOND_AUTHENTICATOR_EVENT_OBJECT_CONSTRUCTOR_NAME,
@@ -195,6 +201,12 @@ void AuthenticatorNativeInterface::Java_com_samsung_android_beyond_Authenticator
         eventObject.klass = nullptr;
         return;
     }
+    if (eventObject.constructor == nullptr) {
+        ErrPrint("Unable to get the constructor");
+        env->DeleteGlobalRef(eventObject.klass);
+        eventObject.klass = nullptr;
+        return;
+    }
 
     DbgPrint("Authenticator JNI cache initialized");
 }
index 096d28cfeccb78cd1415e87fe3547880cc9ac87d..f2593afb6c5e98cef972bf7b0333ecb468dbc4b4 100644 (file)
 
 static void release_arguments(JNIEnv *env, int argc, const char **argv, jstring *strs);
 
+PeerNativeInterface::Info PeerNativeInterface::infoObject = {
+    .klass = nullptr,
+    .constructor = nullptr,
+    .name = nullptr,
+    .host = nullptr,
+    .port = nullptr,
+    .uuid = nullptr,
+};
+
 PeerNativeInterface::PeerNativeInterface(void)
     : peer(nullptr)
 {
@@ -149,7 +158,86 @@ static void release_arguments(JNIEnv *env, int argc, const char **argv, jstring
     delete[] strs;
 }
 
-jboolean PeerNativeInterface::Java_com_samsung_android_beyond_InferencePeer_set_info(JNIEnv *env, jobject thiz, jlong handle, jstring peer_ip, jint peer_port, jstring uuid)
+jobject PeerNativeInterface::Java_com_samsung_android_beyond_InferencePeer_get_info(JNIEnv *env, jobject thiz, jlong handle)
+{
+    if (env == nullptr) {
+        ErrPrint("JNIEnv is nullptr");
+        return nullptr;
+    }
+
+    PeerNativeInterface *peer_handle = reinterpret_cast<PeerNativeInterface *>(handle);
+    if (peer_handle == nullptr) {
+        ErrPrint("peer_handle == nullptr");
+        return nullptr;
+    }
+
+    const beyond_peer_info *info = nullptr;
+    if (peer_handle->peer->GetInfo(info) < 0) {
+        ErrPrint("Failed to get the peer info");
+        return nullptr;
+    }
+
+    jobject object = env->NewObject(infoObject.klass, infoObject.constructor);
+    if (env->ExceptionCheck() == true) {
+        JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+        return nullptr;
+    }
+    if (object == nullptr) {
+        ErrPrint("Failed to construct a new info object");
+        return nullptr;
+    }
+
+    if (info->host != nullptr) {
+        jstring host = env->NewStringUTF(info->host);
+        if (env->ExceptionCheck() == true) {
+            JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+            return nullptr;
+        }
+
+        if (host == nullptr) {
+            ErrPrint("host is not valid");
+            return nullptr;
+        }
+
+        env->SetObjectField(object, infoObject.host, host);
+    }
+
+    jstring uuid = env->NewStringUTF(info->uuid);
+    if (env->ExceptionCheck() == true) {
+        JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+        return nullptr;
+    }
+
+    if (uuid == nullptr) {
+        ErrPrint("uuid is not valid");
+        return nullptr;
+    }
+
+    env->SetObjectField(object, infoObject.uuid, static_cast<jobject>(uuid));
+
+    if (info->name != nullptr) {
+        jstring name = env->NewStringUTF(info->name);
+        if (env->ExceptionCheck() == true) {
+            JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+            return nullptr;
+        }
+
+        if (name == nullptr) {
+            ErrPrint("_name is not valid");
+            return nullptr;
+        }
+
+        env->SetObjectField(object, infoObject.name, name);
+    }
+
+    // TODO:
+    // Port array should be changed to a single value
+    // No more need to keep the multiple port information
+    env->SetIntField(object, infoObject.port, static_cast<const int>(info->port[0]));
+    return object;
+}
+
+jboolean PeerNativeInterface::Java_com_samsung_android_beyond_InferencePeer_set_info(JNIEnv *env, jobject thiz, jlong handle, jobject info)
 {
     if (env == nullptr) {
         ErrPrint("JNIEnv is nullptr.");
@@ -162,38 +250,57 @@ jboolean PeerNativeInterface::Java_com_samsung_android_beyond_InferencePeer_set_
         return false;
     }
 
-    beyond_peer_info info = {
-        .name = const_cast<char *>("serviceName"),
+    beyond_peer_info peerInfo = {
+        .name = nullptr,
         .host = nullptr,
-        .port = { static_cast<unsigned short>(peer_port) },
+        .port = { 0, 0 },
+        .uuid = {
+            0,
+        },
         .free_memory = 0llu,
         .free_storage = 0llu,
         .count_of_runtimes = 0,
         .runtimes = nullptr,
     };
 
-    const char *_uuid = env->GetStringUTFChars(uuid, nullptr);
-    if (_uuid == nullptr) {
-        ErrPrint("Fail to get StringUTFChars of uuid.");
-        return false;
-    }
+    jobject name = env->GetObjectField(info, infoObject.name);
+    jobject host = env->GetObjectField(info, infoObject.host);
+    jobject uuid = env->GetObjectField(info, infoObject.uuid);
+    jint port = env->GetIntField(info, infoObject.port);
 
-    snprintf(info.uuid, BEYOND_UUID_LEN, "%s", _uuid);
+    if (name != nullptr) {
+        peerInfo.name = const_cast<char *>(env->GetStringUTFChars(static_cast<jstring>(name), nullptr));
+    }
 
-    env->ReleaseStringUTFChars(uuid, _uuid);
+    if (host != nullptr) {
+        peerInfo.host = const_cast<char *>(env->GetStringUTFChars(static_cast<jstring>(host), nullptr));
+    }
 
-    const char *_peer_ip = env->GetStringUTFChars(peer_ip, nullptr);
-    if (_peer_ip == nullptr) {
-        ErrPrint("Fail to get StringUTFChars of a peer IP.");
-        return false;
+    if (uuid != nullptr) {
+        const char *_uuid = env->GetStringUTFChars(static_cast<jstring>(uuid), nullptr);
+        if (_uuid != nullptr) {
+            snprintf(peerInfo.uuid, BEYOND_UUID_LEN, "%s", _uuid);
+            env->ReleaseStringUTFChars(static_cast<jstring>(uuid), _uuid);
+        }
     }
 
-    info.host = const_cast<char *>(_peer_ip);
+    peerInfo.port[0] = static_cast<unsigned short>(port);
+    peerInfo.port[1] = 0;
+    peerInfo.free_memory = 0llu;
+    peerInfo.free_storage = 0llu;
+    peerInfo.count_of_runtimes = 0;
+    peerInfo.runtimes = nullptr;
+
+    int ret = peer_handle->peer->SetInfo(&peerInfo);
+
+    if (peerInfo.name != nullptr) {
+        env->ReleaseStringUTFChars(static_cast<jstring>(name), peerInfo.name);
+    }
 
-    DbgPrint("Peer IP = %s, ports[0] = %d, uuid = %s\n", _peer_ip, peer_port, info.uuid);
+    if (peerInfo.host != nullptr) {
+        env->ReleaseStringUTFChars(static_cast<jstring>(host), peerInfo.host);
+    }
 
-    int ret = peer_handle->peer->SetInfo(&info);
-    env->ReleaseStringUTFChars(peer_ip, _peer_ip);
     if (ret < 0) {
         ErrPrint("Fail to set peer info, ret = %d\n", ret);
         return false;
@@ -275,6 +382,94 @@ jboolean PeerNativeInterface::Java_com_samsung_android_beyond_InferencePeer_conf
     return true;
 }
 
+void PeerNativeInterface::Java_com_samsung_android_beyond_InferencePeer_initialize(JNIEnv *env, jclass klass)
+{
+    jclass infoKlass = env->FindClass("com/samsung/android/beyond/inference/Peer$Info");
+    if (infoKlass == nullptr) {
+        ErrPrint("Unable to get the class");
+        return;
+    }
+
+    infoObject.klass = static_cast<jclass>(env->NewGlobalRef(infoKlass));
+    env->DeleteLocalRef(infoKlass);
+    if (infoObject.klass == nullptr) {
+        ErrPrint("Unable to get the Info class");
+        return;
+    }
+
+    infoObject.constructor = env->GetMethodID(infoObject.klass, "<init>", "()V");
+    if (env->ExceptionCheck() == true) {
+        JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+        env->DeleteGlobalRef(infoObject.klass);
+        infoObject.klass = nullptr;
+        return;
+    }
+    if (infoObject.constructor == nullptr) {
+        ErrPrint("Unable to get the info constructor");
+        env->DeleteGlobalRef(infoObject.klass);
+        infoObject.klass = nullptr;
+        return;
+    }
+
+    infoObject.name = env->GetFieldID(infoObject.klass, "name", "Ljava/lang/String;");
+    if (env->ExceptionCheck() == true) {
+        JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+        env->DeleteGlobalRef(infoObject.klass);
+        infoObject.klass = nullptr;
+        return;
+    }
+    if (infoObject.name == nullptr) {
+        ErrPrint("Unable to get the name field from info");
+        env->DeleteGlobalRef(infoObject.klass);
+        infoObject.klass = nullptr;
+        return;
+    }
+
+    infoObject.host = env->GetFieldID(infoObject.klass, "host", "Ljava/lang/String;");
+    if (env->ExceptionCheck() == true) {
+        JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+        env->DeleteGlobalRef(infoObject.klass);
+        infoObject.klass = nullptr;
+        return;
+    }
+    if (infoObject.host == nullptr) {
+        ErrPrint("Unable to get the host field from info");
+        env->DeleteGlobalRef(infoObject.klass);
+        infoObject.klass = nullptr;
+        return;
+    }
+
+    infoObject.port = env->GetFieldID(infoObject.klass, "port", "I");
+    if (env->ExceptionCheck() == true) {
+        JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+        env->DeleteGlobalRef(infoObject.klass);
+        infoObject.klass = nullptr;
+        return;
+    }
+    if (infoObject.port == nullptr) {
+        ErrPrint("Unable to get the port field from info");
+        env->DeleteGlobalRef(infoObject.klass);
+        infoObject.klass = nullptr;
+        return;
+    }
+
+    infoObject.uuid = env->GetFieldID(infoObject.klass, "uuid", "Ljava/lang/String;");
+    if (env->ExceptionCheck() == true) {
+        JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+        env->DeleteGlobalRef(infoObject.klass);
+        infoObject.klass = nullptr;
+        return;
+    }
+    if (infoObject.uuid == nullptr) {
+        ErrPrint("Unable to get the uuid field from info");
+        env->DeleteGlobalRef(infoObject.klass);
+        infoObject.klass = nullptr;
+        return;
+    }
+
+    DbgPrint("Successfully initialized");
+}
+
 int PeerNativeInterface::RegisterPeerNatives(JNIEnv *env)
 {
     jclass klass = env->FindClass("com/samsung/android/beyond/inference/Peer");
@@ -283,16 +478,17 @@ int PeerNativeInterface::RegisterPeerNatives(JNIEnv *env)
     }
 
     static JNINativeMethod peer_jni_methods[] = {
-        { "create", "(Landroid/content/Context;[Ljava/lang/String;)J", (void *)Java_com_samsung_android_beyond_InferencePeer_create },
-        { "setInfo", "(JLjava/lang/String;ILjava/lang/String;)Z", (void *)Java_com_samsung_android_beyond_InferencePeer_set_info },
-        { "activate", "(J)Z", (void *)Java_com_samsung_android_beyond_InferencePeer_activate },
-        { "configure", "(JCLjava/lang/Object;)Z", (void *)Java_com_samsung_android_beyond_InferencePeer_configure },
-        { "deactivate", "(J)Z", (void *)Java_com_samsung_android_beyond_InferencePeer_deactivate },
-        { "destroy", "(J)V", (void *)Java_com_samsung_android_beyond_InferencePeer_destroy },
+        { "initialize", "()V", reinterpret_cast<void *>(Java_com_samsung_android_beyond_InferencePeer_initialize) },
+        { "create", "(Landroid/content/Context;[Ljava/lang/String;)J", reinterpret_cast<void *>(Java_com_samsung_android_beyond_InferencePeer_create) },
+        { "setInfo", "(JLcom/samsung/android/beyond/inference/Peer$Info;)Z", reinterpret_cast<void *>(Java_com_samsung_android_beyond_InferencePeer_set_info) },
+        { "getInfo", "(J)Lcom/samsung/android/beyond/inference/Peer$Info;", reinterpret_cast<void *>(Java_com_samsung_android_beyond_InferencePeer_get_info) },
+        { "activate", "(J)Z", reinterpret_cast<void *>(Java_com_samsung_android_beyond_InferencePeer_activate) },
+        { "configure", "(JCLjava/lang/Object;)Z", reinterpret_cast<void *>(Java_com_samsung_android_beyond_InferencePeer_configure) },
+        { "deactivate", "(J)Z", reinterpret_cast<void *>(Java_com_samsung_android_beyond_InferencePeer_deactivate) },
+        { "destroy", "(J)V", reinterpret_cast<void *>(Java_com_samsung_android_beyond_InferencePeer_destroy) },
     };
 
-    if (env->RegisterNatives(klass, peer_jni_methods,
-                             sizeof(peer_jni_methods) / sizeof(JNINativeMethod)) != JNI_OK) {
+    if (env->RegisterNatives(klass, peer_jni_methods, sizeof(peer_jni_methods) / sizeof(JNINativeMethod)) != JNI_OK) {
         ErrPrint("Failed to register peer jni methods for BeyonD Java APIs.");
         return -EFAULT;
     }
index 5a806c8584bbc3c5129723b20b258cf2a60ac297..86dfea4266d1c034e85a332cef7e748b61bd3028 100644 (file)
@@ -31,12 +31,24 @@ public:
     static int RegisterPeerNatives(JNIEnv *env);
     void *GetBeyonDInstance(void) override;
 
+private:
+    struct Info {
+        jclass klass;
+        jmethodID constructor;
+        jfieldID name;
+        jfieldID host;
+        jfieldID port;
+        jfieldID uuid;
+    };
+
 private:
     PeerNativeInterface(void);
     virtual ~PeerNativeInterface(void);
 
+    static void Java_com_samsung_android_beyond_InferencePeer_initialize(JNIEnv *env, jclass klass);
     static jlong Java_com_samsung_android_beyond_InferencePeer_create(JNIEnv *env, jobject thiz, jobject context, jobjectArray args);
-    static jboolean Java_com_samsung_android_beyond_InferencePeer_set_info(JNIEnv *env, jobject thiz, jlong handle, jstring peer_ip, jint peer_port, jstring uuid);
+    static jboolean Java_com_samsung_android_beyond_InferencePeer_set_info(JNIEnv *env, jobject thiz, jlong handle, jobject info);
+    static jobject Java_com_samsung_android_beyond_InferencePeer_get_info(JNIEnv *env, jobject thiz, jlong handle);
     static jboolean Java_com_samsung_android_beyond_InferencePeer_activate(JNIEnv *env, jobject thiz, jlong handle);
     static jboolean Java_com_samsung_android_beyond_InferencePeer_prepare(JNIEnv *env, jobject thiz, jlong handle);
     static jboolean Java_com_samsung_android_beyond_InferencePeer_deactivate(JNIEnv *env, jobject thiz, jlong handle);
@@ -44,6 +56,7 @@ private:
     static jboolean Java_com_samsung_android_beyond_InferencePeer_configure(JNIEnv *env, jobject thiz, jlong handle, jchar type, jobject obj);
 
     beyond::InferenceInterface::PeerInterface *peer;
+    static Info infoObject;
 };
 
 #if USE_PEER_NN