diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java
index 482ae0fedf439ec74f771aba0a79ab09a78a0d35..5a5ca57fce35ce973a81f545e1668c0de10c94d2 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java
@@ -1,6 +1,7 @@
 package org.matrix.olm;
 
 import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
 import android.util.Log;
 
 import org.junit.BeforeClass;
@@ -10,6 +11,7 @@ import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
 
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -19,6 +21,15 @@ public class OlmGroupTest {
     private static final String LOG_TAG = "OlmSessionTest";
 
     private static OlmManager mOlmManager;
+    private static OlmOutboundGroupSession mAliceOutboundSession;
+    private static String mAliceSessionIdentifier;
+    private static long mAliceMessageIndex;
+    public  static final String CLEAR_MESSAGE1 = "Hello!";
+    private static String mAliceToBobMessage;
+    private static OlmInboundGroupSession mBobInboundSession;
+    private static String mAliceOutboundSessionKey;
+    private static String mBobSessionIdentifier;
+    private static String mBobDecryptedMessage;
 
     @BeforeClass
     public static void setUpClass(){
@@ -30,66 +41,112 @@ public class OlmGroupTest {
         Log.d(LOG_TAG, "## setUpClass(): lib version="+version);
     }
 
-    @Test
-    public void test00AliceToBob() {
-        // TBD
-    }
-
     /**
      * Basic test:
-     * - alice creates an account
-     * - bob creates an account
      * - alice creates an outbound group session
      * - bob creates an inbound group session with alice's outbound session key
      * - alice encrypts a message with its session
      * - bob decrypts the encrypted message with its session
+     * - decrypted message is identical to original alice message
      */
-    //@Test
-    public void test01AliceToBob() {
-        // creates alice outbound session
-        OlmOutboundGroupSession aliceOutboundSession = new OlmOutboundGroupSession();
+    @Test
+    public void test01CreateOutboundSession() {
+        // alice creates OUTBOUND GROUP SESSION
+        try {
+            mAliceOutboundSession = new OlmOutboundGroupSession();
+        } catch (OlmException e) {
+            assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false);
+        }
+    }
 
-        // test accounts creation
-        String aliceSessionIdentifier = aliceOutboundSession.sessionIdentifier();
-        assertNotNull(aliceSessionIdentifier);
-        assertTrue(aliceSessionIdentifier.length()>0);
+    @Test
+    public void test02GetOutboundGroupSessionIdentifier() {
+        // test session ID
+        mAliceSessionIdentifier = mAliceOutboundSession.sessionIdentifier();
+        assertNotNull(mAliceSessionIdentifier);
+        assertTrue(mAliceSessionIdentifier.length() > 0);
+    }
 
-        String aliceOutboundSessionKey = aliceOutboundSession.sessionKey();
-        assertNotNull(aliceOutboundSessionKey);
-        assertTrue(aliceOutboundSessionKey.length()>0);
+    @Test
+    public void test03GetOutboundGroupSessionKey() {
+        // test session Key
+        mAliceOutboundSessionKey = mAliceOutboundSession.sessionKey();
+        assertNotNull(mAliceOutboundSessionKey);
+        assertTrue(mAliceOutboundSessionKey.length() > 0);
+    }
 
-        long messageIndex = aliceOutboundSession.messageIndex();
-        assertTrue(0==messageIndex);
+    @Test
+    public void test04GetOutboundGroupMessageIndex() {
+        // test message index before any encryption
+        mAliceMessageIndex = mAliceOutboundSession.messageIndex();
+        assertTrue(0 == mAliceMessageIndex);
+    }
 
-        String clearMessage = "Hello!";
-        String encryptedMessage = aliceOutboundSession.encryptMessage(clearMessage);
-        assertNotNull(encryptedMessage);
+    @Test
+    public void test05OutboundGroupEncryptMessage() {
+        // alice encrypts a message to bob
+        mAliceToBobMessage = mAliceOutboundSession.encryptMessage(CLEAR_MESSAGE1);
+        assertFalse(TextUtils.isEmpty(mAliceToBobMessage));
+
+        // test message index after encryption is incremented
+        mAliceMessageIndex = mAliceOutboundSession.messageIndex();
+        assertTrue(1== mAliceMessageIndex);
+    }
+
+    @Test
+    public void test06CreateInboundGroupSession() {
+        // bob creates INBOUND GROUP SESSION with alice outbound key
+        try {
+            mBobInboundSession = new OlmInboundGroupSession(mAliceOutboundSessionKey);
+        } catch (OlmException e) {
+            assertTrue("Exception in bob OlmInboundGroupSession, Exception code=" + e.getExceptionCode(), false);
+        }
+    }
 
-        messageIndex = aliceOutboundSession.messageIndex();
-        assertTrue(1==messageIndex);
+    @Test
+    public void test07OutboundGroupSessionIdentifiers() {
+        // check session identifiers are equals
+        mAliceSessionIdentifier = mAliceOutboundSession.sessionIdentifier();
+        assertFalse(TextUtils.isEmpty(mAliceSessionIdentifier));
+    }
 
-        assertTrue(encryptedMessage.length()>=0);
+    @Test
+    public void test08InboundGroupSessionIdentifiers() {
+        // check session identifiers are equals
+        mBobSessionIdentifier = mBobInboundSession.sessionIdentifier();
+        assertFalse(TextUtils.isEmpty(mBobSessionIdentifier));
+        assertTrue(mAliceSessionIdentifier.equals(mBobSessionIdentifier));
+    }
 
-        OlmInboundGroupSession bobInboundSession = new OlmInboundGroupSession();
-        bobInboundSession.initInboundGroupSessionWithSessionKey(aliceOutboundSessionKey);
+    @Test
+    public void test09SessionIdentifiersIdentical() {
         // check session identifiers are equals
-        aliceSessionIdentifier = aliceOutboundSession.sessionIdentifier();
-        String bobSessionIdentifier = aliceOutboundSession.sessionIdentifier();
-        assertTrue(aliceSessionIdentifier.equals(bobSessionIdentifier ));
+        assertTrue(mAliceSessionIdentifier.equals(mBobSessionIdentifier));
+    }
 
-        String decryptedMessage = bobInboundSession.decryptMessage(encryptedMessage);
-        assertTrue(decryptedMessage.equals(bobSessionIdentifier ));
+    @Test
+    public void test10InboundDecryptMessage() {
+        // test decrypted message
+        mBobDecryptedMessage = mBobInboundSession.decryptMessage(mAliceToBobMessage);
+        assertFalse(TextUtils.isEmpty(mBobDecryptedMessage));
+        assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1));
     }
 
-    //@Test
-    public void test02InboundGroupSession() {
-        // creates alice outbound session
-        OlmInboundGroupSession aliceInboundSession = new OlmInboundGroupSession();
+    @Test
+    public void test11InboundDecryptedMessageIdentical() {
+        // test decrypted message
+        assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1));
+    }
 
-        // test session identifier
-        String sessionIdentifier = aliceInboundSession.sessionIdentifier();
-        assertNotNull(sessionIdentifier);
-        assertTrue(sessionIdentifier.length()>0);
+    @Test
+    public void test12ReleaseOutboundSession() {
+        // release group sessions
+        mAliceOutboundSession.releaseSession();
     }
 
+    @Test
+    public void test13ReleaseInboundSession() {
+        // release group sessions
+        mBobInboundSession.releaseSession();
+    }
 }
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtilsException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java
similarity index 90%
rename from java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtilsException.java
rename to java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java
index f0cdc83d1f04e17a47766e626394148726c1df29..d4c642fd54ff232060562b35c258562641fb60f6 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtilsException.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java
@@ -16,7 +16,7 @@
 
 package org.matrix.olm;
 
-public class OlmUtilsException extends Exception {
+public class OlmException extends Exception {
     // exception codes
     public static final int EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE = 0;
     public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 1;
@@ -24,7 +24,7 @@ public class OlmUtilsException extends Exception {
 
     private final int mCode;
 
-    public OlmUtilsException(int aExceptionCode) {
+    public OlmException(int aExceptionCode) {
         super();
         mCode = aExceptionCode;
     }
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
index aa15c32c5b1a8cad5a86e13dcd77b2e4a4aae826..86f86c45d9555f05fe273d14a9d68bcb1818697d 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
@@ -48,16 +48,16 @@ public class OlmInboundGroupSession implements Serializable {
      * The session key parameter is retrieved from a outbound group session
      * See {@link #initNewSession()} and {@link #initInboundGroupSessionWithSessionKey(String)}
      * @param aSessionKey session key
-     * @throws OlmUtilsException
+     * @throws OlmException
      */
-    public OlmInboundGroupSession(String aSessionKey) throws OlmUtilsException {
+    public OlmInboundGroupSession(String aSessionKey) throws OlmException {
         if(initNewSession()) {
             if( 0 != initInboundGroupSessionWithSessionKey(aSessionKey)) {
                 releaseSession();// prevent memory leak before throwing
-                throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION);
+                throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION);
             }
         } else {
-            throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE);
+            throw new OlmException(OlmException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE);
         }
     }
 
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java
index bbe27188dccde29103182930ec410e7237a01a27..bca7ab3c73551f5a18f01841f49562ec48b044b1 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java
@@ -18,7 +18,6 @@ package org.matrix.olm;
 
 
 import android.text.TextUtils;
-import android.util.Log;
 
 public class OlmOutboundGroupSession {
     private static final String LOG_TAG = "OlmOutboundGroupSession";
@@ -41,16 +40,16 @@ public class OlmOutboundGroupSession {
      * Create and save a new session native instance ID and
      * initialise a new outbound group session.<br>
      * See {@link #initNewSession()} and {@link #initOutboundGroupSession()}
-     * @throws OlmUtilsException
+     * @throws OlmException
      */
-    public OlmOutboundGroupSession() throws OlmUtilsException {
+    public OlmOutboundGroupSession() throws OlmException {
         if(initNewSession()) {
             if( 0 != initOutboundGroupSession()) {
                 releaseSession();// prevent memory leak before throwing
-                throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION);
+                throw new OlmException(OlmException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION);
             }
         } else {
-            throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE);
+            throw new OlmException(OlmException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE);
         }
     }
 
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp
index 16e5a0bd271382370163e54227cfdc080548b360..09995aba207d88c3e66e476c749115b2d6b0453c 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp
@@ -26,7 +26,7 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env
 {
   OlmInboundGroupSession* sessionPtr = NULL;
 
-  LOGD("## releaseSessionJni(): sessionPtr=%p",sessionPtr);
+  LOGD("## releaseSessionJni(): intbound group session");
 
   if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
   {
@@ -34,12 +34,14 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env
   }
   else
   {
+    LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr);
+
     size_t retCode = olm_clear_inbound_group_session(sessionPtr);
-    LOGD("## releaseSessionJni(): clear_inbound_group_session=%lu",retCode);
+    LOGD(" ## releaseSessionJni(): clear_inbound_group_session=%lu",retCode);
 
-    LOGD("## releaseSessionJni(): IN");
+    LOGD(" ## releaseSessionJni(): free IN");
     free(sessionPtr);
-    LOGD("## releaseSessionJni(): OUT");
+    LOGD(" ## releaseSessionJni(): free OUT");
   }
 }
 
@@ -52,20 +54,23 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env
 JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz)
 {
     OlmInboundGroupSession* sessionPtr = NULL;
-    size_t sessionSize = olm_inbound_group_session_size();
+    size_t sessionSize = 0;
+
+    LOGD("## initNewSessionJni(): inbound group session IN");
+    sessionSize = olm_inbound_group_session_size();
 
     if(0 == sessionSize)
     {
-        LOGE("## initNewSessionJni(): failure - inbound group session size = 0");
+        LOGE(" ## initNewSessionJni(): failure - inbound group session size = 0");
     }
     else if(NULL != (sessionPtr=(OlmInboundGroupSession*)malloc(sessionSize)))
     {
       sessionPtr = olm_inbound_group_session(sessionPtr);
-      LOGD("## initNewSessionJni(): success - inbound group session size=%lu",sessionSize);
+      LOGD(" ## initNewSessionJni(): success - inbound group session size=%lu",sessionSize);
     }
     else
     {
-      LOGE("## initNewSessionJni(): failure - inbound group session OOM");
+      LOGE(" ## initNewSessionJni(): failure - inbound group session OOM");
     }
 
     return (jlong)(intptr_t)sessionPtr;
@@ -83,32 +88,34 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes
     const uint8_t *sessionKeyPtr = NULL;
     size_t sessionResult;
 
+    LOGD("## initInboundGroupSessionWithSessionKeyJni(): inbound group session IN");
+
     if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
     {
-        LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid inbound group session instance");
+        LOGE(" ## initInboundGroupSessionWithSessionKeyJni(): failure - invalid inbound group session instance");
     }
     else if(0 == aSessionKey)
     {
-        LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey");
+        LOGE(" ## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey");
     }
     else if(NULL == (sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0)))
     {
-        LOGE("## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM");
+        LOGE(" ## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM");
     }
     else
     {
         size_t sessionKeyLength = (size_t)env->GetStringUTFLength(aSessionKey);
-        LOGD("## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength);
+        LOGD(" ## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength);
 
         sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength);
         if(sessionResult == olm_error()) {
             const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
-            LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation  Msg=%s",errorMsgPtr);
+            LOGE(" ## initInboundSessionFromIdKeyJni(): failure - init inbound session creation  Msg=%s",errorMsgPtr);
         }
         else
         {
             retCode = ERROR_CODE_OK;
-            LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult);
+            LOGD(" ## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult);
         }
      }
 
@@ -135,17 +142,17 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn
 
     if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
     {
-        LOGE("## sessionIdentifierJni(): failure - invalid inbound group session instance");
+        LOGE(" ## sessionIdentifierJni(): failure - invalid inbound group session instance");
     }
     else
     {
         // get the size to alloc
         size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr);
-        LOGD("## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",lengthSessionId);
+        LOGD(" ## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",lengthSessionId);
 
         if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t))))
         {
-           LOGE("## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM");
+           LOGE(" ## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM");
         }
         else
         {
@@ -153,13 +160,13 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn
             if (result == olm_error())
             {
                 const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
-                LOGE("## sessionIdentifierJni(): failure - get inbound group session identifier failure Msg=%s",errorMsgPtr);
+                LOGE(" ## sessionIdentifierJni(): failure - get inbound group session identifier failure Msg=%s",errorMsgPtr);
             }
             else
             {
                 // update length
                 sessionIdPtr[result] = static_cast<char>('\0');
-                LOGD("## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%s",result, (char*)sessionIdPtr);
+                LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%s",result, (char*)sessionIdPtr);
                 returnValueStr = env->NewStringUTF((const char*)sessionIdPtr);
             }
             free(sessionIdPtr);
@@ -178,19 +185,19 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *
     uint8_t *plainTextMsgPtr = NULL;
     uint8_t *tempEncryptedPtr = NULL;
 
-    LOGD("## decryptMessageJni(): IN");
+    LOGD("## decryptMessageJni(): inbound group session IN");
 
     if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
     {
-        LOGE("##  decryptMessageJni(): failure - invalid inbound group session ptr=NULL");
+        LOGE(" ## decryptMessageJni(): failure - invalid inbound group session ptr=NULL");
     }
     else if(0 == aEncryptedMsg)
     {
-        LOGE("##  decryptMessageJni(): failure - invalid encrypted message");
+        LOGE(" ## decryptMessageJni(): failure - invalid encrypted message");
     }
     else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0)))
     {
-        LOGE("##  decryptMessageJni(): failure - encrypted message JNI allocation OOM");
+        LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM");
     }
     else
     {
@@ -200,12 +207,12 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *
         // create a dedicated temp buffer to be used in next Olm API calls
         if(NULL == (tempEncryptedPtr = static_cast<uint8_t*>(malloc(encryptedMsgLength*sizeof(uint8_t)))))
         {
-            LOGE("##  decryptMessageJni(): failure - tempEncryptedPtr allocation OOM");
+            LOGE(" ## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM");
         }
         else
         {
             memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
-            LOGD("##  decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr);
+            LOGD(" ## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr);
 
             // get max plaintext length
             size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr,
@@ -214,11 +221,11 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *
             if(maxPlainTextLength == olm_error())
             {
                 const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
-                LOGE("##  decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr);
+                LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr);
             }
             else
             {
-                LOGD("##  decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength);
+                LOGD(" ## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength);
 
                 // allocate output decrypted message
                 plainTextMsgPtr = static_cast<uint8_t*>(malloc(maxPlainTextLength*sizeof(uint8_t)));
@@ -233,14 +240,14 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *
                 if(plaintextLength == olm_error())
                 {
                     const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
-                    LOGE("##  decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr);
+                    LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr);
                 }
                 else
                 {
                     // update decrypted buffer size
                     plainTextMsgPtr[plaintextLength] = static_cast<char>('\0');
 
-                    LOGD("##  decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr);
+                    LOGD(" ## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr);
                     decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr);
                 }
             }
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp
index 46c0ee4b1751a2248abd7748787cd68c16a6a96c..42d8901225d178cc9f6c8cd84b61faaa88b0b942 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp
@@ -26,20 +26,22 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en
 {
   OlmOutboundGroupSession* sessionPtr = NULL;
 
-  LOGD("## releaseSessionJni(): sessionPtr=%p",sessionPtr);
+  LOGD("## releaseSessionJni(): outbound group session");
 
   if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz)))
   {
-      LOGE("## releaseSessionJni(): failure - invalid outbound group session instance");
+      LOGE(" ## releaseSessionJni(): failure - invalid outbound group session instance");
   }
   else
   {
+    LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr);
+
     size_t retCode = olm_clear_outbound_group_session(sessionPtr);
-    LOGD("## releaseSessionJni(): clear_outbound_group_session=%lu",retCode);
+    LOGD(" ## releaseSessionJni(): clear_outbound_group_session=%lu",retCode);
 
-    LOGD("## releaseSessionJni(): IN");
+    LOGD(" ## releaseSessionJni(): free IN");
     free(sessionPtr);
-    LOGD("## releaseSessionJni(): OUT");
+    LOGD(" ## releaseSessionJni(): free OUT");
   }
 }
 
@@ -52,20 +54,23 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en
 JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz)
 {
     OlmOutboundGroupSession* sessionPtr = NULL;
-    size_t sessionSize = olm_outbound_group_session_size();
+    size_t sessionSize = 0;
+
+    LOGD("## initNewSessionJni(): outbound group session IN");
+    sessionSize = olm_outbound_group_session_size();
 
     if(0 == sessionSize)
     {
-        LOGE("## initNewSessionJni(): failure - outbound group session size = 0");
+        LOGE(" ## initNewSessionJni(): failure - outbound group session size = 0");
     }
     else if(NULL != (sessionPtr=(OlmOutboundGroupSession*)malloc(sessionSize)))
     {
       sessionPtr = olm_outbound_group_session(sessionPtr);
-      LOGD("## initNewSessionJni(): success - outbound group session size=%lu",sessionSize);
+      LOGD(" ## initNewSessionJni(): success - outbound group session size=%lu",sessionSize);
     }
     else
     {
-      LOGE("## initNewSessionJni(): failure - outbound group session OOM");
+      LOGE(" ## initNewSessionJni(): failure - outbound group session OOM");
     }
 
     return (jlong)(intptr_t)sessionPtr;
@@ -85,33 +90,33 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(
 
     if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz)))
     {
-        LOGE("## initOutboundGroupSessionJni(): failure - invalid outbound group session instance");
+        LOGE(" ## initOutboundGroupSessionJni(): failure - invalid outbound group session instance");
     }
     else
     {
         // compute random buffer
         size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr);
-        LOGW("## initOutboundGroupSessionJni(): randomLength=%lu",randomLength);
+        LOGW(" ## initOutboundGroupSessionJni(): randomLength=%lu",randomLength);
         if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength))
         {
-            LOGE("## initOutboundGroupSessionJni(): failure - random buffer init");
+            LOGE(" ## initOutboundGroupSessionJni(): failure - random buffer init");
         }
         else
         {
             if(0==randomLength)
             {
-                LOGW("## initOutboundGroupSessionJni(): random buffer is not required");
+                LOGW(" ## initOutboundGroupSessionJni(): random buffer is not required");
             }
 
             size_t sessionResult = olm_init_outbound_group_session(sessionPtr, randomBuffPtr, randomLength);
             if(sessionResult == olm_error()) {
                 const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr);
-                LOGE("## initOutboundGroupSessionJni(): failure - init outbound session creation  Msg=%s",errorMsgPtr);
+                LOGE(" ## initOutboundGroupSessionJni(): failure - init outbound session creation  Msg=%s",errorMsgPtr);
             }
             else
             {
                 retCode = ERROR_CODE_OK;
-                LOGD("## initOutboundGroupSessionJni(): success - result=%lu", sessionResult);
+                LOGD(" ## initOutboundGroupSessionJni(): success - result=%lu", sessionResult);
             }
         }
       }
@@ -137,17 +142,17 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE
 
     if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz)))
     {
-        LOGE("## sessionIdentifierJni(): failure - invalid outbound group session instance");
+        LOGE(" ## sessionIdentifierJni(): failure - invalid outbound group session instance");
     }
     else
     {
         // get the size to alloc
         size_t lengthSessionId = olm_outbound_group_session_id_length(sessionPtr);
-        LOGD("## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",lengthSessionId);
+        LOGD(" ## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",lengthSessionId);
 
         if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t))))
         {
-           LOGE("## sessionIdentifierJni(): failure - outbound identifier allocation OOM");
+           LOGE(" ## sessionIdentifierJni(): failure - outbound identifier allocation OOM");
         }
         else
         {
@@ -155,13 +160,13 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE
             if (result == olm_error())
             {
                 const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr);
-                LOGE("## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s",errorMsgPtr);
+                LOGE(" ## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s",errorMsgPtr);
             }
             else
             {
                 // update length
                 sessionIdPtr[result] = static_cast<char>('\0');
-                LOGD("## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId=%s",result, (char*)sessionIdPtr);
+                LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId=%s",result, (char*)sessionIdPtr);
                 returnValueStr = env->NewStringUTF((const char*)sessionIdPtr);
             }
 
@@ -189,13 +194,13 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env,
 
     if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz)))
     {
-        LOGE("## messageIndexJni(): failure - invalid outbound group session instance");
+        LOGE(" ## messageIndexJni(): failure - invalid outbound group session instance");
     }
     else
     {
         indexRetValue = static_cast<jint>(olm_outbound_group_session_message_index(sessionPtr));
     }
-    LOGD("## messageIndexJni(): success - index=%d",indexRetValue);
+    LOGD(" ## messageIndexJni(): success - index=%d",indexRetValue);
 
     return indexRetValue;
 }
@@ -282,28 +287,28 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv
         size_t encryptedMsgLength = olm_group_encrypt_message_length(sessionPtr,clearMsgLength);
         if(NULL == (encryptedMsgPtr = (uint8_t*)malloc(encryptedMsgLength*sizeof(uint8_t))))
         {
-            LOGE("## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM");
+            LOGE(" ## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM");
         }
         else
         {
             LOGD(" ## encryptMessageJni(): estimated encryptedMsgLength=%lu",encryptedMsgLength);
 
-            size_t decryptedLength = olm_group_encrypt(sessionPtr,
+            size_t encryptedLength = olm_group_encrypt(sessionPtr,
                                                        (uint8_t*)clearMsgPtr,
                                                        clearMsgLength,
                                                        encryptedMsgPtr,
                                                        encryptedMsgLength);
-            if(decryptedLength == olm_error())
+            if(encryptedLength == olm_error())
             {
                 const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr);
-                LOGE(" ## encryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr);
+                LOGE(" ## encryptMessageJni(): failure - olm_group_encrypt Msg=%s",errorMsgPtr);
             }
             else
             {
                 // update decrypted buffer size
-                encryptedMsgPtr[decryptedLength] = static_cast<char>('\0');
+                encryptedMsgPtr[encryptedLength] = static_cast<char>('\0');
 
-                LOGD(" ## encryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",decryptedLength, (char*)encryptedMsgPtr);
+                LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%s",encryptedLength, (char*)encryptedMsgPtr);
                 encryptedMsgRetValue = env->NewStringUTF((const char*)encryptedMsgPtr);
             }
         }
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
index 591159192766ab9ec22f42cbf7b759d27b866e77..889e993f4e867a299934cd375e36e99ac94ec1c8 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
@@ -69,14 +69,16 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thi
 {
     OlmSession* sessionPtr = NULL;
 
+    LOGD("## initNewSessionJni(): OlmSession IN");
+
     // init account memory allocation
     if(NULL == (sessionPtr = initializeSessionMemory()))
     {
-        LOGE("## initNewSessionJni(): failure - init session OOM");
+        LOGE(" ## initNewSessionJni(): failure - init session OOM");
     }
     else
     {
-       LOGD("## initNewSessionJni(): success - OLM session created");
+       LOGD(" ## initNewSessionJni(): success - OLM session created");
     }
 
     return (jlong)(intptr_t)sessionPtr;
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp
index bd920fe4529e45b9aafed72288a60afeaf5e33a1..fb9c9c5cbd6072ae2d992f1f0779dd1001920a79 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp
@@ -1,6 +1,3 @@
-/**
- * Created by pedrocon on 06/10/2016.
- */
 /*
  * Copyright 2016 OpenMarket Ltd
  *
@@ -21,201 +18,20 @@
 #include "olm_utility.h"
 
 /**
-* Init a buffer with a given number of random values.
-* @param aBuffer2Ptr the buffer to be initialized
-* @param aRandomSize the number of random values to apply
-* @return true if operation succeed, false otherwise
-**/
-bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize)
+ * Verify an ed25519 signature.
+ * If the key was too small then the message will be "OLM.INVALID_BASE64".
+ * If the signature was invalid then the message will be "OLM.BAD_MESSAGE_MAC".
+ * @param aKey the ed25519 key.
+ * @param aMessage the message which was signed.
+ * @param aSignature the base64-encoded signature to be checked.
+ * @param the result error if there is a problem with the verification.
+ * @return true if validation succeed, false otherwise
+ */
+JNIEXPORT bool OLM_UTILITY_FUNC_DEF(ed25519VerifyJni)(JNIEnv *env, jobject thiz, jstring aKey, jstring aMessage, jstring aSignature, jobject aErrorMessage)
 {
     bool retCode = false;
-    if(NULL == aBuffer2Ptr)
-    {
-        LOGD("## setRandomInBuffer(): failure - aBuffer=NULL");
-    }
-    else if(0 == aRandomSize)
-    {
-        LOGD("## setRandomInBuffer(): failure - random size=0");
-    }
-    else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(aRandomSize*sizeof(uint8_t))))
-    {
-        LOGD("## setRandomInBuffer(): failure - alloc mem OOM");
-    }
-    else
-    {
-        LOGD("## setRandomInBuffer(): randomSize=%ld",aRandomSize);
 
-        srand(time(NULL)); // init seed
-        for(size_t i=0;i<aRandomSize;i++)
-        {
-            (*aBuffer2Ptr)[i] = (uint8_t)(rand()%ACCOUNT_CREATION_RANDOM_MODULO);
 
-            // debug purpose
-            //LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]);
-        }
 
-        retCode = true;
-    }
     return retCode;
-}
-
-
-/**
-* Read the account instance ID of the calling object.
-* @param aJniEnv pointer pointing on the JNI function table
-* @param aJavaObject reference to the object on which the method is invoked
-* @return the instance ID if operation succeed, -1 if instance ID was not found.
-**/
-jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
-{
-  jlong instanceId=-1;
-  jfieldID instanceIdField;
-  jclass loaderClass;
-
-  if(NULL!=aJniEnv)
-  {
-    if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject)))
-    {
-      if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmAccountId", "J")))
-      {
-        instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
-        aJniEnv->DeleteLocalRef(loaderClass);
-        LOGD("## getAccountInstanceId(): read from java instanceId=%lld",instanceId);
-      }
-      else
-      {
-        LOGD("## getAccountInstanceId() ERROR! GetFieldID=null");
-      }
-    }
-    else
-    {
-      LOGD("## getAccountInstanceId() ERROR! GetObjectClass=null");
-    }
-  }
-  else
-  {
-    LOGD("## getAccountInstanceId() ERROR! aJniEnv=NULL");
-  }
-  LOGD("## getAccountInstanceId() success - instanceId=%lld",instanceId);
-  return instanceId;
-}
-
-/**
-* Read the session instance ID of the calling object (aJavaObject).<br>
-* @param aJniEnv pointer pointing on the JNI function table
-* @param aJavaObject reference to the object on which the method is invoked
-* @return the instance ID if read succeed, -1 otherwise.
-**/
-jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
-{
-  jlong instanceId=-1;
-  jfieldID instanceIdField;
-  jclass loaderClass;
-
-  if(NULL!=aJniEnv)
-  {
-    if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject)))
-    {
-      if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmSessionId", "J")))
-      {
-        instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
-        aJniEnv->DeleteLocalRef(loaderClass);
-      }
-      else
-      {
-        LOGD("## getSessionInstanceId() ERROR! GetFieldID=null");
-      }
-    }
-    else
-    {
-      LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null");
-    }
-  }
-  else
-  {
-    LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL");
-  }
-
-  //LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId);
-  return instanceId;
-}
-
-
-/**
-* Read the inbound group session instance ID of the calling object (aJavaObject).<br>
-* @param aJniEnv pointer pointing on the JNI function table
-* @param aJavaObject reference to the object on which the method is invoked
-* @return the instance ID if read succeed, -1 otherwise.
-**/
-jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
-{
-  jlong instanceId=-1;
-  jfieldID instanceIdField;
-  jclass loaderClass;
-
-  if(NULL!=aJniEnv)
-  {
-    if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject)))
-    {
-      if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmInboundGroupSessionId", "J")))
-      {
-        instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
-        aJniEnv->DeleteLocalRef(loaderClass);
-      }
-      else
-      {
-        LOGD("## getSessionInstanceId() ERROR! GetFieldID=null");
-      }
-    }
-    else
-    {
-      LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null");
-    }
-  }
-  else
-  {
-    LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL");
-  }
-
-  return instanceId;
-}
-
-
-/**
-* Read the outbound group session instance ID of the calling object (aJavaObject).<br>
-* @param aJniEnv pointer pointing on the JNI function table
-* @param aJavaObject reference to the object on which the method is invoked
-* @return the instance ID if read succeed, -1 otherwise.
-**/
-jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
-{
-  jlong instanceId=-1;
-  jfieldID instanceIdField;
-  jclass loaderClass;
-
-  if(NULL!=aJniEnv)
-  {
-    if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject)))
-    {
-      if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmOutboundGroupSessionId", "J")))
-      {
-        instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
-        aJniEnv->DeleteLocalRef(loaderClass);
-      }
-      else
-      {
-        LOGD("## getSessionInstanceId() ERROR! GetFieldID=null");
-      }
-    }
-    else
-    {
-      LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null");
-    }
-  }
-  else
-  {
-    LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL");
-  }
-
-  return instanceId;
-}
+}
\ No newline at end of file
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h
index b16e9156d0600a43d297a5b57eb5bf91a96f1f4b..4e5772cda7bc5cb5a8e0b7c7664bd29b6848feb2 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h
@@ -17,19 +17,18 @@
 #ifndef _OMLUTILITY_H
 #define _OMLUTILITY_H
 
+#define OLM_UTILITY_FUNC_DEF(func_name) FUNC_DEF(OlmUtility,func_name)
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize);
-jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
-jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
-jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
+JNIEXPORT bool OLM_UTILITY_FUNC_DEF(ed25519VerifyJni)(JNIEnv *env, jobject thiz, jstring aKey, jstring aMessage, jstring aSignature, jobject aErrorMessage);
 
 #ifdef __cplusplus
 }
 #endif
 
 
+
 #endif