Enables SimpleClient/SimpleServer to communicate over the BLE on Android.
authorTim Kourt <tim.a.kourt@intel.com>
Wed, 19 Aug 2015 23:17:59 +0000 (16:17 -0700)
committerJon A. Cruz <jonc@osg.samsung.com>
Tue, 25 Aug 2015 18:23:00 +0000 (18:23 +0000)
The wait/re-try logic was introduced into CALEClientSendMulticastMessageImpl
to make sure that there is at least one connections established before
the send call is made.

Change-Id: I5ad52321fc316005dbc48e4e323205a661293f3e
Signed-off-by: Tim Kourt <tim.a.kourt@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2248
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jon A. Cruz <jonc@osg.samsung.com>
resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.c

index 075c9bd35c0e343d1106e0a9a0c2780bce3f5e29..ef9569d3a173599575a0c1a478d885fe84918ad1 100644 (file)
@@ -39,6 +39,8 @@
 
 #define TAG PCF("CA_LE_CLIENT")
 
+#define MICROSECS_PER_SEC 1000000
+
 static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;";
 static const char CLASSPATH_BT_ADAPTER[] = "android/bluetooth/BluetoothAdapter";
 static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
@@ -69,6 +71,7 @@ static bool g_isFinishedSendData = false;
 static ca_mutex g_SendFinishMutex = NULL;
 static ca_mutex g_threadMutex = NULL;
 static ca_cond g_threadCond = NULL;
+static ca_cond g_deviceDescCond = NULL;
 
 static ca_mutex g_threadSendMutex = NULL;
 
@@ -218,6 +221,8 @@ CAResult_t CALEClientInitialize(ca_thread_pool_t handle)
         return ret;
     }
 
+    g_deviceDescCond = ca_cond_new();
+
     // init mutex for send logic
     g_threadCond = ca_cond_new();
 
@@ -251,6 +256,11 @@ CAResult_t CALEClientInitialize(ca_thread_pool_t handle)
     }
     g_isStartedLEClient = true;
 
+    if (isAttached)
+    {
+        (*g_jvm)->DetachCurrentThread(g_jvm);
+    }
+
     return CA_STATUS_OK;
 }
 
@@ -324,8 +334,12 @@ void CALEClientTerminate()
 
     CALEClientTerminateGattMutexVariables();
 
+    ca_cond_free(g_deviceDescCond);
     ca_cond_free(g_threadCond);
 
+    g_deviceDescCond = NULL;
+    g_threadCond = NULL;
+
     if (isAttached)
     {
         (*g_jvm)->DetachCurrentThread(g_jvm);
@@ -610,6 +624,10 @@ error_exit:
     {
         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
         ca_mutex_unlock(g_threadSendMutex);
+        if (isAttached)
+        {
+            (*g_jvm)->DetachCurrentThread(g_jvm);
+        }
         return res;
     }
 
@@ -643,9 +661,35 @@ CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data,
     {
         (*env)->DeleteGlobalRef(env, g_sendBuffer);
     }
-    jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
-    (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
-    g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
+
+    if (0 == u_arraylist_length(g_deviceList))
+    {
+        // Wait for LE peripherals to be discovered.
+
+        // Number of times to wait for discovery to complete.
+        static int const RETRIES = 5;
+
+        static uint64_t const TIMEOUT =
+            2 * MICROSECS_PER_SEC;  // Microseconds
+
+        bool devicesDiscovered = false;
+        for (size_t i = 0;
+             0 == u_arraylist_length(g_deviceList) && i < RETRIES;
+             ++i)
+        {
+            if (ca_cond_wait_for(g_deviceDescCond,
+                                 g_threadSendMutex,
+                                 TIMEOUT) == 0)
+            {
+                devicesDiscovered = true;
+            }
+        }
+
+        if (!devicesDiscovered)
+        {
+            goto error_exit;
+        }
+    }
 
     // connect to gatt server
     CAResult_t res = CALEClientStopScan();
@@ -655,13 +699,12 @@ CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data,
         ca_mutex_unlock(g_threadSendMutex);
         return res;
     }
-
     uint32_t length = u_arraylist_length(g_deviceList);
     g_targetCnt = length;
-    if (0 == length)
-    {
-        goto error_exit;
-    }
+
+    jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
+    (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
+    g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
 
     for (uint32_t index = 0; index < length; index++)
     {
@@ -2068,6 +2111,7 @@ CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device)
     {
         jobject gdevice = (*env)->NewGlobalRef(env, device);
         u_arraylist_add(g_deviceList, gdevice);
+        ca_cond_signal(g_deviceDescCond);
         OIC_LOG(DEBUG, TAG, "Set Object to Array as Element");
     }
     (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);