Add a Java event data class for the discovery event
authorSung-jae Park <nicesj.park@samsung.com>
Fri, 1 Oct 2021 04:06:05 +0000 (13:06 +0900)
committerYoungjae Shin <yj99.shin@samsung.com>
Thu, 28 Oct 2021 10:29:19 +0000 (19:29 +0900)
[Problem] Java BeyonD Device application cannot get the event data
[Solution] Add an eventObject for the discovery event

Change-Id: I22fdee660f9aa5c71389233fddd895832f6c3304
Signed-off-by: Sung-jae Park <nicesj.park@samsung.com>
subprojects/libbeyond-android/src/main/java/com/samsung/android/beyond/discovery/Discovery.java
subprojects/libbeyond-android/src/main/jni/discovery/beyond-discovery_jni.cc
subprojects/libbeyond-android/src/main/jni/discovery/beyond-discovery_jni.h

index fbe8a21d186e45f3ac45d23f6e1f6293c7cc7ec8..4cd9009563da1418acc59b6d5fa7b872c35f313f 100644 (file)
@@ -28,6 +28,13 @@ public class Discovery extends NativeInstance {
         initialize();
     }
 
+    public static class Info {
+        public String name;
+        public String host;
+        public int port;
+        public String uuid;
+    }
+
     public class DefaultEventObject extends EventObject {
     }
 
index e2d27d8015868ac5abf6c50fedc581716b58e733..3f4078c00c16dc0e27fa0a05da52cd8e6f944618 100644 (file)
@@ -25,8 +25,9 @@
 #define BEYOND_EVENT_LISTENER_ON_EVENT_METHOD_SIGNATURE "(Lcom/samsung/android/beyond/EventObject;)V"
 
 #define BEYOND_DISCOVERY_EVENT_OBJECT_CLASS_NAME "com/samsung/android/beyond/discovery/Discovery$DefaultEventObject"
-#define BEYOND_DISCOVERY_EVENT_OBJECT_CONSTRUCTOR_NAME "<init>"
-#define BEYOND_DISCOVERY_EVENT_OBJECT_CONSTRUCTOR_SIGANTURE "()V"
+#define BEYOND_DISCOVERY_INFO_CLASS_NAME "com/samsung/android/beyond/discovery/Discovery$Info"
+#define BEYOND_DISCOVERY_DEFAULT_CONSTRUCTOR_NAME "<init>"
+#define BEYOND_DISCOVERY_DEFAULT_CONSTRUCTOR_SIGANTURE "()V"
 #define BEYOND_DISCOVERY_EVENT_OBJECT_EVENT_TYPE_FIELD_NAME "eventType"
 #define BEYOND_DISCOVERY_EVENT_OBJECT_EVENT_DATA_FIELD_NAME "eventData"
 
@@ -40,6 +41,15 @@ DiscoveryNativeInterface::EventObject DiscoveryNativeInterface::eventObject = {
 };
 jfieldID DiscoveryNativeInterface::eventListener = nullptr;
 
+DiscoveryNativeInterface::Info DiscoveryNativeInterface::infoObject = {
+    .klass = nullptr,
+    .constructor = nullptr,
+    .name = nullptr,
+    .host = nullptr,
+    .port = nullptr,
+    .uuid = nullptr,
+};
+
 DiscoveryNativeInterface::DiscoveryNativeInterface(void)
     : discovery(nullptr)
     , looper(nullptr)
@@ -64,7 +74,95 @@ DiscoveryNativeInterface::~DiscoveryNativeInterface(void)
     }
 }
 
-void DiscoveryNativeInterface::Java_com_samsung_android_beyond_discovery_Discovery_initialize(JNIEnv *env, jclass klass)
+void DiscoveryNativeInterface::initializeInfo(JNIEnv *env, jclass klass)
+{
+    jclass infoKlass = env->FindClass(BEYOND_DISCOVERY_INFO_CLASS_NAME);
+    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,
+                                              BEYOND_DISCOVERY_DEFAULT_CONSTRUCTOR_NAME,
+                                              BEYOND_DISCOVERY_DEFAULT_CONSTRUCTOR_SIGANTURE);
+    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.host == nullptr) {
+        ErrPrint("Unable to get the host 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;
+    }
+}
+
+void DiscoveryNativeInterface::initializeEventObject(JNIEnv *env, jclass klass)
 {
     eventListener = env->GetFieldID(klass,
                                     BEYOND_DISCOVERY_EVENT_LISTENER_FIELD_NAME,
@@ -130,8 +228,8 @@ void DiscoveryNativeInterface::Java_com_samsung_android_beyond_discovery_Discove
     }
 
     eventObject.constructor = env->GetMethodID(eventObject.klass,
-                                               BEYOND_DISCOVERY_EVENT_OBJECT_CONSTRUCTOR_NAME,
-                                               BEYOND_DISCOVERY_EVENT_OBJECT_CONSTRUCTOR_SIGANTURE);
+                                               BEYOND_DISCOVERY_DEFAULT_CONSTRUCTOR_NAME,
+                                               BEYOND_DISCOVERY_DEFAULT_CONSTRUCTOR_SIGANTURE);
     if (eventObject.constructor == nullptr) {
         ErrPrint("Unable to find the event constructor metohd");
         if (env->ExceptionCheck() == true) {
@@ -141,10 +239,98 @@ void DiscoveryNativeInterface::Java_com_samsung_android_beyond_discovery_Discove
         eventObject.klass = nullptr;
         return;
     }
+}
 
+void DiscoveryNativeInterface::Java_com_samsung_android_beyond_discovery_Discovery_initialize(JNIEnv *env, jclass klass)
+{
+    initializeInfo(env, klass);
+    initializeEventObject(env, klass);
     DbgPrint("Discovery JNI cache initialized");
 }
 
+jobject DiscoveryNativeInterface::NewEventObject(JNIEnv *env, jobject thiz, void *eventData)
+{
+    beyond_peer_info *info = static_cast<beyond_peer_info *>(eventData);
+    jstring host = nullptr;
+    jstring name = nullptr;
+
+    jobject object = env->NewObject(infoObject.klass, infoObject.constructor);
+    if (env->ExceptionCheck() == true) {
+        JNIPrintException(env);
+        return nullptr;
+    }
+    if (object == nullptr) {
+        ErrPrint("Failed to construct a new info object");
+        return nullptr;
+    }
+
+    if (info->host == nullptr) {
+        DbgPrint("There is no host information");
+    } else {
+        host = env->NewStringUTF(info->host);
+        if (env->ExceptionCheck() == true) {
+            JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+            env->DeleteLocalRef(object);
+            return nullptr;
+        }
+
+        if (host == nullptr) {
+            ErrPrint("host is not valid");
+            env->DeleteLocalRef(object);
+            return nullptr;
+        }
+
+        env->SetObjectField(object, infoObject.host, host);
+    }
+
+    if (info->name == nullptr) {
+        DbgPrint("There is no service name");
+    } else {
+        name = env->NewStringUTF(info->name);
+        if (env->ExceptionCheck() == true) {
+            JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+            env->DeleteLocalRef(object);
+            env->DeleteLocalRef(host);
+            return nullptr;
+        }
+
+        if (name == nullptr) {
+            ErrPrint("host is not valid");
+            env->DeleteLocalRef(object);
+            env->DeleteLocalRef(host);
+            return nullptr;
+        }
+
+        env->SetObjectField(object, infoObject.name, name);
+    }
+
+    jstring uuid = env->NewStringUTF(info->uuid);
+    if (env->ExceptionCheck() == true) {
+        JNIHelper::PrintException(env, __FUNCTION__, __LINE__);
+        env->DeleteLocalRef(object);
+        env->DeleteLocalRef(host);
+        env->DeleteLocalRef(name);
+        return nullptr;
+    }
+
+    if (uuid == nullptr) {
+        ErrPrint("uuid is not valid");
+        env->DeleteLocalRef(object);
+        env->DeleteLocalRef(host);
+        env->DeleteLocalRef(name);
+        return nullptr;
+    }
+
+    env->SetObjectField(object, infoObject.uuid, static_cast<jobject>(uuid));
+
+    // 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;
+}
+
 int DiscoveryNativeInterface::InvokeEventListener(JNIEnv *env, jobject thiz, int eventType, void *eventData)
 {
     jobject eventListenerObject = env->GetObjectField(thiz, eventListener);
@@ -159,19 +345,29 @@ int DiscoveryNativeInterface::InvokeEventListener(JNIEnv *env, jobject thiz, int
         if (env->ExceptionCheck() == true) {
             JNIPrintException(env);
         }
+        env->DeleteLocalRef(eventListenerObject);
         return -EFAULT;
     }
 
     env->SetIntField(object, eventObject.eventType, eventType);
+    jobject evtObj = nullptr;
     if (eventData != nullptr) {
-        // TODO: convert eventData to JAVA object
-        // env->SetObjectField(object, eventObject.eventData, static_cast<jobject>(eventData));
+        evtObj = NewEventObject(env, thiz, eventData);
+        if (evtObj == nullptr) {
+            env->DeleteLocalRef(object);
+            env->DeleteLocalRef(eventListenerObject);
+            return -EFAULT;
+        }
+
+        env->SetObjectField(object, eventObject.eventData, evtObj);
     }
+
     int ret = JNIHelper::CallVoidMethod(env, eventListenerObject,
                                         BEYOND_EVENT_LISTENER_ON_EVENT_METHOD_NAME,
                                         BEYOND_EVENT_LISTENER_ON_EVENT_METHOD_SIGNATURE,
                                         object);
     env->DeleteLocalRef(object);
+    env->DeleteLocalRef(evtObj);
     env->DeleteLocalRef(eventListenerObject);
     return ret;
 }
index 5206a73111594bf0299b1577c4d55f28a29a5c1e..c67a6a89515a0bd37575d98e4d62820b10100869 100644 (file)
@@ -36,6 +36,11 @@ private:
     DiscoveryNativeInterface(void);
     virtual ~DiscoveryNativeInterface(void);
 
+private:
+    static void initializeEventObject(JNIEnv *env, jclass klass);
+    static void initializeInfo(JNIEnv *env, jclass klass);
+    jobject NewEventObject(JNIEnv *env, jobject thiz, void *eventData);
+
 private:
     static void Java_com_samsung_android_beyond_discovery_Discovery_initialize(JNIEnv *env, jclass klass);
     static jlong Java_com_samsung_android_beyond_discovery_Discovery_create(JNIEnv *env, jobject thiz, jobjectArray args);
@@ -60,9 +65,19 @@ private: // JNI Cache
         jfieldID eventData;
     };
 
+    struct Info {
+        jclass klass;
+        jmethodID constructor;
+        jfieldID name;
+        jfieldID host;
+        jfieldID port;
+        jfieldID uuid;
+    };
+
 private: // JNI Cache
     static EventObject eventObject;
     static jfieldID eventListener;
+    static Info infoObject;
 
 private:
     int InvokeEventListener(JNIEnv *env, jobject thiz, int eventType, void *eventData);