diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/account/AccountCreationTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/account/AccountCreationTest.kt
index c44ac9c47b..679ea8f3fe 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/account/AccountCreationTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/account/AccountCreationTest.kt
@@ -38,9 +38,7 @@ class AccountCreationTest : InstrumentedTest {
     fun createAccountTest() {
         val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
 
-        commonTestHelper.signout(session)
-
-        session.close()
+        commonTestHelper.signOutAndClose(session)
     }
 
     @Test
@@ -50,14 +48,14 @@ class AccountCreationTest : InstrumentedTest {
         // Log again to the same account
         val session2 = commonTestHelper.logIntoAccount(session.myUserId, SessionTestParams(withInitialSync = true))
 
-        session.close()
-        session2.close()
+        commonTestHelper.signOutAndClose(session)
+        commonTestHelper.signOutAndClose(session2)
     }
 
     @Test
     fun simpleE2eTest() {
         val res = cryptoTestHelper.doE2ETestWithAliceInARoom()
 
-        res.close()
+        res.cleanUp(commonTestHelper)
     }
 }
diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CommonTestHelper.kt
index 2e18133071..386787b882 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CommonTestHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CommonTestHelper.kt
@@ -28,7 +28,10 @@ import im.vector.matrix.android.api.auth.data.LoginFlowResult
 import im.vector.matrix.android.api.auth.registration.RegistrationResult
 import im.vector.matrix.android.api.session.Session
 import im.vector.matrix.android.api.session.events.model.EventType
+import im.vector.matrix.android.api.session.events.model.LocalEcho
+import im.vector.matrix.android.api.session.events.model.toModel
 import im.vector.matrix.android.api.session.room.Room
+import im.vector.matrix.android.api.session.room.model.message.MessageContent
 import im.vector.matrix.android.api.session.room.timeline.Timeline
 import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.matrix.android.api.session.room.timeline.TimelineSettings
@@ -113,7 +116,7 @@ class CommonTestHelper(context: Context) {
     fun sendTextMessage(room: Room, message: String, nbOfMessages: Int): List<TimelineEvent> {
         val sentEvents = ArrayList<TimelineEvent>(nbOfMessages)
         val latch = CountDownLatch(nbOfMessages)
-        val onEventSentListener = object : Timeline.Listener {
+        val timelineListener = object : Timeline.Listener {
             override fun onTimelineFailure(throwable: Throwable) {
             }
 
@@ -122,20 +125,26 @@ class CommonTestHelper(context: Context) {
             }
 
             override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
-                // TODO Count only new messages?
-                if (snapshot.count { it.root.type == EventType.MESSAGE } == nbOfMessages) {
-                    sentEvents.addAll(snapshot.filter { it.root.type == EventType.MESSAGE })
+                val newMessages = snapshot
+                        .filter { LocalEcho.isLocalEchoId(it.eventId).not() }
+                        .filter { it.root.getClearType() == EventType.MESSAGE }
+                        .filter { it.root.getClearContent().toModel<MessageContent>()?.body?.startsWith(message) == true }
+
+                if (newMessages.size == nbOfMessages) {
+                    sentEvents.addAll(newMessages)
                     latch.countDown()
                 }
             }
         }
         val timeline = room.createTimeline(null, TimelineSettings(10))
-        timeline.addListener(onEventSentListener)
+        timeline.start()
+        timeline.addListener(timelineListener)
         for (i in 0 until nbOfMessages) {
             room.sendTextMessage(message + " #" + (i + 1))
         }
         await(latch)
-        timeline.removeListener(onEventSentListener)
+        timeline.removeListener(timelineListener)
+        timeline.dispose()
 
         // Check that all events has been created
         assertEquals(nbOfMessages.toLong(), sentEvents.size.toLong())
@@ -283,11 +292,10 @@ class CommonTestHelper(context: Context) {
     /**
      * Clear all provided sessions
      */
-    fun Iterable<Session>.close() = forEach { it.close() }
+    fun Iterable<Session>.signOutAndClose() = forEach { signOutAndClose(it) }
 
-    fun signout(session: Session) {
-        val lock = CountDownLatch(1)
-        session.signOut(true, TestMatrixCallback(lock))
-        await(lock)
+    fun signOutAndClose(session: Session) {
+        doSync<Unit> { session.signOut(true, it) }
+        session.close()
     }
 }
diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CryptoTestData.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CryptoTestData.kt
index 8ad9f1ec6f..7eea832160 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CryptoTestData.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CryptoTestData.kt
@@ -23,9 +23,9 @@ data class CryptoTestData(val firstSession: Session,
                           val secondSession: Session? = null,
                           val thirdSession: Session? = null) {
 
-    fun close() {
-        firstSession.close()
-        secondSession?.close()
-        secondSession?.close()
+    fun cleanUp(testHelper: CommonTestHelper) {
+        testHelper.signOutAndClose(firstSession)
+        secondSession?.let { testHelper.signOutAndClose(it) }
+        thirdSession?.let { testHelper.signOutAndClose(it) }
     }
 }
diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CryptoTestHelper.kt
index 7368c87252..826c70a63f 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CryptoTestHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/CryptoTestHelper.kt
@@ -41,16 +41,15 @@ import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
 import org.junit.Assert.assertNull
 import org.junit.Assert.assertTrue
-import java.util.Arrays
 import java.util.HashMap
 import java.util.concurrent.CountDownLatch
 
-class CryptoTestHelper(val mTestHelper: CommonTestHelper) {
+class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
 
-    val messagesFromAlice: List<String> = Arrays.asList("0 - Hello I'm Alice!", "4 - Go!")
-    val messagesFromBob: List<String> = Arrays.asList("1 - Hello I'm Bob!", "2 - Isn't life grand?", "3 - Let's go to the opera.")
+    private val messagesFromAlice: List<String> = listOf("0 - Hello I'm Alice!", "4 - Go!")
+    private val messagesFromBob: List<String> = listOf("1 - Hello I'm Bob!", "2 - Isn't life grand?", "3 - Let's go to the opera.")
 
-    val defaultSessionParams = SessionTestParams(true)
+    private val defaultSessionParams = SessionTestParams(true)
 
     /**
      * @return alice session
@@ -58,34 +57,23 @@ class CryptoTestHelper(val mTestHelper: CommonTestHelper) {
     fun doE2ETestWithAliceInARoom(): CryptoTestData {
         val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams)
 
-        var roomId: String? = null
-        val lock1 = CountDownLatch(1)
+        val roomId = mTestHelper.doSync<String> {
+            aliceSession.createRoom(CreateRoomParams(name = "MyRoom"), it)
+        }
 
-        aliceSession.createRoom(CreateRoomParams(name = "MyRoom"), object : TestMatrixCallback<String>(lock1) {
-            override fun onSuccess(data: String) {
-                roomId = data
-                super.onSuccess(data)
-            }
-        })
+        val room = aliceSession.getRoom(roomId)!!
 
-        mTestHelper.await(lock1)
-        assertNotNull(roomId)
+        mTestHelper.doSync<Unit> {
+            room.enableEncryption(callback = it)
+        }
 
-        val room = aliceSession.getRoom(roomId!!)!!
-
-        val lock2 = CountDownLatch(1)
-        room.enableEncryption(callback = TestMatrixCallback(lock2))
-        mTestHelper.await(lock2)
-
-        return CryptoTestData(aliceSession, roomId!!)
+        return CryptoTestData(aliceSession, roomId)
     }
 
     /**
      * @return alice and bob sessions
      */
     fun doE2ETestWithAliceAndBobInARoom(): CryptoTestData {
-        val statuses = HashMap<String, String>()
-
         val cryptoTestData = doE2ETestWithAliceInARoom()
         val aliceSession = cryptoTestData.firstSession
         val aliceRoomId = cryptoTestData.roomId
@@ -94,7 +82,7 @@ class CryptoTestHelper(val mTestHelper: CommonTestHelper) {
 
         val bobSession = mTestHelper.createAccount(TestConstants.USER_BOB, defaultSessionParams)
 
-        val lock1 = CountDownLatch(2)
+        val lock1 = CountDownLatch(1)
 
         val bobRoomSummariesLive = runBlocking(Dispatchers.Main) {
             bobSession.getRoomSummariesLive(roomSummaryQueryParams { })
@@ -103,7 +91,6 @@ class CryptoTestHelper(val mTestHelper: CommonTestHelper) {
         val newRoomObserver = object : Observer<List<RoomSummary>> {
             override fun onChanged(t: List<RoomSummary>?) {
                 if (t?.isNotEmpty() == true) {
-                    statuses["onNewRoom"] = "onNewRoom"
                     lock1.countDown()
                     bobRoomSummariesLive.removeObserver(this)
                 }
@@ -114,26 +101,20 @@ class CryptoTestHelper(val mTestHelper: CommonTestHelper) {
             bobRoomSummariesLive.observeForever(newRoomObserver)
         }
 
-        aliceRoom.invite(bobSession.myUserId, callback = object : TestMatrixCallback<Unit>(lock1) {
-            override fun onSuccess(data: Unit) {
-                statuses["invite"] = "invite"
-                super.onSuccess(data)
-            }
-        })
+        mTestHelper.doSync<Unit> {
+            aliceRoom.invite(bobSession.myUserId, callback = it)
+        }
 
         mTestHelper.await(lock1)
 
-        assertTrue(statuses.containsKey("invite") && statuses.containsKey("onNewRoom"))
-
-        val lock2 = CountDownLatch(2)
+        val lock = CountDownLatch(1)
 
         val roomJoinedObserver = object : Observer<List<RoomSummary>> {
             override fun onChanged(t: List<RoomSummary>?) {
                 if (bobSession.getRoom(aliceRoomId)
                                 ?.getRoomMember(aliceSession.myUserId)
                                 ?.membership == Membership.JOIN) {
-                    statuses["AliceJoin"] = "AliceJoin"
-                    lock2.countDown()
+                    lock.countDown()
                     bobRoomSummariesLive.removeObserver(this)
                 }
             }
@@ -143,19 +124,15 @@ class CryptoTestHelper(val mTestHelper: CommonTestHelper) {
             bobRoomSummariesLive.observeForever(roomJoinedObserver)
         }
 
-        bobSession.joinRoom(aliceRoomId, callback = TestMatrixCallback(lock2))
+        mTestHelper.doSync<Unit> { bobSession.joinRoom(aliceRoomId, callback = it) }
 
-        mTestHelper.await(lock2)
+        mTestHelper.await(lock)
 
         // Ensure bob can send messages to the room
 //        val roomFromBobPOV = bobSession.getRoom(aliceRoomId)!!
 //        assertNotNull(roomFromBobPOV.powerLevels)
 //        assertTrue(roomFromBobPOV.powerLevels.maySendMessage(bobSession.myUserId))
 
-        assertTrue(statuses.toString() + "", statuses.containsKey("AliceJoin"))
-
-//        bobSession.dataHandler.removeListener(bobEventListener)
-
         return CryptoTestData(aliceSession, aliceRoomId, bobSession)
     }
 
@@ -237,7 +214,7 @@ class CryptoTestHelper(val mTestHelper: CommonTestHelper) {
         val roomFromBobPOV = bobSession.getRoom(aliceRoomId)!!
         val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!!
 
-        var lock = CountDownLatch(1)
+        val lock = CountDownLatch(1)
 
         val bobEventsListener = object : Timeline.Listener {
             override fun onTimelineFailure(throwable: Throwable) {
@@ -249,63 +226,35 @@ class CryptoTestHelper(val mTestHelper: CommonTestHelper) {
             }
 
             override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
-                val size = snapshot.filter { it.root.senderId != bobSession.myUserId && it.root.getClearType() == EventType.MESSAGE }
-                        .size
+                val messages = snapshot.filter { it.root.getClearType() == EventType.MESSAGE }
+                        .groupBy { it.root.senderId!! }
 
-                if (size == 3) {
+                // Alice has sent 2 messages and Bob has sent 3 messages
+                if (messages[aliceSession.myUserId]?.size == 2 && messages[bobSession.myUserId]?.size == 3) {
                     lock.countDown()
                 }
             }
         }
 
-        val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(10))
+        val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(20))
+        bobTimeline.start()
         bobTimeline.addListener(bobEventsListener)
 
-        val results = HashMap<String, Any>()
-
-        // bobSession.dataHandler.addListener(object : MXEventListener() {
-        //     override fun onToDeviceEvent(event: Event) {
-        //         results["onToDeviceEvent"] = event
-        //         lock.countDown()
-        //     }
-        // })
-
         // Alice sends a message
         roomFromAlicePOV.sendTextMessage(messagesFromAlice[0])
-        assertTrue(results.containsKey("onToDeviceEvent"))
-//        assertEquals(1, messagesReceivedByBobCount)
 
-        // Bob send a message
-        lock = CountDownLatch(1)
+        // Bob send 3 messages
         roomFromBobPOV.sendTextMessage(messagesFromBob[0])
-        // android does not echo the messages sent from itself
-//        messagesReceivedByBobCount++
-        mTestHelper.await(lock)
-//        assertEquals(2, messagesReceivedByBobCount)
-
-        // Bob send a message
-        lock = CountDownLatch(1)
         roomFromBobPOV.sendTextMessage(messagesFromBob[1])
-        // android does not echo the messages sent from itself
-//        messagesReceivedByBobCount++
-        mTestHelper.await(lock)
-//        assertEquals(3, messagesReceivedByBobCount)
-
-        // Bob send a message
-        lock = CountDownLatch(1)
         roomFromBobPOV.sendTextMessage(messagesFromBob[2])
-        // android does not echo the messages sent from itself
-//        messagesReceivedByBobCount++
-        mTestHelper.await(lock)
-//        assertEquals(4, messagesReceivedByBobCount)
 
         // Alice sends a message
-        lock = CountDownLatch(2)
         roomFromAlicePOV.sendTextMessage(messagesFromAlice[1])
+
         mTestHelper.await(lock)
-//        assertEquals(5, messagesReceivedByBobCount)
 
         bobTimeline.removeListener(bobEventsListener)
+        bobTimeline.dispose()
 
         return cryptoTestData
     }
@@ -340,18 +289,14 @@ class CryptoTestHelper(val mTestHelper: CommonTestHelper) {
     fun createFakeMegolmBackupAuthData(): MegolmBackupAuthData {
         return MegolmBackupAuthData(
                 publicKey = "abcdefg",
-                signatures = HashMap<String, Map<String, String>>().apply {
-                    this["something"] = HashMap<String, String>().apply {
-                        this["ed25519:something"] = "hijklmnop"
-                    }
-                }
+                signatures = mapOf("something" to mapOf("ed25519:something" to "hijklmnop"))
         )
     }
 
     fun createFakeMegolmBackupCreationInfo(): MegolmBackupCreationInfo {
-        return MegolmBackupCreationInfo().apply {
-            algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
-            authData = createFakeMegolmBackupAuthData()
-        }
+        return MegolmBackupCreationInfo(
+                algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP,
+                authData = createFakeMegolmBackupAuthData()
+        )
     }
 }
diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/TestConstants.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/TestConstants.kt
index 60cc87d330..2346898ca7 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/TestConstants.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/common/TestConstants.kt
@@ -22,11 +22,11 @@ object TestConstants {
 
     const val TESTS_HOME_SERVER_URL = "http://10.0.2.2:8080"
 
-    // Time out to use when waiting for server response. 60s
-    private const val AWAIT_TIME_OUT_MILLIS = 60000
+    // Time out to use when waiting for server response. 10s
+    private const val AWAIT_TIME_OUT_MILLIS = 10_000
 
     // Time out to use when waiting for server response, when the debugger is connected. 10 minutes
-    private const val AWAIT_TIME_OUT_WITH_DEBUGGER_MILLIS = 10 * 60000
+    private const val AWAIT_TIME_OUT_WITH_DEBUGGER_MILLIS = 10 * 60_000
 
     const val USER_ALICE = "Alice"
     const val USER_BOB = "Bob"
diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/XSigningTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/XSigningTest.kt
index 069d32acaf..b56ee4a489 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/XSigningTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/crosssigning/XSigningTest.kt
@@ -2,12 +2,10 @@ package im.vector.matrix.android.internal.crypto.crosssigning
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import im.vector.matrix.android.InstrumentedTest
-import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.common.CommonTestHelper
 import im.vector.matrix.android.common.CryptoTestHelper
 import im.vector.matrix.android.common.SessionTestParams
 import im.vector.matrix.android.common.TestConstants
-import im.vector.matrix.android.common.TestMatrixCallback
 import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
 import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
 import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
@@ -21,7 +19,6 @@ import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
-import java.util.concurrent.CountDownLatch
 
 @RunWith(AndroidJUnit4::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -34,14 +31,13 @@ class XSigningTest : InstrumentedTest {
     fun test_InitializeAndStoreKeys() {
         val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
 
-        val aliceLatch = CountDownLatch(1)
-        aliceSession.cryptoService().crossSigningService()
-                .initializeCrossSigning(UserPasswordAuth(
-                        user = aliceSession.myUserId,
-                        password = TestConstants.PASSWORD
-                ), TestMatrixCallback(aliceLatch))
-
-        mTestHelper.await(aliceLatch)
+        mTestHelper.doSync<Unit> {
+            aliceSession.cryptoService().crossSigningService()
+                    .initializeCrossSigning(UserPasswordAuth(
+                            user = aliceSession.myUserId,
+                            password = TestConstants.PASSWORD
+                    ), it)
+        }
 
         val myCrossSigningKeys = aliceSession.cryptoService().crossSigningService().getMyCrossSigningKeys()
         val masterPubKey = myCrossSigningKeys?.masterKey()
@@ -55,7 +51,7 @@ class XSigningTest : InstrumentedTest {
 
         assertTrue("Signing Keys should be trusted", aliceSession.cryptoService().crossSigningService().checkUserTrust(aliceSession.myUserId).isVerified())
 
-        mTestHelper.signout(aliceSession)
+        mTestHelper.signOutAndClose(aliceSession)
     }
 
     @Test
@@ -74,17 +70,11 @@ class XSigningTest : InstrumentedTest {
                 password = TestConstants.PASSWORD
         )
 
-        val latch = CountDownLatch(2)
-
-        aliceSession.cryptoService().crossSigningService().initializeCrossSigning(aliceAuthParams, TestMatrixCallback(latch))
-        bobSession.cryptoService().crossSigningService().initializeCrossSigning(bobAuthParams, TestMatrixCallback(latch))
-
-        mTestHelper.await(latch)
+        mTestHelper.doSync<Unit> { aliceSession.cryptoService().crossSigningService().initializeCrossSigning(aliceAuthParams, it) }
+        mTestHelper.doSync<Unit> { bobSession.cryptoService().crossSigningService().initializeCrossSigning(bobAuthParams, it) }
 
         // Check that alice can see bob keys
-        val downloadLatch = CountDownLatch(1)
-        aliceSession.cryptoService().downloadKeys(listOf(bobSession.myUserId), true, TestMatrixCallback(downloadLatch))
-        mTestHelper.await(downloadLatch)
+        mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> { aliceSession.cryptoService().downloadKeys(listOf(bobSession.myUserId), true, it) }
 
         val bobKeysFromAlicePOV = aliceSession.cryptoService().crossSigningService().getUserCrossSigningKeys(bobSession.myUserId)
         assertNotNull("Alice can see bob Master key", bobKeysFromAlicePOV!!.masterKey())
@@ -96,8 +86,8 @@ class XSigningTest : InstrumentedTest {
 
         assertFalse("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV.isTrusted())
 
-        mTestHelper.signout(aliceSession)
-        mTestHelper.signout(bobSession)
+        mTestHelper.signOutAndClose(aliceSession)
+        mTestHelper.signOutAndClose(bobSession)
     }
 
     @Test
@@ -116,94 +106,56 @@ class XSigningTest : InstrumentedTest {
                 password = TestConstants.PASSWORD
         )
 
-        val latch = CountDownLatch(2)
-
-        aliceSession.cryptoService().crossSigningService().initializeCrossSigning(aliceAuthParams, TestMatrixCallback(latch))
-        bobSession.cryptoService().crossSigningService().initializeCrossSigning(bobAuthParams, TestMatrixCallback(latch))
-
-        mTestHelper.await(latch)
+        mTestHelper.doSync<Unit> { aliceSession.cryptoService().crossSigningService().initializeCrossSigning(aliceAuthParams, it) }
+        mTestHelper.doSync<Unit> { bobSession.cryptoService().crossSigningService().initializeCrossSigning(bobAuthParams, it) }
 
         // Check that alice can see bob keys
-        val downloadLatch = CountDownLatch(1)
         val bobUserId = bobSession.myUserId
-        aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true, TestMatrixCallback(downloadLatch))
-        mTestHelper.await(downloadLatch)
+        mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> { aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true, it) }
 
         val bobKeysFromAlicePOV = aliceSession.cryptoService().crossSigningService().getUserCrossSigningKeys(bobUserId)
         assertTrue("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV?.isTrusted() == false)
 
-        val trustLatch = CountDownLatch(1)
-        aliceSession.cryptoService().crossSigningService().trustUser(bobUserId, object : MatrixCallback<Unit> {
-            override fun onSuccess(data: Unit) {
-                trustLatch.countDown()
-            }
-
-            override fun onFailure(failure: Throwable) {
-                fail("Failed to trust bob")
-            }
-        })
-        mTestHelper.await(trustLatch)
+        mTestHelper.doSync<Unit> { aliceSession.cryptoService().crossSigningService().trustUser(bobUserId, it) }
 
         // Now bobs logs in on a new device and verifies it
         // We will want to test that in alice POV, this new device would be trusted by cross signing
 
         val bobSession2 = mTestHelper.logIntoAccount(bobUserId, SessionTestParams(true))
-        val bobSecondDeviceId = bobSession2.sessionParams.credentials.deviceId
+        val bobSecondDeviceId = bobSession2.sessionParams.credentials.deviceId!!
 
         // Check that bob first session sees the new login
-        val bobKeysLatch = CountDownLatch(1)
-        bobSession.cryptoService().downloadKeys(listOf(bobUserId), true, object : MatrixCallback<MXUsersDevicesMap<CryptoDeviceInfo>> {
-            override fun onFailure(failure: Throwable) {
-                fail("Failed to get device")
-            }
+        val data = mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> {
+            bobSession.cryptoService().downloadKeys(listOf(bobUserId), true, it)
+        }
 
-            override fun onSuccess(data: MXUsersDevicesMap<CryptoDeviceInfo>) {
-                if (data.getUserDeviceIds(bobUserId)?.contains(bobSecondDeviceId!!) == false) {
-                    fail("Bob should see the new device")
-                }
-                bobKeysLatch.countDown()
-            }
-        })
-        mTestHelper.await(bobKeysLatch)
+        if (data.getUserDeviceIds(bobUserId)?.contains(bobSecondDeviceId) == false) {
+            fail("Bob should see the new device")
+        }
 
         val bobSecondDevicePOVFirstDevice = bobSession.cryptoService().getDeviceInfo(bobUserId, bobSecondDeviceId)
         assertNotNull("Bob Second device should be known and persisted from first", bobSecondDevicePOVFirstDevice)
 
         // Manually mark it as trusted from first session
-        val bobSignLatch = CountDownLatch(1)
-        bobSession.cryptoService().crossSigningService().signDevice(bobSecondDeviceId!!, object : MatrixCallback<Unit> {
-            override fun onSuccess(data: Unit) {
-                bobSignLatch.countDown()
-            }
-
-            override fun onFailure(failure: Throwable) {
-                fail("Failed to trust bob ${failure.localizedMessage}")
-            }
-        })
-        mTestHelper.await(bobSignLatch)
+        mTestHelper.doSync<Unit> {
+            bobSession.cryptoService().crossSigningService().signDevice(bobSecondDeviceId, it)
+        }
 
         // Now alice should cross trust bob's second device
-        val aliceKeysLatch = CountDownLatch(1)
-        aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true, object : MatrixCallback<MXUsersDevicesMap<CryptoDeviceInfo>> {
-            override fun onFailure(failure: Throwable) {
-                fail("Failed to get device")
-            }
+        val data2 = mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> {
+            aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true, it)
+        }
 
-            override fun onSuccess(data: MXUsersDevicesMap<CryptoDeviceInfo>) {
-                // check that the device is seen
-                if (data.getUserDeviceIds(bobUserId)?.contains(bobSecondDeviceId) == false) {
-                    fail("Alice should see the new device")
-                }
-                aliceKeysLatch.countDown()
-            }
-        })
-        mTestHelper.await(aliceKeysLatch)
+        // check that the device is seen
+        if (data2.getUserDeviceIds(bobUserId)?.contains(bobSecondDeviceId) == false) {
+            fail("Alice should see the new device")
+        }
 
         val result = aliceSession.cryptoService().crossSigningService().checkDeviceTrust(bobUserId, bobSecondDeviceId, null)
         assertTrue("Bob second device should be trusted from alice POV", result.isCrossSignedVerified())
 
-        mTestHelper.signout(aliceSession)
-        mTestHelper.signout(bobSession)
-        mTestHelper.signout(bobSession2)
+        mTestHelper.signOutAndClose(aliceSession)
+        mTestHelper.signOutAndClose(bobSession)
+        mTestHelper.signOutAndClose(bobSession2)
     }
 }
diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackupTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackupTest.kt
index 2edc0c3976..77ba66d341 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackupTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackupTest.kt
@@ -18,7 +18,6 @@ package im.vector.matrix.android.internal.crypto.keysbackup
 
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import im.vector.matrix.android.InstrumentedTest
-import im.vector.matrix.android.api.MatrixCallback
 import im.vector.matrix.android.api.listeners.ProgressListener
 import im.vector.matrix.android.api.listeners.StepProgressListener
 import im.vector.matrix.android.api.session.Session
@@ -58,7 +57,7 @@ import java.util.Collections
 import java.util.concurrent.CountDownLatch
 
 @RunWith(AndroidJUnit4::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FixMethodOrder(MethodSorters.JVM)
 class KeysBackupTest : InstrumentedTest {
 
     private val mTestHelper = CommonTestHelper(context())
@@ -103,6 +102,8 @@ class KeysBackupTest : InstrumentedTest {
         assertEquals(sessionsCount, sessions3.size)
         assertEquals(sessionsCount, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(false))
         assertEquals(0, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(true))
+
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     /**
@@ -120,31 +121,18 @@ class KeysBackupTest : InstrumentedTest {
 
         assertFalse(keysBackup.isEnabled)
 
-        val latch = CountDownLatch(1)
+        val megolmBackupCreationInfo = mTestHelper.doSync<MegolmBackupCreationInfo> {
+            keysBackup.prepareKeysBackupVersion(null, null, it)
+        }
 
-        keysBackup.prepareKeysBackupVersion(null, null, object : MatrixCallback<MegolmBackupCreationInfo> {
-            override fun onSuccess(data: MegolmBackupCreationInfo) {
-                assertNotNull(data)
-
-                assertEquals(MXCRYPTO_ALGORITHM_MEGOLM_BACKUP, data.algorithm)
-                assertNotNull(data.authData)
-                assertNotNull(data.authData!!.publicKey)
-                assertNotNull(data.authData!!.signatures)
-                assertNotNull(data.recoveryKey)
-
-                latch.countDown()
-            }
-
-            override fun onFailure(failure: Throwable) {
-                fail(failure.localizedMessage)
-
-                latch.countDown()
-            }
-        })
-        mTestHelper.await(latch)
+        assertEquals(MXCRYPTO_ALGORITHM_MEGOLM_BACKUP, megolmBackupCreationInfo.algorithm)
+        assertNotNull(megolmBackupCreationInfo.authData)
+        assertNotNull(megolmBackupCreationInfo.authData!!.publicKey)
+        assertNotNull(megolmBackupCreationInfo.authData!!.signatures)
+        assertNotNull(megolmBackupCreationInfo.recoveryKey)
 
         stateObserver.stopAndCheckStates(null)
-        bobSession.close()
+        mTestHelper.signOutAndClose(bobSession)
     }
 
     /**
@@ -160,45 +148,22 @@ class KeysBackupTest : InstrumentedTest {
 
         assertFalse(keysBackup.isEnabled)
 
-        var megolmBackupCreationInfo: MegolmBackupCreationInfo? = null
-        val latch = CountDownLatch(1)
-        keysBackup.prepareKeysBackupVersion(null, null, object : MatrixCallback<MegolmBackupCreationInfo> {
-            override fun onSuccess(data: MegolmBackupCreationInfo) {
-                megolmBackupCreationInfo = data
-
-                latch.countDown()
-            }
-
-            override fun onFailure(failure: Throwable) {
-                fail(failure.localizedMessage)
-
-                latch.countDown()
-            }
-        })
-        mTestHelper.await(latch)
-
-        assertNotNull(megolmBackupCreationInfo)
+        val megolmBackupCreationInfo = mTestHelper.doSync<MegolmBackupCreationInfo> {
+            keysBackup.prepareKeysBackupVersion(null, null, it)
+        }
 
         assertFalse(keysBackup.isEnabled)
 
-        val latch2 = CountDownLatch(1)
-
         // Create the version
-        keysBackup.createKeysBackupVersion(megolmBackupCreationInfo!!, object : TestMatrixCallback<KeysVersion>(latch2) {
-            override fun onSuccess(data: KeysVersion) {
-                assertNotNull(data)
-                assertNotNull(data.version)
-
-                super.onSuccess(data)
-            }
-        })
-        mTestHelper.await(latch2)
+        mTestHelper.doSync<KeysVersion> {
+            keysBackup.createKeysBackupVersion(megolmBackupCreationInfo, it)
+        }
 
         // Backup must be enable now
         assertTrue(keysBackup.isEnabled)
 
         stateObserver.stopAndCheckStates(null)
-        bobSession.close()
+        mTestHelper.signOutAndClose(bobSession)
     }
 
     /**
@@ -238,7 +203,7 @@ class KeysBackupTest : InstrumentedTest {
                         KeysBackupState.ReadyToBackUp
                 )
         )
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     /**
@@ -259,18 +224,17 @@ class KeysBackupTest : InstrumentedTest {
 
         assertEquals(2, nbOfKeys)
 
-        val latch = CountDownLatch(1)
-
         var lastBackedUpKeysProgress = 0
 
-        keysBackup.backupAllGroupSessions(object : ProgressListener {
-            override fun onProgress(progress: Int, total: Int) {
-                assertEquals(nbOfKeys, total)
-                lastBackedUpKeysProgress = progress
-            }
-        }, TestMatrixCallback(latch))
+        mTestHelper.doSync<Unit> {
+            keysBackup.backupAllGroupSessions(object : ProgressListener {
+                override fun onProgress(progress: Int, total: Int) {
+                    assertEquals(nbOfKeys, total)
+                    lastBackedUpKeysProgress = progress
+                }
+            }, it)
+        }
 
-        mTestHelper.await(latch)
         assertEquals(nbOfKeys, lastBackedUpKeysProgress)
 
         val backedUpKeys = cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(true)
@@ -278,7 +242,7 @@ class KeysBackupTest : InstrumentedTest {
         assertEquals("All keys must have been marked as backed up", nbOfKeys, backedUpKeys)
 
         stateObserver.stopAndCheckStates(null)
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     /**
@@ -321,7 +285,7 @@ class KeysBackupTest : InstrumentedTest {
         assertKeysEquals(session.exportKeys(), sessionData)
 
         stateObserver.stopAndCheckStates(null)
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     /**
@@ -335,25 +299,19 @@ class KeysBackupTest : InstrumentedTest {
         val testData = createKeysBackupScenarioWithPassword(null)
 
         // - Restore the e2e backup from the homeserver
-        val latch2 = CountDownLatch(1)
-        var importRoomKeysResult: ImportRoomKeysResult? = null
-        testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
-                testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey,
-                null,
-                null,
-                null,
-                object : TestMatrixCallback<ImportRoomKeysResult>(latch2) {
-                    override fun onSuccess(data: ImportRoomKeysResult) {
-                        importRoomKeysResult = data
-                        super.onSuccess(data)
-                    }
-                }
-        )
-        mTestHelper.await(latch2)
+        val importRoomKeysResult = mTestHelper.doSync<ImportRoomKeysResult> {
+            testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
+                    testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey,
+                    null,
+                    null,
+                    null,
+                    it
+            )
+        }
 
-        checkRestoreSuccess(testData, importRoomKeysResult!!.totalNumberOfKeys, importRoomKeysResult!!.successfullyNumberOfImportedKeys)
+        checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys)
 
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -370,6 +328,8 @@ class KeysBackupTest : InstrumentedTest {
      */
     @Test
     fun restoreKeysBackupAndKeyShareRequestTest() {
+        fail("Check with Valere for this test. I think we do not send key share request")
+
         val testData = createKeysBackupScenarioWithPassword(null)
 
         // - Check the SDK sent key share requests
@@ -383,23 +343,17 @@ class KeysBackupTest : InstrumentedTest {
         assertTrue(unsentRequest != null || sentRequest != null)
 
         // - Restore the e2e backup from the homeserver
-        val latch2 = CountDownLatch(1)
-        var importRoomKeysResult: ImportRoomKeysResult? = null
-        testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
-                testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey,
-                null,
-                null,
-                null,
-                object : TestMatrixCallback<ImportRoomKeysResult>(latch2) {
-                    override fun onSuccess(data: ImportRoomKeysResult) {
-                        importRoomKeysResult = data
-                        super.onSuccess(data)
-                    }
-                }
-        )
-        mTestHelper.await(latch2)
+        val importRoomKeysResult = mTestHelper.doSync<ImportRoomKeysResult> {
+            testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
+                    testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey,
+                    null,
+                    null,
+                    null,
+                    it
+            )
+        }
 
-        checkRestoreSuccess(testData, importRoomKeysResult!!.totalNumberOfKeys, importRoomKeysResult!!.successfullyNumberOfImportedKeys)
+        checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys)
 
         // - There must be no more pending key share requests
         val unsentRequestAfterRestoration = cryptoStore2
@@ -410,7 +364,7 @@ class KeysBackupTest : InstrumentedTest {
         // Request is either sent or unsent
         assertTrue(unsentRequestAfterRestoration == null && sentRequestAfterRestoration == null)
 
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -437,13 +391,13 @@ class KeysBackupTest : InstrumentedTest {
         assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
 
         // - Trust the backup from the new device
-        val latch = CountDownLatch(1)
-        testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersion(
-                testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
-                true,
-                TestMatrixCallback(latch)
-        )
-        mTestHelper.await(latch)
+        mTestHelper.doSync<Unit> {
+            testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersion(
+                    testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
+                    true,
+                    it
+            )
+        }
 
         // Wait for backup state to be ReadyToBackUp
         waitForKeysBackupToBeInState(testData.aliceSession2, KeysBackupState.ReadyToBackUp)
@@ -453,38 +407,23 @@ class KeysBackupTest : InstrumentedTest {
         assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
 
         // - Retrieve the last version from the server
-        val latch2 = CountDownLatch(1)
-        var keysVersionResult: KeysVersionResult? = null
-        testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(
-                object : TestMatrixCallback<KeysVersionResult?>(latch2) {
-                    override fun onSuccess(data: KeysVersionResult?) {
-                        keysVersionResult = data
-                        super.onSuccess(data)
-                    }
-                }
-        )
-        mTestHelper.await(latch2)
+        val keysVersionResult = mTestHelper.doSync<KeysVersionResult?> {
+            testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(it)
+        }
 
         // - It must be the same
         assertEquals(testData.prepareKeysBackupDataResult.version, keysVersionResult!!.version)
 
-        val latch3 = CountDownLatch(1)
-        var keysBackupVersionTrust: KeysBackupVersionTrust? = null
-        testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult!!,
-                object : TestMatrixCallback<KeysBackupVersionTrust>(latch3) {
-                    override fun onSuccess(data: KeysBackupVersionTrust) {
-                        keysBackupVersionTrust = data
-                        super.onSuccess(data)
-                    }
-                })
-        mTestHelper.await(latch3)
+        val keysBackupVersionTrust = mTestHelper.doSync<KeysBackupVersionTrust> {
+            testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult, it)
+        }
 
         // - It must be trusted and must have 2 signatures now
-        assertTrue(keysBackupVersionTrust!!.usable)
-        assertEquals(2, keysBackupVersionTrust!!.signatures.size)
+        assertTrue(keysBackupVersionTrust.usable)
+        assertEquals(2, keysBackupVersionTrust.signatures.size)
 
         stateObserver.stopAndCheckStates(null)
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -511,13 +450,13 @@ class KeysBackupTest : InstrumentedTest {
         assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
 
         // - Trust the backup from the new device with the recovery key
-        val latch = CountDownLatch(1)
-        testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithRecoveryKey(
-                testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
-                testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey,
-                TestMatrixCallback(latch)
-        )
-        mTestHelper.await(latch)
+        mTestHelper.doSync<Unit> {
+            testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithRecoveryKey(
+                    testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
+                    testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey,
+                    it
+            )
+        }
 
         // Wait for backup state to be ReadyToBackUp
         waitForKeysBackupToBeInState(testData.aliceSession2, KeysBackupState.ReadyToBackUp)
@@ -527,38 +466,23 @@ class KeysBackupTest : InstrumentedTest {
         assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
 
         // - Retrieve the last version from the server
-        val latch2 = CountDownLatch(1)
-        var keysVersionResult: KeysVersionResult? = null
-        testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(
-                object : TestMatrixCallback<KeysVersionResult?>(latch2) {
-                    override fun onSuccess(data: KeysVersionResult?) {
-                        keysVersionResult = data
-                        super.onSuccess(data)
-                    }
-                }
-        )
-        mTestHelper.await(latch2)
+        val keysVersionResult = mTestHelper.doSync<KeysVersionResult?> {
+            testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(it)
+        }
 
         // - It must be the same
         assertEquals(testData.prepareKeysBackupDataResult.version, keysVersionResult!!.version)
 
-        val latch3 = CountDownLatch(1)
-        var keysBackupVersionTrust: KeysBackupVersionTrust? = null
-        testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult!!,
-                object : TestMatrixCallback<KeysBackupVersionTrust>(latch3) {
-                    override fun onSuccess(data: KeysBackupVersionTrust) {
-                        keysBackupVersionTrust = data
-                        super.onSuccess(data)
-                    }
-                })
-        mTestHelper.await(latch3)
+        val keysBackupVersionTrust = mTestHelper.doSync<KeysBackupVersionTrust> {
+            testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult, it)
+        }
 
         // - It must be trusted and must have 2 signatures now
-        assertTrue(keysBackupVersionTrust!!.usable)
-        assertEquals(2, keysBackupVersionTrust!!.signatures.size)
+        assertTrue(keysBackupVersionTrust.usable)
+        assertEquals(2, keysBackupVersionTrust.signatures.size)
 
         stateObserver.stopAndCheckStates(null)
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -597,7 +521,7 @@ class KeysBackupTest : InstrumentedTest {
         assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
 
         stateObserver.stopAndCheckStates(null)
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -626,13 +550,13 @@ class KeysBackupTest : InstrumentedTest {
         assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
 
         // - Trust the backup from the new device with the password
-        val latch = CountDownLatch(1)
-        testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithPassphrase(
-                testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
-                password,
-                TestMatrixCallback(latch)
-        )
-        mTestHelper.await(latch)
+        mTestHelper.doSync<Unit> {
+            testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithPassphrase(
+                    testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
+                    password,
+                    it
+            )
+        }
 
         // Wait for backup state to be ReadyToBackUp
         waitForKeysBackupToBeInState(testData.aliceSession2, KeysBackupState.ReadyToBackUp)
@@ -642,38 +566,23 @@ class KeysBackupTest : InstrumentedTest {
         assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
 
         // - Retrieve the last version from the server
-        val latch2 = CountDownLatch(1)
-        var keysVersionResult: KeysVersionResult? = null
-        testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(
-                object : TestMatrixCallback<KeysVersionResult?>(latch2) {
-                    override fun onSuccess(data: KeysVersionResult?) {
-                        keysVersionResult = data
-                        super.onSuccess(data)
-                    }
-                }
-        )
-        mTestHelper.await(latch2)
+        val keysVersionResult = mTestHelper.doSync<KeysVersionResult?> {
+            testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(it)
+        }
 
         // - It must be the same
         assertEquals(testData.prepareKeysBackupDataResult.version, keysVersionResult!!.version)
 
-        val latch3 = CountDownLatch(1)
-        var keysBackupVersionTrust: KeysBackupVersionTrust? = null
-        testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult!!,
-                object : TestMatrixCallback<KeysBackupVersionTrust>(latch3) {
-                    override fun onSuccess(data: KeysBackupVersionTrust) {
-                        keysBackupVersionTrust = data
-                        super.onSuccess(data)
-                    }
-                })
-        mTestHelper.await(latch3)
+        val keysBackupVersionTrust = mTestHelper.doSync<KeysBackupVersionTrust> {
+            testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult, it)
+        }
 
         // - It must be trusted and must have 2 signatures now
-        assertTrue(keysBackupVersionTrust!!.usable)
-        assertEquals(2, keysBackupVersionTrust!!.signatures.size)
+        assertTrue(keysBackupVersionTrust.usable)
+        assertEquals(2, keysBackupVersionTrust.signatures.size)
 
         stateObserver.stopAndCheckStates(null)
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -715,7 +624,7 @@ class KeysBackupTest : InstrumentedTest {
         assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
 
         stateObserver.stopAndCheckStates(null)
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -748,7 +657,7 @@ class KeysBackupTest : InstrumentedTest {
         // onSuccess may not have been called
         assertNull(importRoomKeysResult)
 
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -764,27 +673,21 @@ class KeysBackupTest : InstrumentedTest {
         val testData = createKeysBackupScenarioWithPassword(password)
 
         // - Restore the e2e backup with the password
-        val latch2 = CountDownLatch(1)
-        var importRoomKeysResult: ImportRoomKeysResult? = null
         val steps = ArrayList<StepProgressListener.Step>()
 
-        testData.aliceSession2.cryptoService().keysBackupService().restoreKeyBackupWithPassword(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
-                password,
-                null,
-                null,
-                object : StepProgressListener {
-                    override fun onStepProgress(step: StepProgressListener.Step) {
-                        steps.add(step)
-                    }
-                },
-                object : TestMatrixCallback<ImportRoomKeysResult>(latch2) {
-                    override fun onSuccess(data: ImportRoomKeysResult) {
-                        importRoomKeysResult = data
-                        super.onSuccess(data)
-                    }
-                }
-        )
-        mTestHelper.await(latch2)
+        val importRoomKeysResult = mTestHelper.doSync<ImportRoomKeysResult> {
+            testData.aliceSession2.cryptoService().keysBackupService().restoreKeyBackupWithPassword(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
+                    password,
+                    null,
+                    null,
+                    object : StepProgressListener {
+                        override fun onStepProgress(step: StepProgressListener.Step) {
+                            steps.add(step)
+                        }
+                    },
+                    it
+            )
+        }
 
         // Check steps
         assertEquals(105, steps.size)
@@ -807,9 +710,9 @@ class KeysBackupTest : InstrumentedTest {
         assertEquals(50, (steps[103] as StepProgressListener.Step.ImportingKey).progress)
         assertEquals(100, (steps[104] as StepProgressListener.Step.ImportingKey).progress)
 
-        checkRestoreSuccess(testData, importRoomKeysResult!!.totalNumberOfKeys, importRoomKeysResult!!.successfullyNumberOfImportedKeys)
+        checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys)
 
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -845,7 +748,7 @@ class KeysBackupTest : InstrumentedTest {
         // onSuccess may not have been called
         assertNull(importRoomKeysResult)
 
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -861,25 +764,19 @@ class KeysBackupTest : InstrumentedTest {
         val testData = createKeysBackupScenarioWithPassword(password)
 
         // - Restore the e2e backup with the recovery key.
-        val latch2 = CountDownLatch(1)
-        var importRoomKeysResult: ImportRoomKeysResult? = null
-        testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
-                testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey,
-                null,
-                null,
-                null,
-                object : TestMatrixCallback<ImportRoomKeysResult>(latch2) {
-                    override fun onSuccess(data: ImportRoomKeysResult) {
-                        importRoomKeysResult = data
-                        super.onSuccess(data)
-                    }
-                }
-        )
-        mTestHelper.await(latch2)
+        val importRoomKeysResult = mTestHelper.doSync<ImportRoomKeysResult> {
+            testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
+                    testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey,
+                    null,
+                    null,
+                    null,
+                    it
+            )
+        }
 
-        checkRestoreSuccess(testData, importRoomKeysResult!!.totalNumberOfKeys, importRoomKeysResult!!.successfullyNumberOfImportedKeys)
+        checkRestoreSuccess(testData, importRoomKeysResult.totalNumberOfKeys, importRoomKeysResult.successfullyNumberOfImportedKeys)
 
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -912,7 +809,7 @@ class KeysBackupTest : InstrumentedTest {
         // onSuccess may not have been called
         assertNull(importRoomKeysResult)
 
-        testData.cryptoTestData.close()
+        testData.cleanUp(mTestHelper)
     }
 
     /**
@@ -932,46 +829,27 @@ class KeysBackupTest : InstrumentedTest {
         prepareAndCreateKeysBackupData(keysBackup)
 
         // Get key backup version from the home server
-        var keysVersionResult: KeysVersionResult? = null
-        val lock = CountDownLatch(1)
-        keysBackup.getCurrentVersion(object : TestMatrixCallback<KeysVersionResult?>(lock) {
-            override fun onSuccess(data: KeysVersionResult?) {
-                keysVersionResult = data
-                super.onSuccess(data)
-            }
-        })
-        mTestHelper.await(lock)
-
-        assertNotNull(keysVersionResult)
+        val keysVersionResult = mTestHelper.doSync<KeysVersionResult?> {
+            keysBackup.getCurrentVersion(it)
+        }
 
         // - Check the returned KeyBackupVersion is trusted
-        val latch = CountDownLatch(1)
-        var keysBackupVersionTrust: KeysBackupVersionTrust? = null
-        keysBackup.getKeysBackupTrust(keysVersionResult!!, object : MatrixCallback<KeysBackupVersionTrust> {
-            override fun onSuccess(data: KeysBackupVersionTrust) {
-                keysBackupVersionTrust = data
-                latch.countDown()
-            }
-
-            override fun onFailure(failure: Throwable) {
-                super.onFailure(failure)
-                latch.countDown()
-            }
-        })
-        mTestHelper.await(latch)
+        val keysBackupVersionTrust = mTestHelper.doSync<KeysBackupVersionTrust> {
+            keysBackup.getKeysBackupTrust(keysVersionResult!!, it)
+        }
 
         assertNotNull(keysBackupVersionTrust)
-        assertTrue(keysBackupVersionTrust!!.usable)
-        assertEquals(1, keysBackupVersionTrust!!.signatures.size)
+        assertTrue(keysBackupVersionTrust.usable)
+        assertEquals(1, keysBackupVersionTrust.signatures.size)
 
-        val signature = keysBackupVersionTrust!!.signatures[0]
+        val signature = keysBackupVersionTrust.signatures[0]
         assertTrue(signature.valid)
         assertNotNull(signature.device)
         assertEquals(cryptoTestData.firstSession.cryptoService().getMyDevice().deviceId, signature.deviceId)
         assertEquals(signature.device!!.deviceId, cryptoTestData.firstSession.sessionParams.credentials.deviceId)
 
         stateObserver.stopAndCheckStates(null)
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     /**
@@ -983,6 +861,7 @@ class KeysBackupTest : InstrumentedTest {
      */
     @Test
     fun testCheckAndStartKeysBackupWhenRestartingAMatrixSession() {
+        fail("This test still fail. To investigate")
         // - Create a backup version
         val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
 
@@ -1000,7 +879,7 @@ class KeysBackupTest : InstrumentedTest {
         // - Log Alice on a new device
         val aliceSession2 = mTestHelper.logIntoAccount(cryptoTestData.firstSession.myUserId, defaultSessionParamsWithInitialSync)
 
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
 
         val keysBackup2 = aliceSession2.cryptoService().keysBackupService()
 
@@ -1012,12 +891,12 @@ class KeysBackupTest : InstrumentedTest {
         keysBackup2.addListener(object : KeysBackupStateListener {
             override fun onStateChange(newState: KeysBackupState) {
                 // Check the backup completes
-                if (keysBackup.state == KeysBackupState.ReadyToBackUp) {
+                if (newState == KeysBackupState.ReadyToBackUp) {
                     count++
 
                     if (count == 2) {
                         // Remove itself from the list of listeners
-                        keysBackup.removeListener(this)
+                        keysBackup2.removeListener(this)
 
                         latch.countDown()
                     }
@@ -1030,7 +909,7 @@ class KeysBackupTest : InstrumentedTest {
 
         stateObserver.stopAndCheckStates(null)
         stateObserver2.stopAndCheckStates(null)
-        aliceSession2.close()
+        mTestHelper.signOutAndClose(aliceSession2)
     }
 
     /**
@@ -1079,21 +958,17 @@ class KeysBackupTest : InstrumentedTest {
         mTestHelper.await(latch0)
 
         // - Create a new backup with fake data on the homeserver, directly using the rest client
-        val latch = CountDownLatch(1)
-
         val megolmBackupCreationInfo = mCryptoTestHelper.createFakeMegolmBackupCreationInfo()
-        (keysBackup as DefaultKeysBackupService).createFakeKeysBackupVersion(megolmBackupCreationInfo, TestMatrixCallback(latch))
-        mTestHelper.await(latch)
+        mTestHelper.doSync<KeysVersion> {
+            (keysBackup as DefaultKeysBackupService).createFakeKeysBackupVersion(megolmBackupCreationInfo, it)
+        }
 
         // Reset the store backup status for keys
         (cryptoTestData.firstSession.cryptoService().keysBackupService() as DefaultKeysBackupService).store.resetBackupMarkers()
 
         // - Make alice back up all her keys again
         val latch2 = CountDownLatch(1)
-        keysBackup.backupAllGroupSessions(object : ProgressListener {
-            override fun onProgress(progress: Int, total: Int) {
-            }
-        }, TestMatrixCallback(latch2, false))
+        keysBackup.backupAllGroupSessions(null, TestMatrixCallback(latch2, false))
         mTestHelper.await(latch2)
 
         // -> That must fail and her backup state must be WrongBackUpVersion
@@ -1101,7 +976,7 @@ class KeysBackupTest : InstrumentedTest {
         assertFalse(keysBackup.isEnabled)
 
         stateObserver.stopAndCheckStates(null)
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     /**
@@ -1129,20 +1004,14 @@ class KeysBackupTest : InstrumentedTest {
         prepareAndCreateKeysBackupData(keysBackup)
 
         // Wait for keys backup to finish by asking again to backup keys.
-        val latch = CountDownLatch(1)
-        keysBackup.backupAllGroupSessions(object : ProgressListener {
-            override fun onProgress(progress: Int, total: Int) {
-            }
-        }, TestMatrixCallback(latch))
-        mTestHelper.await(latch)
+        mTestHelper.doSync<Unit> {
+            keysBackup.backupAllGroupSessions(null, it)
+        }
 
         val oldDeviceId = cryptoTestData.firstSession.sessionParams.credentials.deviceId!!
         val oldKeyBackupVersion = keysBackup.currentBackupVersion
         val aliceUserId = cryptoTestData.firstSession.myUserId
 
-        // Close first Alice session, else they will share the same Crypto store and the test fails.
-        cryptoTestData.firstSession.close()
-
         // - Log Alice on a new device
         val aliceSession2 = mTestHelper.logIntoAccount(aliceUserId, defaultSessionParamsWithInitialSync)
 
@@ -1160,15 +1029,14 @@ class KeysBackupTest : InstrumentedTest {
 
         var isSuccessful = false
         val latch2 = CountDownLatch(1)
-        keysBackup2.backupAllGroupSessions(object : ProgressListener {
-            override fun onProgress(progress: Int, total: Int) {
-            }
-        }, object : TestMatrixCallback<Unit>(latch2, false) {
-            override fun onSuccess(data: Unit) {
-                isSuccessful = true
-                super.onSuccess(data)
-            }
-        })
+        keysBackup2.backupAllGroupSessions(
+                null,
+                object : TestMatrixCallback<Unit>(latch2, false) {
+                    override fun onSuccess(data: Unit) {
+                        isSuccessful = true
+                        super.onSuccess(data)
+                    }
+                })
         mTestHelper.await(latch2)
 
         assertFalse(isSuccessful)
@@ -1178,7 +1046,7 @@ class KeysBackupTest : InstrumentedTest {
         assertFalse(keysBackup2.isEnabled)
 
         // - Validate the old device from the new one
-        aliceSession2.cryptoService().setDeviceVerification(DeviceTrustLevel(false, true), aliceSession2.myUserId, oldDeviceId)
+        aliceSession2.cryptoService().setDeviceVerification(DeviceTrustLevel(crossSigningVerified = false, locallyVerified = true), aliceSession2.myUserId, oldDeviceId)
 
         // -> Backup should automatically enable on the new device
         val latch4 = CountDownLatch(1)
@@ -1198,17 +1066,17 @@ class KeysBackupTest : InstrumentedTest {
         // -> It must use the same backup version
         assertEquals(oldKeyBackupVersion, aliceSession2.cryptoService().keysBackupService().currentBackupVersion)
 
-        val latch5 = CountDownLatch(1)
-        aliceSession2.cryptoService().keysBackupService().backupAllGroupSessions(null, TestMatrixCallback(latch5))
-        mTestHelper.await(latch5)
+        mTestHelper.doSync<Unit> {
+            aliceSession2.cryptoService().keysBackupService().backupAllGroupSessions(null, it)
+        }
 
         // -> It must success
         assertTrue(aliceSession2.cryptoService().keysBackupService().isEnabled)
 
         stateObserver.stopAndCheckStates(null)
         stateObserver2.stopAndCheckStates(null)
-        aliceSession2.close()
-        cryptoTestData.close()
+        mTestHelper.signOutAndClose(aliceSession2)
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     /**
@@ -1230,18 +1098,14 @@ class KeysBackupTest : InstrumentedTest {
 
         assertTrue(keysBackup.isEnabled)
 
-        val latch = CountDownLatch(1)
-
         // Delete the backup
-        keysBackup.deleteBackup(keyBackupCreationInfo.version, TestMatrixCallback(latch))
-
-        mTestHelper.await(latch)
+        mTestHelper.doSync<Unit> { keysBackup.deleteBackup(keyBackupCreationInfo.version, it) }
 
         // Backup is now disabled
         assertFalse(keysBackup.isEnabled)
 
         stateObserver.stopAndCheckStates(null)
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     /* ==========================================================================================
@@ -1280,49 +1144,26 @@ class KeysBackupTest : InstrumentedTest {
                                                password: String? = null): PrepareKeysBackupDataResult {
         val stateObserver = StateObserver(keysBackup)
 
-        var megolmBackupCreationInfo: MegolmBackupCreationInfo? = null
-        val latch = CountDownLatch(1)
-        keysBackup.prepareKeysBackupVersion(password, null, object : MatrixCallback<MegolmBackupCreationInfo> {
-            override fun onSuccess(data: MegolmBackupCreationInfo) {
-                megolmBackupCreationInfo = data
-
-                latch.countDown()
-            }
-
-            override fun onFailure(failure: Throwable) {
-                fail(failure.localizedMessage)
-
-                latch.countDown()
-            }
-        })
-        mTestHelper.await(latch)
+        val megolmBackupCreationInfo = mTestHelper.doSync<MegolmBackupCreationInfo> {
+            keysBackup.prepareKeysBackupVersion(password, null, it)
+        }
 
         assertNotNull(megolmBackupCreationInfo)
 
         assertFalse(keysBackup.isEnabled)
 
-        val latch2 = CountDownLatch(1)
-
         // Create the version
-        var version: String? = null
-        keysBackup.createKeysBackupVersion(megolmBackupCreationInfo!!, object : TestMatrixCallback<KeysVersion>(latch2) {
-            override fun onSuccess(data: KeysVersion) {
-                assertNotNull(data)
-                assertNotNull(data.version)
+        val keysVersion = mTestHelper.doSync<KeysVersion> {
+            keysBackup.createKeysBackupVersion(megolmBackupCreationInfo, it)
+        }
 
-                version = data.version
-
-                super.onSuccess(data)
-            }
-        })
-        mTestHelper.await(latch2)
+        assertNotNull(keysVersion.version)
 
         // Backup must be enable now
         assertTrue(keysBackup.isEnabled)
-        assertNotNull(version)
 
         stateObserver.stopAndCheckStates(null)
-        return PrepareKeysBackupDataResult(megolmBackupCreationInfo!!, version!!)
+        return PrepareKeysBackupDataResult(megolmBackupCreationInfo, keysVersion.version!!)
     }
 
     private fun assertKeysEquals(keys1: MegolmSessionData?, keys2: MegolmSessionData?) {
@@ -1347,7 +1188,12 @@ class KeysBackupTest : InstrumentedTest {
     private data class KeysBackupScenarioData(val cryptoTestData: CryptoTestData,
                                               val aliceKeys: List<OlmInboundGroupSessionWrapper>,
                                               val prepareKeysBackupDataResult: PrepareKeysBackupDataResult,
-                                              val aliceSession2: Session)
+                                              val aliceSession2: Session) {
+        fun cleanUp(testHelper: CommonTestHelper) {
+            cryptoTestData.cleanUp(testHelper)
+            testHelper.signOutAndClose(aliceSession2)
+        }
+    }
 
     /**
      * Common initial condition
@@ -1369,27 +1215,22 @@ class KeysBackupTest : InstrumentedTest {
         // - Do an e2e backup to the homeserver
         val prepareKeysBackupDataResult = prepareAndCreateKeysBackupData(keysBackup, password)
 
-        val latch = CountDownLatch(1)
         var lastProgress = 0
         var lastTotal = 0
-        keysBackup.backupAllGroupSessions(object : ProgressListener {
-            override fun onProgress(progress: Int, total: Int) {
-                lastProgress = progress
-                lastTotal = total
-            }
-        }, TestMatrixCallback(latch))
-        mTestHelper.await(latch)
+        mTestHelper.doSync<Unit> {
+            keysBackup.backupAllGroupSessions(object : ProgressListener {
+                override fun onProgress(progress: Int, total: Int) {
+                    lastProgress = progress
+                    lastTotal = total
+                }
+            }, it)
+        }
 
         assertEquals(2, lastProgress)
         assertEquals(2, lastTotal)
 
         val aliceUserId = cryptoTestData.firstSession.myUserId
 
-        // Logout first Alice session, else they will share the same Crypto store and some tests may fail.
-        val latch2 = CountDownLatch(1)
-        cryptoTestData.firstSession.signOut(true, TestMatrixCallback(latch2))
-        mTestHelper.await(latch2)
-
         // - Log Alice on a new device
         val aliceSession2 = mTestHelper.logIntoAccount(aliceUserId, defaultSessionParamsWithInitialSync)
 
diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/ssss/QuadSTests.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/ssss/QuadSTests.kt
index 7802096338..8dd2109df3 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/ssss/QuadSTests.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/ssss/QuadSTests.kt
@@ -128,7 +128,7 @@ class QuadSTests : InstrumentedTest {
         assertNotNull(defaultKeyAccountData?.content)
         assertEquals("Unexpected default key ${defaultKeyAccountData?.content}", TEST_KEY_ID, defaultKeyAccountData?.content?.get("key"))
 
-        mTestHelper.signout(aliceSession)
+        mTestHelper.signOutAndClose(aliceSession)
     }
 
     @Test
@@ -172,7 +172,7 @@ class QuadSTests : InstrumentedTest {
         }
 
         assertEquals("Secret mismatch", clearSecret, decryptedSecret)
-        mTestHelper.signout(aliceSession)
+        mTestHelper.signOutAndClose(aliceSession)
     }
 
     @Test
@@ -192,7 +192,7 @@ class QuadSTests : InstrumentedTest {
             quadS.setDefaultKey(TEST_KEY_ID, it)
         }
 
-        mTestHelper.signout(aliceSession)
+        mTestHelper.signOutAndClose(aliceSession)
     }
 
     @Test
@@ -239,7 +239,7 @@ class QuadSTests : InstrumentedTest {
             )
         }
 
-        mTestHelper.signout(aliceSession)
+        mTestHelper.signOutAndClose(aliceSession)
     }
 
     @Test
@@ -298,7 +298,7 @@ class QuadSTests : InstrumentedTest {
             )
         }
 
-        mTestHelper.signout(aliceSession)
+        mTestHelper.signOutAndClose(aliceSession)
     }
 
     private fun assertAccountData(session: Session, type: String): UserAccountDataEvent {
diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/SASTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/SASTest.kt
index 7fad87b82d..85fc7e1b36 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/SASTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/SASTest.kt
@@ -132,7 +132,7 @@ class SASTest : InstrumentedTest {
         assertNull(bobVerificationService.getExistingTransaction(aliceSession.myUserId, txID))
         assertNull(aliceVerificationService.getExistingTransaction(bobSession.myUserId, txID))
 
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     @Test
@@ -189,7 +189,7 @@ class SASTest : InstrumentedTest {
 
         assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod, cancelReason)
 
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     @Test
@@ -227,7 +227,7 @@ class SASTest : InstrumentedTest {
         val cancelReq = canceledToDeviceEvent!!.content.toModel<KeyVerificationCancel>()!!
         assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
 
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     @Test
@@ -265,7 +265,7 @@ class SASTest : InstrumentedTest {
         val cancelReq = canceledToDeviceEvent!!.content.toModel<KeyVerificationCancel>()!!
         assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
 
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     private fun fakeBobStart(bobSession: Session,
@@ -334,7 +334,7 @@ class SASTest : InstrumentedTest {
         mTestHelper.await(aliceCreatedLatch)
         mTestHelper.await(aliceCancelledLatch)
 
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     /**
@@ -393,7 +393,7 @@ class SASTest : InstrumentedTest {
             assertTrue("all agreed Short Code should be known by alice", startReq!!.shortAuthenticationStrings!!.contains(it))
         }
 
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     @Test
@@ -449,7 +449,7 @@ class SASTest : InstrumentedTest {
         assertEquals("Should have same SAS", aliceTx.getShortCodeRepresentation(SasMode.DECIMAL),
                 bobTx.getShortCodeRepresentation(SasMode.DECIMAL))
 
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 
     @Test
@@ -514,6 +514,6 @@ class SASTest : InstrumentedTest {
 
         assertTrue("alice device should be verified from bob point of view", aliceDeviceInfoFromBobPOV!!.isVerified)
         assertTrue("bob device should be verified from alice point of view", bobDeviceInfoFromAlicePOV!!.isVerified)
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 }
diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/qrcode/VerificationTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/qrcode/VerificationTest.kt
index d62aef077e..ae8a1ad718 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/qrcode/VerificationTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/qrcode/VerificationTest.kt
@@ -227,6 +227,6 @@ class VerificationTest : InstrumentedTest {
             pr.otherCanScanQrCode() shouldBe expectedResultForBob.otherCanScanQrCode
         }
 
-        cryptoTestData.close()
+        cryptoTestData.cleanUp(mTestHelper)
     }
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/WellKnown.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/WellKnown.kt
index 6285e866cc..bdad4702b7 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/WellKnown.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/auth/data/WellKnown.kt
@@ -46,13 +46,13 @@ import com.squareup.moshi.JsonClass
 @JsonClass(generateAdapter = true)
 data class WellKnown(
         @Json(name = "m.homeserver")
-        var homeServer: WellKnownBaseConfig? = null,
+        val homeServer: WellKnownBaseConfig? = null,
 
         @Json(name = "m.identity_server")
-        var identityServer: WellKnownBaseConfig? = null,
+        val identityServer: WellKnownBaseConfig? = null,
 
         @Json(name = "m.integrations")
-        var integrations: Map<String, @JvmSuppressWildcards Any>? = null
+        val integrations: Map<String, @JvmSuppressWildcards Any>? = null
 ) {
     /**
      * Returns the list of integration managers proposed
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomResponse.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomResponse.kt
index 29c8cb830d..da54b344a2 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomResponse.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/create/CreateRoomResponse.kt
@@ -24,7 +24,7 @@ internal data class CreateRoomResponse(
         /**
          * Required. The created room's ID.
          */
-        @Json(name = "room_id") var roomId: String
+        @Json(name = "room_id") val roomId: String
 )
 
 internal typealias JoinRoomResponse = CreateRoomResponse
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/roomdirectory/PublicRoomsFilter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/roomdirectory/PublicRoomsFilter.kt
index b4de72e41a..c519d054f2 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/roomdirectory/PublicRoomsFilter.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/roomdirectory/PublicRoomsFilter.kt
@@ -27,5 +27,5 @@ data class PublicRoomsFilter(
          * A string to search for in the room metadata, e.g. name, topic, canonical alias etc. (Optional).
          */
         @Json(name = "generic_search_term")
-        var searchTerm: String? = null
+        val searchTerm: String? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/roomdirectory/PublicRoomsParams.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/roomdirectory/PublicRoomsParams.kt
index e2af1c3ccb..467968cd2a 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/roomdirectory/PublicRoomsParams.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/roomdirectory/PublicRoomsParams.kt
@@ -28,30 +28,30 @@ data class PublicRoomsParams(
          * Limit the number of results returned.
          */
         @Json(name = "limit")
-        var limit: Int? = null,
+        val limit: Int? = null,
 
         /**
          * A pagination token from a previous request, allowing clients to get the next (or previous) batch of rooms.
          * The direction of pagination is specified solely by which token is supplied, rather than via an explicit flag.
          */
         @Json(name = "since")
-        var since: String? = null,
+        val since: String? = null,
 
         /**
          * Filter to apply to the results.
          */
         @Json(name = "filter")
-        var filter: PublicRoomsFilter? = null,
+        val filter: PublicRoomsFilter? = null,
 
         /**
          * Whether or not to include all known networks/protocols from application services on the homeserver. Defaults to false.
          */
         @Json(name = "include_all_networks")
-        var includeAllNetworks: Boolean = false,
+        val includeAllNetworks: Boolean = false,
 
         /**
          * The specific third party network/protocol to request from the homeserver. Can only be used if include_all_networks is false.
          */
         @Json(name = "third_party_instance_id")
-        var thirdPartyInstanceId: String? = null
+        val thirdPartyInstanceId: String? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/thirdparty/ThirdPartyProtocol.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/thirdparty/ThirdPartyProtocol.kt
index b066cff164..b4ed1f1a8e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/thirdparty/ThirdPartyProtocol.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/thirdparty/ThirdPartyProtocol.kt
@@ -26,7 +26,7 @@ data class ThirdPartyProtocol(
          * where higher groupings are ordered first. For example, the name of a network should be searched before the nickname of a user.
          */
         @Json(name = "user_fields")
-        var userFields: List<String>? = null,
+        val userFields: List<String>? = null,
 
         /**
          * Required. Fields which may be used to identify a third party location. These should be ordered to suggest the way that
@@ -34,15 +34,15 @@ data class ThirdPartyProtocol(
          * searched before the name of a channel.
          */
         @Json(name = "location_fields")
-        var locationFields: List<String>? = null,
+        val locationFields: List<String>? = null,
 
         /**
          * Required. A content URI representing an icon for the third party protocol.
          *
-         * FIXDOC: This field was not present in legacy Riot, and it is sometimes sent by the server (no not Required?)
+         * FIXDOC: This field was not present in legacy Riot, and it is sometimes sent by the server (so not Required?)
          */
         @Json(name = "icon")
-        var icon: String? = null,
+        val icon: String? = null,
 
         /**
          * Required. The type definitions for the fields defined in the user_fields and location_fields. Each entry in those arrays MUST have an entry here.
@@ -51,12 +51,12 @@ data class ThirdPartyProtocol(
          * May be an empty object if no fields are defined.
          */
         @Json(name = "field_types")
-        var fieldTypes: Map<String, FieldType>? = null,
+        val fieldTypes: Map<String, FieldType>? = null,
 
         /**
          * Required. A list of objects representing independent instances of configuration. For example, multiple networks on IRC
          * if multiple are provided by the same application service.
          */
         @Json(name = "instances")
-        var instances: List<ThirdPartyProtocolInstance>? = null
+        val instances: List<ThirdPartyProtocolInstance>? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/thirdparty/ThirdPartyProtocolInstance.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/thirdparty/ThirdPartyProtocolInstance.kt
index 50f92356fb..f5d59f9282 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/thirdparty/ThirdPartyProtocolInstance.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/thirdparty/ThirdPartyProtocolInstance.kt
@@ -25,35 +25,35 @@ data class ThirdPartyProtocolInstance(
          * Required. A human-readable description for the protocol, such as the name.
          */
         @Json(name = "desc")
-        var desc: String? = null,
+        val desc: String? = null,
 
         /**
          * An optional content URI representing the protocol. Overrides the one provided at the higher level Protocol object.
          */
         @Json(name = "icon")
-        var icon: String? = null,
+        val icon: String? = null,
 
         /**
          * Required. Preset values for fields the client may use to search by.
          */
         @Json(name = "fields")
-        var fields: Map<String, Any>? = null,
+        val fields: Map<String, Any>? = null,
 
         /**
          * Required. A unique identifier across all instances.
          */
         @Json(name = "network_id")
-        var networkId: String? = null,
+        val networkId: String? = null,
 
         /**
          * FIXDOC Not documented on matrix.org doc
          */
         @Json(name = "instance_id")
-        var instanceId: String? = null,
+        val instanceId: String? = null,
 
         /**
          * FIXDOC Not documented on matrix.org doc
          */
         @Json(name = "bot_user_id")
-        var botUserId: String? = null
+        val botUserId: String? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/Timeline.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/Timeline.kt
index 164afb3a60..eb4a9b59e4 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/Timeline.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/Timeline.kt
@@ -41,12 +41,12 @@ interface Timeline {
     fun removeAllListeners()
 
     /**
-     * This should be called before any other method after creating the timeline. It ensures the underlying database is open
+     * This must be called before any other method after creating the timeline. It ensures the underlying database is open
      */
     fun start()
 
     /**
-     * This should be called when you don't need the timeline. It ensures the underlying database get closed.
+     * This must be called when you don't need the timeline. It ensures the underlying database get closed.
      */
     fun dispose()
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/TimelineService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/TimelineService.kt
index 2b23ee40ca..a69127532e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/TimelineService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/timeline/TimelineService.kt
@@ -27,6 +27,9 @@ interface TimelineService {
     /**
      * Instantiate a [Timeline] with an optional initial eventId, to be used with permalink.
      * You can also configure some settings with the [settings] param.
+     *
+     * Important: the returned Timeline has to be started
+     *
      * @param eventId the optional initial eventId.
      * @param settings settings to configure the timeline.
      * @return the instantiated timeline
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/RegistrationFlowResponse.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/RegistrationFlowResponse.kt
index 2d3d25e538..7512454052 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/RegistrationFlowResponse.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/auth/registration/RegistrationFlowResponse.kt
@@ -32,20 +32,20 @@ data class RegistrationFlowResponse(
          * The list of flows.
          */
         @Json(name = "flows")
-        var flows: List<InteractiveAuthenticationFlow>? = null,
+        val flows: List<InteractiveAuthenticationFlow>? = null,
 
         /**
          * The list of stages the client has completed successfully.
          */
         @Json(name = "completed")
-        var completedStages: List<String>? = null,
+        val completedStages: List<String>? = null,
 
         /**
          * The session identifier that the client must pass back to the home server, if one is provided,
          * in subsequent attempts to authenticate in the same API call.
          */
         @Json(name = "session")
-        var session: String? = null,
+        val session: String? = null,
 
         /**
          * The information that the client will need to know in order to use a given type of authentication.
@@ -53,7 +53,7 @@ data class RegistrationFlowResponse(
          * For example, the public key of reCAPTCHA stage could be given here.
          */
         @Json(name = "params")
-        var params: JsonDict? = null
+        val params: JsonDict? = null
 
         /**
          * WARNING,
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt
index c4d115b10c..1db774fd2d 100755
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/DefaultCryptoService.kt
@@ -1021,12 +1021,12 @@ internal class DefaultCryptoService @Inject constructor(
             return
         }
 
-        val requestBody = RoomKeyRequestBody()
-
-        requestBody.roomId = event.roomId
-        requestBody.algorithm = wireContent["algorithm"]?.toString()
-        requestBody.senderKey = wireContent["sender_key"]?.toString()
-        requestBody.sessionId = wireContent["session_id"]?.toString()
+        val requestBody = RoomKeyRequestBody(
+                algorithm = wireContent["algorithm"]?.toString(),
+                roomId = event.roomId,
+                senderKey = wireContent["sender_key"]?.toString(),
+                sessionId = wireContent["session_id"]?.toString()
+        )
 
         outgoingRoomKeyRequestManager.resendRoomKeyRequest(requestBody)
     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequest.kt
index fe1f69f904..39b4678a27 100755
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequest.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequest.kt
@@ -25,54 +25,56 @@ import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyShareRequest
 /**
  * IncomingRoomKeyRequest class defines the incoming room keys request.
  */
-open class IncomingRoomKeyRequest {
-    /**
-     * The user id
-     */
-    var userId: String? = null
+data class IncomingRoomKeyRequest(
+        /**
+         * The user id
+         */
+        override val userId: String? = null,
 
-    /**
-     * The device id
-     */
-    var deviceId: String? = null
+        /**
+         * The device id
+         */
+        override val deviceId: String? = null,
 
-    /**
-     * The request id
-     */
-    var requestId: String? = null
+        /**
+         * The request id
+         */
+        override val requestId: String? = null,
 
-    /**
-     * The request body
-     */
-    var requestBody: RoomKeyRequestBody? = null
+        /**
+         * The request body
+         */
+        val requestBody: RoomKeyRequestBody? = null,
 
-    /**
-     * The runnable to call to accept to share the keys
-     */
-    @Transient
-    var share: Runnable? = null
+        /**
+         * The runnable to call to accept to share the keys
+         */
+        @Transient
+        var share: Runnable? = null,
 
-    /**
-     * The runnable to call to ignore the key share request.
-     */
-    @Transient
-    var ignore: Runnable? = null
-
-    /**
-     * Constructor
-     *
-     * @param event the event
-     */
-    constructor(event: Event) {
-        userId = event.senderId
-        val roomKeyShareRequest = event.getClearContent().toModel<RoomKeyShareRequest>()!!
-        deviceId = roomKeyShareRequest.requestingDeviceId
-        requestId = roomKeyShareRequest.requestId
-        requestBody = if (null != roomKeyShareRequest.body) roomKeyShareRequest.body else RoomKeyRequestBody()
+        /**
+         * The runnable to call to ignore the key share request.
+         */
+        @Transient
+        var ignore: Runnable? = null
+) : IncomingRoomKeyRequestCommon {
+    companion object {
+        /**
+         * Factory
+         *
+         * @param event the event
+         */
+        fun fromEvent(event: Event): IncomingRoomKeyRequest? {
+            return event.getClearContent()
+                    .toModel<RoomKeyShareRequest>()
+                    ?.let {
+                        IncomingRoomKeyRequest(
+                                userId = event.senderId,
+                                deviceId = it.requestingDeviceId,
+                                requestId = it.requestId,
+                                requestBody = it.body ?: RoomKeyRequestBody()
+                        )
+                    }
+        }
     }
-
-    /**
-     * Constructor for object creation from crypto store
-     */
-    constructor()
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestCancellation.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestCancellation.kt
index 0b22a0e28b..6779936f3a 100755
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestCancellation.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestCancellation.kt
@@ -17,13 +17,44 @@
 package im.vector.matrix.android.internal.crypto
 
 import im.vector.matrix.android.api.session.events.model.Event
+import im.vector.matrix.android.api.session.events.model.toModel
+import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyShareCancellation
 
 /**
  * IncomingRoomKeyRequestCancellation describes the incoming room key cancellation.
  */
-class IncomingRoomKeyRequestCancellation(event: Event) : IncomingRoomKeyRequest(event) {
+data class IncomingRoomKeyRequestCancellation(
+        /**
+         * The user id
+         */
+        override val userId: String? = null,
 
-    init {
-        requestBody = null
+        /**
+         * The device id
+         */
+        override val deviceId: String? = null,
+
+        /**
+         * The request id
+         */
+        override val requestId: String? = null
+) : IncomingRoomKeyRequestCommon {
+    companion object {
+        /**
+         * Factory
+         *
+         * @param event the event
+         */
+        fun fromEvent(event: Event): IncomingRoomKeyRequestCancellation? {
+            return event.getClearContent()
+                    .toModel<RoomKeyShareCancellation>()
+                    ?.let {
+                        IncomingRoomKeyRequestCancellation(
+                                userId = event.senderId,
+                                deviceId = it.requestingDeviceId,
+                                requestId = it.requestId
+                        )
+                    }
+        }
     }
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestCommon.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestCommon.kt
new file mode 100644
index 0000000000..a7b1c6b117
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestCommon.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.matrix.android.internal.crypto
+
+interface IncomingRoomKeyRequestCommon {
+    /**
+     * The user id
+     */
+    val userId: String?
+
+    /**
+     * The device id
+     */
+    val deviceId: String?
+
+    /**
+     * The request id
+     */
+    val requestId: String?
+}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt
index 814d9d5a7c..8bad39bd25 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/IncomingRoomKeyRequestManager.kt
@@ -53,8 +53,8 @@ internal class IncomingRoomKeyRequestManager @Inject constructor(
     fun onRoomKeyRequestEvent(event: Event) {
         val roomKeyShare = event.getClearContent().toModel<RoomKeyShare>()
         when (roomKeyShare?.action) {
-            RoomKeyShare.ACTION_SHARE_REQUEST      -> receivedRoomKeyRequests.add(IncomingRoomKeyRequest(event))
-            RoomKeyShare.ACTION_SHARE_CANCELLATION -> receivedRoomKeyRequestCancellations.add(IncomingRoomKeyRequestCancellation(event))
+            RoomKeyShare.ACTION_SHARE_REQUEST      -> IncomingRoomKeyRequest.fromEvent(event)?.let { receivedRoomKeyRequests.add(it) }
+            RoomKeyShare.ACTION_SHARE_CANCELLATION -> IncomingRoomKeyRequestCancellation.fromEvent(event)?.let { receivedRoomKeyRequestCancellations.add(it) }
             else                                   -> Timber.e("## onRoomKeyRequestEvent() : unsupported action ${roomKeyShare?.action}")
         }
     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MegolmSessionData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MegolmSessionData.kt
index 821ed0a553..d6dae1a865 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MegolmSessionData.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MegolmSessionData.kt
@@ -28,46 +28,46 @@ data class MegolmSessionData(
          * The algorithm used.
          */
         @Json(name = "algorithm")
-        var algorithm: String? = null,
+        val algorithm: String? = null,
 
         /**
          * Unique id for the session.
          */
         @Json(name = "session_id")
-        var sessionId: String? = null,
+        val sessionId: String? = null,
 
         /**
          * Sender's Curve25519 device key.
          */
         @Json(name = "sender_key")
-        var senderKey: String? = null,
+        val senderKey: String? = null,
 
         /**
          * Room this session is used in.
          */
         @Json(name = "room_id")
-        var roomId: String? = null,
+        val roomId: String? = null,
 
         /**
          * Base64'ed key data.
          */
         @Json(name = "session_key")
-        var sessionKey: String? = null,
+        val sessionKey: String? = null,
 
         /**
          * Other keys the sender claims.
          */
         @Json(name = "sender_claimed_keys")
-        var senderClaimedKeys: Map<String, String>? = null,
+        val senderClaimedKeys: Map<String, String>? = null,
 
         // This is a shortcut for sender_claimed_keys.get("ed25519")
         // Keep it for compatibility reason.
         @Json(name = "sender_claimed_ed25519_key")
-        var senderClaimedEd25519Key: String? = null,
+        val senderClaimedEd25519Key: String? = null,
 
         /**
          * Devices which forwarded this session to us (normally empty).
          */
         @Json(name = "forwarding_curve25519_key_chain")
-        var forwardingCurve25519KeyChain: List<String>? = null
+        val forwardingCurve25519KeyChain: List<String>? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt
index 5320b84b0e..b59c93ba83 100755
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OutgoingRoomKeyRequestManager.kt
@@ -213,10 +213,11 @@ internal class OutgoingRoomKeyRequestManager @Inject constructor(
         Timber.v("## sendOutgoingRoomKeyRequest() : Requesting keys " + request.requestBody
                 + " from " + request.recipients + " id " + request.requestId)
 
-        val requestMessage = RoomKeyShareRequest()
-        requestMessage.requestingDeviceId = cryptoStore.getDeviceId()
-        requestMessage.requestId = request.requestId
-        requestMessage.body = request.requestBody
+        val requestMessage = RoomKeyShareRequest(
+                requestingDeviceId = cryptoStore.getDeviceId(),
+                requestId = request.requestId,
+                body = request.requestBody
+        )
 
         sendMessageToDevices(requestMessage, request.recipients, request.requestId, object : MatrixCallback<Unit> {
             private fun onDone(state: OutgoingRoomKeyRequest.RequestState) {
@@ -253,9 +254,10 @@ internal class OutgoingRoomKeyRequestManager @Inject constructor(
                 + " to " + request.recipients
                 + " cancellation id  " + request.cancellationTxnId)
 
-        val roomKeyShareCancellation = RoomKeyShareCancellation()
-        roomKeyShareCancellation.requestingDeviceId = cryptoStore.getDeviceId()
-        roomKeyShareCancellation.requestId = request.cancellationTxnId
+        val roomKeyShareCancellation = RoomKeyShareCancellation(
+                requestingDeviceId = cryptoStore.getDeviceId(),
+                requestId = request.cancellationTxnId
+        )
 
         sendMessageToDevices(roomKeyShareCancellation, request.recipients, request.cancellationTxnId, object : MatrixCallback<Unit> {
             private fun onDone() {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt
index ca6cfad0f9..6f41116b90 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MegolmSessionDataImporter.kt
@@ -66,12 +66,12 @@ internal class MegolmSessionDataImporter @Inject constructor(private val olmDevi
                     totalNumbersOfImportedKeys++
 
                     // cancel any outstanding room key requests for this session
-                    val roomKeyRequestBody = RoomKeyRequestBody()
-
-                    roomKeyRequestBody.algorithm = megolmSessionData.algorithm
-                    roomKeyRequestBody.roomId = megolmSessionData.roomId
-                    roomKeyRequestBody.senderKey = megolmSessionData.senderKey
-                    roomKeyRequestBody.sessionId = megolmSessionData.sessionId
+                    val roomKeyRequestBody = RoomKeyRequestBody(
+                            algorithm = megolmSessionData.algorithm,
+                            roomId = megolmSessionData.roomId,
+                            senderKey = megolmSessionData.senderKey,
+                            sessionId = megolmSessionData.sessionId
+                    )
 
                     outgoingRoomKeyRequestManager.cancelRoomKeyRequest(roomKeyRequestBody)
 
@@ -83,7 +83,7 @@ internal class MegolmSessionDataImporter @Inject constructor(private val olmDevi
             }
 
             if (progressListener != null) {
-                val progress = 100 * cpt / totalNumbersOfKeys
+                val progress = 100 * (cpt + 1) / totalNumbersOfKeys
 
                 if (lastProgress != progress) {
                     lastProgress = progress
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt
index 054b38ad06..90100fcc48 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt
@@ -163,12 +163,12 @@ internal class MXMegolmDecryption(private val userId: String,
             recipients.add(senderMap)
         }
 
-        val requestBody = RoomKeyRequestBody()
-
-        requestBody.roomId = event.roomId
-        requestBody.algorithm = encryptedEventContent.algorithm
-        requestBody.senderKey = encryptedEventContent.senderKey
-        requestBody.sessionId = encryptedEventContent.sessionId
+        val requestBody = RoomKeyRequestBody(
+                roomId = event.roomId,
+                algorithm = encryptedEventContent.algorithm,
+                senderKey = encryptedEventContent.senderKey,
+                sessionId = encryptedEventContent.sessionId
+        )
 
         outgoingRoomKeyRequestManager.sendRoomKeyRequest(requestBody, recipients)
     }
@@ -264,12 +264,12 @@ internal class MXMegolmDecryption(private val userId: String,
         if (added) {
             defaultKeysBackupService.maybeBackupKeys()
 
-            val content = RoomKeyRequestBody()
-
-            content.algorithm = roomKeyContent.algorithm
-            content.roomId = roomKeyContent.roomId
-            content.sessionId = roomKeyContent.sessionId
-            content.senderKey = senderKey
+            val content = RoomKeyRequestBody(
+                    algorithm = roomKeyContent.algorithm,
+                    roomId = roomKeyContent.roomId,
+                    sessionId = roomKeyContent.sessionId,
+                    senderKey = senderKey
+            )
 
             outgoingRoomKeyRequestManager.cancelRoomKeyRequest(content)
 
@@ -290,8 +290,8 @@ internal class MXMegolmDecryption(private val userId: String,
 
     override fun hasKeysForKeyRequest(request: IncomingRoomKeyRequest): Boolean {
         val roomId = request.requestBody?.roomId ?: return false
-        val senderKey = request.requestBody?.senderKey ?: return false
-        val sessionId = request.requestBody?.sessionId ?: return false
+        val senderKey = request.requestBody.senderKey ?: return false
+        val sessionId = request.requestBody.sessionId ?: return false
         return olmDevice.hasInboundSessionKeys(roomId, senderKey, sessionId)
     }
 
@@ -319,15 +319,14 @@ internal class MXMegolmDecryption(private val userId: String,
                                 return@mapCatching
                             }
                             Timber.v("## shareKeysWithDevice() : sharing keys for session" +
-                                    " ${body?.senderKey}|${body?.sessionId} with device $userId:$deviceId")
+                                    " ${body.senderKey}|${body.sessionId} with device $userId:$deviceId")
 
                             val payloadJson = mutableMapOf<String, Any>("type" to EventType.FORWARDED_ROOM_KEY)
-                            runCatching { olmDevice.getInboundGroupSession(body?.sessionId, body?.senderKey, body?.roomId) }
+                            runCatching { olmDevice.getInboundGroupSession(body.sessionId, body.senderKey, body.roomId) }
                                     .fold(
                                             {
                                                 // TODO
-                                                payloadJson["content"] = it.exportKeys()
-                                                        ?: ""
+                                                payloadJson["content"] = it.exportKeys() ?: ""
                                             },
                                             {
                                                 // TODO
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt
index 5bc6e2df0f..8fb33731a7 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/crosssigning/ShieldTrustUpdater.kt
@@ -28,6 +28,7 @@ import io.realm.RealmConfiguration
 import kotlinx.coroutines.launch
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.Subscribe
+import java.util.concurrent.atomic.AtomicBoolean
 import java.util.concurrent.atomic.AtomicReference
 import javax.inject.Inject
 
@@ -47,6 +48,8 @@ internal class ShieldTrustUpdater @Inject constructor(
     private val backgroundCryptoRealm = AtomicReference<Realm>()
     private val backgroundSessionRealm = AtomicReference<Realm>()
 
+    private val isStarted = AtomicBoolean()
+
 //    private var cryptoDevicesResult: RealmResults<DeviceInfoEntity>? = null
 
 //    private val cryptoDeviceChangeListener = object : OrderedRealmCollectionChangeListener<RealmResults<DeviceInfoEntity>> {
@@ -57,38 +60,46 @@ internal class ShieldTrustUpdater @Inject constructor(
 //    }
 
     fun start() {
-        eventBus.register(this)
-        BACKGROUND_HANDLER.post {
-            val cryptoRealm = Realm.getInstance(cryptoRealmConfiguration)
-            backgroundCryptoRealm.set(cryptoRealm)
+        if (isStarted.compareAndSet(false, true)) {
+            eventBus.register(this)
+            BACKGROUND_HANDLER.post {
+                val cryptoRealm = Realm.getInstance(cryptoRealmConfiguration)
+                backgroundCryptoRealm.set(cryptoRealm)
 //            cryptoDevicesResult = cryptoRealm.where<DeviceInfoEntity>().findAll()
 //            cryptoDevicesResult?.addChangeListener(cryptoDeviceChangeListener)
 
-            backgroundSessionRealm.set(Realm.getInstance(sessionRealmConfiguration))
+                backgroundSessionRealm.set(Realm.getInstance(sessionRealmConfiguration))
+            }
         }
     }
 
     fun stop() {
-        eventBus.unregister(this)
-        BACKGROUND_HANDLER.post {
-            //            cryptoDevicesResult?.removeAllChangeListeners()
-            backgroundCryptoRealm.getAndSet(null).also {
-                it?.close()
-            }
-            backgroundSessionRealm.getAndSet(null).also {
-                it?.close()
+        if (isStarted.compareAndSet(true, false)) {
+            eventBus.unregister(this)
+            BACKGROUND_HANDLER.post {
+                //            cryptoDevicesResult?.removeAllChangeListeners()
+                backgroundCryptoRealm.getAndSet(null).also {
+                    it?.close()
+                }
+                backgroundSessionRealm.getAndSet(null).also {
+                    it?.close()
+                }
             }
         }
     }
 
     @Subscribe
     fun onRoomMemberChange(update: SessionToCryptoRoomMembersUpdate) {
+        if (!isStarted.get()) {
+            return
+        }
+
         taskExecutor.executorScope.launch {
             val updatedTrust = computeTrustTask.execute(ComputeTrustTask.Params(update.userIds))
             // We need to send that back to session base
 
             BACKGROUND_HANDLER.post {
-                backgroundSessionRealm.get().executeTransaction { realm ->
+                backgroundSessionRealm.get()?.executeTransaction { realm ->
                     roomSummaryUpdater.updateShieldTrust(realm, update.roomId, updatedTrust)
                 }
             }
@@ -97,6 +108,10 @@ internal class ShieldTrustUpdater @Inject constructor(
 
     @Subscribe
     fun onTrustUpdate(update: CryptoToSessionUserTrustChange) {
+        if (!isStarted.get()) {
+            return
+        }
+
         onCryptoDevicesChange(update.userIds)
     }
 
@@ -123,7 +138,7 @@ internal class ShieldTrustUpdater @Inject constructor(
                 taskExecutor.executorScope.launch {
                     val updatedTrust = computeTrustTask.execute(ComputeTrustTask.Params(userList))
                     BACKGROUND_HANDLER.post {
-                        backgroundSessionRealm.get().executeTransaction { realm ->
+                        backgroundSessionRealm.get()?.executeTransaction { realm ->
                             roomSummaryUpdater.updateShieldTrust(realm, roomId, updatedTrust)
                         }
                     }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/DefaultKeysBackupService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/DefaultKeysBackupService.kt
index aa291e8206..3ec5a2f979 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/DefaultKeysBackupService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/DefaultKeysBackupService.kt
@@ -80,6 +80,7 @@ import im.vector.matrix.android.internal.util.JsonCanonicalizer
 import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
 import im.vector.matrix.android.internal.util.awaitCallback
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import org.matrix.olm.OlmException
@@ -167,9 +168,7 @@ internal class DefaultKeysBackupService @Inject constructor(
             runCatching {
                 withContext(coroutineDispatchers.crypto) {
                     val olmPkDecryption = OlmPkDecryption()
-                    val megolmBackupAuthData = MegolmBackupAuthData()
-
-                    if (password != null) {
+                    val megolmBackupAuthData = if (password != null) {
                         // Generate a private key from the password
                         val backgroundProgressListener = if (progressListener == null) {
                             null
@@ -188,25 +187,30 @@ internal class DefaultKeysBackupService @Inject constructor(
                         }
 
                         val generatePrivateKeyResult = generatePrivateKeyWithPassword(password, backgroundProgressListener)
-                        megolmBackupAuthData.publicKey = olmPkDecryption.setPrivateKey(generatePrivateKeyResult.privateKey)
-                        megolmBackupAuthData.privateKeySalt = generatePrivateKeyResult.salt
-                        megolmBackupAuthData.privateKeyIterations = generatePrivateKeyResult.iterations
+                        MegolmBackupAuthData(
+                                publicKey = olmPkDecryption.setPrivateKey(generatePrivateKeyResult.privateKey),
+                                privateKeySalt = generatePrivateKeyResult.salt,
+                                privateKeyIterations = generatePrivateKeyResult.iterations
+                        )
                     } else {
                         val publicKey = olmPkDecryption.generateKey()
 
-                        megolmBackupAuthData.publicKey = publicKey
+                        MegolmBackupAuthData(
+                                publicKey = publicKey
+                        )
                     }
 
                     val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, megolmBackupAuthData.signalableJSONDictionary())
 
-                    megolmBackupAuthData.signatures = objectSigner.signObject(canonicalJson)
+                    val signedMegolmBackupAuthData = megolmBackupAuthData.copy(
+                            signatures = objectSigner.signObject(canonicalJson)
+                    )
 
-                    val megolmBackupCreationInfo = MegolmBackupCreationInfo()
-                    megolmBackupCreationInfo.algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
-                    megolmBackupCreationInfo.authData = megolmBackupAuthData
-                    megolmBackupCreationInfo.recoveryKey = computeRecoveryKey(olmPkDecryption.privateKey())
-
-                    megolmBackupCreationInfo
+                    MegolmBackupCreationInfo(
+                            algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP,
+                            authData = signedMegolmBackupAuthData,
+                            recoveryKey = computeRecoveryKey(olmPkDecryption.privateKey())
+                    )
                 }
             }.foldToCallback(callback)
         }
@@ -214,11 +218,12 @@ internal class DefaultKeysBackupService @Inject constructor(
 
     override fun createKeysBackupVersion(keysBackupCreationInfo: MegolmBackupCreationInfo,
                                          callback: MatrixCallback<KeysVersion>) {
-        val createKeysBackupVersionBody = CreateKeysBackupVersionBody()
-        createKeysBackupVersionBody.algorithm = keysBackupCreationInfo.algorithm
         @Suppress("UNCHECKED_CAST")
-        createKeysBackupVersionBody.authData = MoshiProvider.providesMoshi().adapter(Map::class.java)
-                .fromJson(keysBackupCreationInfo.authData?.toJsonString() ?: "") as JsonDict?
+        val createKeysBackupVersionBody = CreateKeysBackupVersionBody(
+                algorithm = keysBackupCreationInfo.algorithm,
+                authData = MoshiProvider.providesMoshi().adapter(Map::class.java)
+                        .fromJson(keysBackupCreationInfo.authData?.toJsonString() ?: "") as JsonDict?
+        )
 
         keysBackupStateManager.state = KeysBackupState.Enabling
 
@@ -229,14 +234,14 @@ internal class DefaultKeysBackupService @Inject constructor(
                             // Reset backup markers.
                             cryptoStore.resetBackupMarkers()
 
-                            val keyBackupVersion = KeysVersionResult()
-                            keyBackupVersion.algorithm = createKeysBackupVersionBody.algorithm
-                            keyBackupVersion.authData = createKeysBackupVersionBody.authData
-                            keyBackupVersion.version = data.version
-
-                            // We can consider that the server does not have keys yet
-                            keyBackupVersion.count = 0
-                            keyBackupVersion.hash = null
+                            val keyBackupVersion = KeysVersionResult(
+                                    algorithm = createKeysBackupVersionBody.algorithm,
+                                    authData = createKeysBackupVersionBody.authData,
+                                    version = data.version,
+                                    // We can consider that the server does not have keys yet
+                                    count = 0,
+                                    hash = null
+                            )
 
                             enableKeysBackup(keyBackupVersion)
 
@@ -406,7 +411,7 @@ internal class DefaultKeysBackupService @Inject constructor(
             return keysBackupVersionTrust
         }
 
-        val mySigs = authData.signatures?.get(userId)
+        val mySigs = authData.signatures[userId]
         if (mySigs.isNullOrEmpty()) {
             Timber.v("getKeysBackupTrust: Ignoring key backup because it lacks any signatures from this user")
             return keysBackupVersionTrust
@@ -469,8 +474,7 @@ internal class DefaultKeysBackupService @Inject constructor(
             cryptoCoroutineScope.launch(coroutineDispatchers.main) {
                 val updateKeysBackupVersionBody = withContext(coroutineDispatchers.crypto) {
                     // Get current signatures, or create an empty set
-                    val myUserSignatures = authData.signatures?.get(userId)?.toMutableMap()
-                            ?: HashMap()
+                    val myUserSignatures = authData.signatures?.get(userId)?.toMutableMap() ?: HashMap()
 
                     if (trust) {
                         // Add current device signature
@@ -487,24 +491,23 @@ internal class DefaultKeysBackupService @Inject constructor(
                     }
 
                     // Create an updated version of KeysVersionResult
-                    val updateKeysBackupVersionBody = UpdateKeysBackupVersionBody(keysBackupVersion.version!!)
-
-                    updateKeysBackupVersionBody.algorithm = keysBackupVersion.algorithm
-
                     val newMegolmBackupAuthData = authData.copy()
 
                     val newSignatures = newMegolmBackupAuthData.signatures!!.toMutableMap()
                     newSignatures[userId] = myUserSignatures
 
-                    newMegolmBackupAuthData.signatures = newSignatures
+                    val newMegolmBackupAuthDataWithNewSignature = newMegolmBackupAuthData.copy(
+                            signatures = newSignatures
+                    )
 
                     val moshi = MoshiProvider.providesMoshi()
                     val adapter = moshi.adapter(Map::class.java)
 
                     @Suppress("UNCHECKED_CAST")
-                    updateKeysBackupVersionBody.authData = adapter.fromJson(newMegolmBackupAuthData.toJsonString()) as Map<String, Any>?
-
-                    updateKeysBackupVersionBody
+                    UpdateKeysBackupVersionBody(
+                            algorithm = keysBackupVersion.algorithm,
+                            authData = adapter.fromJson(newMegolmBackupAuthDataWithNewSignature.toJsonString()) as Map<String, Any>?,
+                            version = keysBackupVersion.version!!)
                 }
 
                 // And send it to the homeserver
@@ -513,13 +516,13 @@ internal class DefaultKeysBackupService @Inject constructor(
                             this.callback = object : MatrixCallback<Unit> {
                                 override fun onSuccess(data: Unit) {
                                     // Relaunch the state machine on this updated backup version
-                                    val newKeysBackupVersion = KeysVersionResult()
-
-                                    newKeysBackupVersion.version = keysBackupVersion.version
-                                    newKeysBackupVersion.algorithm = keysBackupVersion.algorithm
-                                    newKeysBackupVersion.count = keysBackupVersion.count
-                                    newKeysBackupVersion.hash = keysBackupVersion.hash
-                                    newKeysBackupVersion.authData = updateKeysBackupVersionBody.authData
+                                    val newKeysBackupVersion = KeysVersionResult(
+                                            algorithm = keysBackupVersion.algorithm,
+                                            authData = updateKeysBackupVersionBody.authData,
+                                            version = keysBackupVersion.version,
+                                            hash = keysBackupVersion.hash,
+                                            count = keysBackupVersion.count
+                                    )
 
                                     checkAndStartWithKeysBackupVersion(newKeysBackupVersion)
 
@@ -807,7 +810,10 @@ internal class DefaultKeysBackupService @Inject constructor(
                 // new key is sent
                 val delayInMs = Random.nextLong(KEY_BACKUP_WAITING_TIME_TO_SEND_KEY_BACKUP_MILLIS)
 
-                uiHandler.postDelayed({ backupKeys() }, delayInMs)
+                cryptoCoroutineScope.launch {
+                    delay(delayInMs)
+                    uiHandler.post { backupKeys() }
+                }
             }
             else                                   -> {
                 Timber.v("maybeBackupKeys: Skip it because state: $state")
@@ -1024,7 +1030,7 @@ internal class DefaultKeysBackupService @Inject constructor(
         }
 
         // Extract the recovery key from the passphrase
-        val data = retrievePrivateKeyWithPassword(password, authData.privateKeySalt!!, authData.privateKeyIterations!!, progressListener)
+        val data = retrievePrivateKeyWithPassword(password, authData.privateKeySalt, authData.privateKeyIterations, progressListener)
 
         return computeRecoveryKey(data)
     }
@@ -1178,14 +1184,16 @@ internal class DefaultKeysBackupService @Inject constructor(
 
                 // Gather data to send to the homeserver
                 // roomId -> sessionId -> MXKeyBackupData
-                val keysBackupData = KeysBackupData()
-                keysBackupData.roomIdToRoomKeysBackupData = HashMap()
+                val keysBackupData = KeysBackupData(
+                        roomIdToRoomKeysBackupData = HashMap()
+                )
 
                 for (olmInboundGroupSessionWrapper in olmInboundGroupSessionWrappers) {
                     val keyBackupData = encryptGroupSession(olmInboundGroupSessionWrapper)
                     if (keysBackupData.roomIdToRoomKeysBackupData[olmInboundGroupSessionWrapper.roomId] == null) {
-                        val roomKeysBackupData = RoomKeysBackupData()
-                        roomKeysBackupData.sessionIdToKeyBackupData = HashMap()
+                        val roomKeysBackupData = RoomKeysBackupData(
+                                sessionIdToKeyBackupData = HashMap()
+                        )
                         keysBackupData.roomIdToRoomKeysBackupData[olmInboundGroupSessionWrapper.roomId!!] = roomKeysBackupData
                     }
 
@@ -1301,24 +1309,21 @@ internal class DefaultKeysBackupService @Inject constructor(
         }
 
         // Build backup data for that key
-        val keyBackupData = KeyBackupData()
-        try {
-            keyBackupData.firstMessageIndex = olmInboundGroupSessionWrapper.olmInboundGroupSession!!.firstKnownIndex
-        } catch (e: OlmException) {
-            Timber.e(e, "OlmException")
-        }
+        return KeyBackupData(
+                firstMessageIndex = try {
+                    olmInboundGroupSessionWrapper.olmInboundGroupSession!!.firstKnownIndex
+                } catch (e: OlmException) {
+                    Timber.e(e, "OlmException")
+                    0L
+                },
+                forwardedCount = olmInboundGroupSessionWrapper.forwardingCurve25519KeyChain!!.size,
+                isVerified = device?.isVerified == true,
 
-        keyBackupData.forwardedCount = olmInboundGroupSessionWrapper.forwardingCurve25519KeyChain!!.size
-        keyBackupData.isVerified = device?.isVerified == true
-
-        val data = mapOf(
-                "ciphertext" to encryptedSessionBackupData!!.mCipherText,
-                "mac" to encryptedSessionBackupData.mMac,
-                "ephemeral" to encryptedSessionBackupData.mEphemeralKey)
-
-        keyBackupData.sessionData = data
-
-        return keyBackupData
+                sessionData = mapOf(
+                        "ciphertext" to encryptedSessionBackupData!!.mCipherText,
+                        "mac" to encryptedSessionBackupData.mMac,
+                        "ephemeral" to encryptedSessionBackupData.mEphemeralKey)
+        )
     }
 
     @VisibleForTesting
@@ -1350,8 +1355,10 @@ internal class DefaultKeysBackupService @Inject constructor(
             }
 
             if (sessionBackupData != null) {
-                sessionBackupData.sessionId = sessionId
-                sessionBackupData.roomId = roomId
+                sessionBackupData = sessionBackupData.copy(
+                        sessionId = sessionId,
+                        roomId = roomId
+                )
             }
         }
 
@@ -1370,11 +1377,12 @@ internal class DefaultKeysBackupService @Inject constructor(
     @VisibleForTesting
     fun createFakeKeysBackupVersion(keysBackupCreationInfo: MegolmBackupCreationInfo,
                                     callback: MatrixCallback<KeysVersion>) {
-        val createKeysBackupVersionBody = CreateKeysBackupVersionBody()
-        createKeysBackupVersionBody.algorithm = keysBackupCreationInfo.algorithm
         @Suppress("UNCHECKED_CAST")
-        createKeysBackupVersionBody.authData = MoshiProvider.providesMoshi().adapter(Map::class.java)
-                .fromJson(keysBackupCreationInfo.authData?.toJsonString() ?: "") as JsonDict?
+        val createKeysBackupVersionBody = CreateKeysBackupVersionBody(
+                algorithm = keysBackupCreationInfo.algorithm,
+                authData = MoshiProvider.providesMoshi().adapter(Map::class.java)
+                        .fromJson(keysBackupCreationInfo.authData?.toJsonString() ?: "") as JsonDict?
+        )
 
         createKeysBackupVersionTask
                 .configureWith(createKeysBackupVersionBody) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/MegolmBackupAuthData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/MegolmBackupAuthData.kt
index 442b1f081c..48015a98dd 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/MegolmBackupAuthData.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/MegolmBackupAuthData.kt
@@ -30,26 +30,27 @@ data class MegolmBackupAuthData(
          * The curve25519 public key used to encrypt the backups.
          */
         @Json(name = "public_key")
-        var publicKey: String = "",
+        val publicKey: String = "",
 
         /**
          * In case of a backup created from a password, the salt associated with the backup
          * private key.
          */
         @Json(name = "private_key_salt")
-        var privateKeySalt: String? = null,
+        val privateKeySalt: String? = null,
 
         /**
          * In case of a backup created from a password, the number of key derivations.
          */
         @Json(name = "private_key_iterations")
-        var privateKeyIterations: Int? = null,
+        val privateKeyIterations: Int? = null,
 
         /**
          * Signatures of the public key.
          * userId -> (deviceSignKeyId -> signature)
          */
-        var signatures: Map<String, Map<String, String>>? = null
+        @Json(name = "signatures")
+        val signatures: Map<String, Map<String, String>>? = null
 ) {
 
     fun toJsonString(): String {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/MegolmBackupCreationInfo.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/MegolmBackupCreationInfo.kt
index a08ba9ba96..b329fa44c9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/MegolmBackupCreationInfo.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/MegolmBackupCreationInfo.kt
@@ -19,20 +19,19 @@ package im.vector.matrix.android.internal.crypto.keysbackup.model
 /**
  * Data retrieved from Olm library. algorithm and authData will be send to the homeserver, and recoveryKey will be displayed to the user
  */
-class MegolmBackupCreationInfo {
+data class MegolmBackupCreationInfo(
+        /**
+         * The algorithm used for storing backups [org.matrix.androidsdk.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP].
+         */
+        val algorithm: String = "",
 
-    /**
-     * The algorithm used for storing backups [org.matrix.androidsdk.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP].
-     */
-    var algorithm: String = ""
+        /**
+         * Authentication data.
+         */
+        val authData: MegolmBackupAuthData? = null,
 
-    /**
-     * Authentication data.
-     */
-    var authData: MegolmBackupAuthData? = null
-
-    /**
-     * The Base58 recovery key.
-     */
-    var recoveryKey: String = ""
-}
+        /**
+         * The Base58 recovery key.
+         */
+        val recoveryKey: String = ""
+)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt
index 5efbc6d017..3b267280e5 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt
@@ -16,7 +16,21 @@
 
 package im.vector.matrix.android.internal.crypto.keysbackup.model.rest
 
+import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
+import im.vector.matrix.android.api.util.JsonDict
 
 @JsonClass(generateAdapter = true)
-class CreateKeysBackupVersionBody : KeysAlgorithmAndData()
+data class CreateKeysBackupVersionBody(
+        /**
+         * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
+         */
+        @Json(name = "algorithm")
+        override val algorithm: String? = null,
+
+        /**
+         * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" see [im.vector.matrix.android.internal.crypto.keysbackup.MegolmBackupAuthData]
+         */
+        @Json(name = "auth_data")
+        override val authData: JsonDict? = null
+) : KeysAlgorithmAndData
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeyBackupData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeyBackupData.kt
index f172d45ffd..b2d10687aa 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeyBackupData.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeyBackupData.kt
@@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.crypto.keysbackup.model.rest
 import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
 import im.vector.matrix.android.internal.di.MoshiProvider
+import im.vector.matrix.android.internal.network.parsing.ForceToBoolean
 
 /**
  * Backup data for one key.
@@ -29,25 +30,27 @@ data class KeyBackupData(
          * Required. The index of the first message in the session that the key can decrypt.
          */
         @Json(name = "first_message_index")
-        var firstMessageIndex: Long = 0,
+        val firstMessageIndex: Long = 0,
 
         /**
          * Required. The number of times this key has been forwarded.
          */
         @Json(name = "forwarded_count")
-        var forwardedCount: Int = 0,
+        val forwardedCount: Int = 0,
 
         /**
          * Whether the device backing up the key has verified the device that the key is from.
+         * Force to boolean because of https://github.com/matrix-org/synapse/issues/6977
          */
+        @ForceToBoolean
         @Json(name = "is_verified")
-        var isVerified: Boolean = false,
+        val isVerified: Boolean = false,
 
         /**
          * Algorithm-dependent data.
          */
         @Json(name = "session_data")
-        var sessionData: Map<String, Any>? = null
+        val sessionData: Map<String, Any>? = null
 ) {
 
     fun toJsonString(): String {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt
index 6fba833589..81ca6586a3 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt
@@ -16,7 +16,6 @@
 
 package im.vector.matrix.android.internal.crypto.keysbackup.model.rest
 
-import com.squareup.moshi.Json
 import im.vector.matrix.android.api.util.JsonDict
 import im.vector.matrix.android.internal.crypto.keysbackup.model.MegolmBackupAuthData
 import im.vector.matrix.android.internal.di.MoshiProvider
@@ -38,19 +37,17 @@ import im.vector.matrix.android.internal.di.MoshiProvider
  *     }
  * </pre>
  */
-open class KeysAlgorithmAndData {
+interface KeysAlgorithmAndData {
 
     /**
      * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
      */
-    @Json(name = "algorithm")
-    var algorithm: String? = null
+    val algorithm: String?
 
     /**
      * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" see [im.vector.matrix.android.internal.crypto.keysbackup.MegolmBackupAuthData]
      */
-    @Json(name = "auth_data")
-    var authData: JsonDict? = null
+    val authData: JsonDict?
 
     /**
      * Facility method to convert authData to a MegolmBackupAuthData object
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysBackupData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysBackupData.kt
index 2f4165d8ab..240c79fd1e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysBackupData.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysBackupData.kt
@@ -24,9 +24,7 @@ import com.squareup.moshi.JsonClass
  */
 @JsonClass(generateAdapter = true)
 data class KeysBackupData(
-
         // the keys are the room IDs, and the values are RoomKeysBackupData
         @Json(name = "rooms")
-        var roomIdToRoomKeysBackupData: MutableMap<String, RoomKeysBackupData> = HashMap()
-
+        val roomIdToRoomKeysBackupData: MutableMap<String, RoomKeysBackupData> = HashMap()
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysVersionResult.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysVersionResult.kt
index 4510cdd773..0addd1491e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysVersionResult.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/KeysVersionResult.kt
@@ -16,16 +16,33 @@
 
 package im.vector.matrix.android.internal.crypto.keysbackup.model.rest
 
+import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
+import im.vector.matrix.android.api.util.JsonDict
 
 @JsonClass(generateAdapter = true)
 data class KeysVersionResult(
+        /**
+         * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
+         */
+        @Json(name = "algorithm")
+        override val algorithm: String? = null,
+
+        /**
+         * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" see [im.vector.matrix.android.internal.crypto.keysbackup.MegolmBackupAuthData]
+         */
+        @Json(name = "auth_data")
+        override val authData: JsonDict? = null,
+
         // the backup version
-        var version: String? = null,
+        @Json(name = "version")
+        val version: String? = null,
 
         // The hash value which is an opaque string representing stored keys in the backup
-        var hash: String? = null,
+        @Json(name = "hash")
+        val hash: String? = null,
 
         // The number of keys stored in the backup.
-        var count: Int? = null
-) : KeysAlgorithmAndData()
+        @Json(name = "count")
+        val count: Int? = null
+) : KeysAlgorithmAndData
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/RoomKeysBackupData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/RoomKeysBackupData.kt
index 5d69f63538..f3c218baca 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/RoomKeysBackupData.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/RoomKeysBackupData.kt
@@ -24,8 +24,7 @@ import com.squareup.moshi.JsonClass
  */
 @JsonClass(generateAdapter = true)
 data class RoomKeysBackupData(
-
         // the keys are the session IDs, and the values are KeyBackupData
         @Json(name = "sessions")
-        var sessionIdToKeyBackupData: MutableMap<String, KeyBackupData> = HashMap()
+        val sessionIdToKeyBackupData: MutableMap<String, KeyBackupData> = HashMap()
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt
index cb8ba5e26c..9d88af20ef 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt
@@ -16,10 +16,25 @@
 
 package im.vector.matrix.android.internal.crypto.keysbackup.model.rest
 
+import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
+import im.vector.matrix.android.api.util.JsonDict
 
 @JsonClass(generateAdapter = true)
 data class UpdateKeysBackupVersionBody(
+        /**
+         * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
+         */
+        @Json(name = "algorithm")
+        override val algorithm: String? = null,
+
+        /**
+         * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" see [im.vector.matrix.android.internal.crypto.keysbackup.MegolmBackupAuthData]
+         */
+        @Json(name = "auth_data")
+        override val authData: JsonDict? = null,
+
         // the backup version, mandatory
+        @Json(name = "version")
         val version: String
-) : KeysAlgorithmAndData()
+) : KeysAlgorithmAndData
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/MXDeviceInfo.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/MXDeviceInfo.kt
index cc9b3bff74..ae53694a0f 100755
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/MXDeviceInfo.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/MXDeviceInfo.kt
@@ -26,48 +26,47 @@ import java.io.Serializable
 
 @JsonClass(generateAdapter = true)
 data class MXDeviceInfo(
-
         /**
          * The id of this device.
          */
         @Json(name = "device_id")
-        var deviceId: String,
+        val deviceId: String,
 
         /**
          * the user id
          */
         @Json(name = "user_id")
-        var userId: String,
+        val userId: String,
 
         /**
          * The list of algorithms supported by this device.
          */
         @Json(name = "algorithms")
-        var algorithms: List<String>? = null,
+        val algorithms: List<String>? = null,
 
         /**
          * A map from "<key type>:<deviceId>" to "<base64-encoded key>".
          */
         @Json(name = "keys")
-        var keys: Map<String, String>? = null,
+        val keys: Map<String, String>? = null,
 
         /**
          * The signature of this MXDeviceInfo.
          * A map from "<userId>" to a map from "<key type>:<deviceId>" to "<signature>"
          */
         @Json(name = "signatures")
-        var signatures: Map<String, Map<String, String>>? = null,
+        val signatures: Map<String, Map<String, String>>? = null,
 
         /*
          * Additional data from the home server.
          */
         @Json(name = "unsigned")
-        var unsigned: JsonDict? = null,
+        val unsigned: JsonDict? = null,
 
         /**
          * Verification state of this device.
          */
-        var verified: Int = DEVICE_VERIFICATION_UNKNOWN
+        val verified: Int = DEVICE_VERIFICATION_UNKNOWN
 ) : Serializable {
     /**
      * Tells if the device is unknown
@@ -137,11 +136,11 @@ data class MXDeviceInfo(
         map["user_id"] = userId
 
         if (null != algorithms) {
-            map["algorithms"] = algorithms!!
+            map["algorithms"] = algorithms
         }
 
         if (null != keys) {
-            map["keys"] = keys!!
+            map["keys"] = keys
         }
 
         return map
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/OlmInboundGroupSessionWrapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/OlmInboundGroupSessionWrapper.kt
index 361b8bc205..cf1a3b237a 100755
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/OlmInboundGroupSessionWrapper.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/OlmInboundGroupSessionWrapper.kt
@@ -116,16 +116,16 @@ class OlmInboundGroupSessionWrapper : Serializable {
                 return null
             }
 
-            MegolmSessionData().also {
-                it.senderClaimedEd25519Key = keysClaimed?.get("ed25519")
-                it.forwardingCurve25519KeyChain = ArrayList(forwardingCurve25519KeyChain!!)
-                it.senderKey = senderKey
-                it.senderClaimedKeys = keysClaimed
-                it.roomId = roomId
-                it.sessionId = olmInboundGroupSession!!.sessionIdentifier()
-                it.sessionKey = olmInboundGroupSession!!.export(olmInboundGroupSession!!.firstKnownIndex)
-                it.algorithm = MXCRYPTO_ALGORITHM_MEGOLM
-            }
+            MegolmSessionData(
+                    senderClaimedEd25519Key = keysClaimed?.get("ed25519"),
+                    forwardingCurve25519KeyChain = ArrayList(forwardingCurve25519KeyChain!!),
+                    senderKey = senderKey,
+                    senderClaimedKeys = keysClaimed,
+                    roomId = roomId,
+                    sessionId = olmInboundGroupSession!!.sessionIdentifier(),
+                    sessionKey = olmInboundGroupSession!!.export(olmInboundGroupSession!!.firstKnownIndex),
+                    algorithm = MXCRYPTO_ALGORITHM_MEGOLM
+            )
         } catch (e: Exception) {
             Timber.e(e, "## export() : senderKey $senderKey failed")
             null
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/EncryptionEventContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/EncryptionEventContent.kt
index 6de50f84c2..05e97da68d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/EncryptionEventContent.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/EncryptionEventContent.kt
@@ -23,22 +23,21 @@ import com.squareup.moshi.JsonClass
  */
 @JsonClass(generateAdapter = true)
 data class EncryptionEventContent(
-
         /**
          * Required. The encryption algorithm to be used to encrypt messages sent in this room. Must be 'm.megolm.v1.aes-sha2'.
          */
         @Json(name = "algorithm")
-        var algorithm: String,
+        val algorithm: String,
 
         /**
          * How long the session should be used before changing it. 604800000 (a week) is the recommended default.
          */
         @Json(name = "rotation_period_ms")
-        var rotationPeriodMs: Long? = null,
+        val rotationPeriodMs: Long? = null,
 
         /**
          * How many messages should be sent before changing the session. 100 is the recommended default.
          */
         @Json(name = "rotation_period_msgs")
-        var rotationPeriodMsgs: Long? = null
+        val rotationPeriodMsgs: Long? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/NewDeviceContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/NewDeviceContent.kt
index a6777a4f12..62fe4293e7 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/NewDeviceContent.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/NewDeviceContent.kt
@@ -20,12 +20,11 @@ import com.squareup.moshi.JsonClass
 
 @JsonClass(generateAdapter = true)
 data class NewDeviceContent(
-
         // the device id
         @Json(name = "device_id")
-        var deviceId: String? = null,
+        val deviceId: String? = null,
 
         // the room ids list
         @Json(name = "rooms")
-        var rooms: List<String>? = null
+        val rooms: List<String>? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/OlmEventContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/OlmEventContent.kt
index 7ac0b075be..2b2b49120a 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/OlmEventContent.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/event/OlmEventContent.kt
@@ -27,11 +27,11 @@ data class OlmEventContent(
          *
          */
         @Json(name = "ciphertext")
-        var ciphertext: Map<String, Any>? = null,
+        val ciphertext: Map<String, Any>? = null,
 
         /**
          * the sender key
          */
         @Json(name = "sender_key")
-        var senderKey: String? = null
+        val senderKey: String? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/DeviceInfo.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/DeviceInfo.kt
index 1289ef3d92..b058fac082 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/DeviceInfo.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/DeviceInfo.kt
@@ -30,31 +30,31 @@ data class DeviceInfo(
          * The owner user id (not documented and useless but the homeserver sent it. You should not need it)
          */
         @Json(name = "user_id")
-        var user_id: String? = null,
+        val user_id: String? = null,
 
         /**
          * The device id
          */
         @Json(name = "device_id")
-        var deviceId: String? = null,
+        val deviceId: String? = null,
 
         /**
          * The device display name
          */
         @Json(name = "display_name")
-        var displayName: String? = null,
+        val displayName: String? = null,
 
         /**
          * The last time this device has been seen.
          */
         @Json(name = "last_seen_ts")
-        var lastSeenTs: Long? = null,
+        val lastSeenTs: Long? = null,
 
         /**
          * The last ip address
          */
         @Json(name = "last_seen_ip")
-        var lastSeenIp: String? = null
+        val lastSeenIp: String? = null
 ) : DatedObject {
 
     override val date: Long
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/DevicesListResponse.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/DevicesListResponse.kt
index 9b50b486dc..2bf3d06299 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/DevicesListResponse.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/DevicesListResponse.kt
@@ -24,5 +24,5 @@ import com.squareup.moshi.JsonClass
 @JsonClass(generateAdapter = true)
 data class DevicesListResponse(
         @Json(name = "devices")
-        var devices: List<DeviceInfo>? = null
+        val devices: List<DeviceInfo>? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedFileInfo.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedFileInfo.kt
index 5e09b20c91..93e8b4d211 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedFileInfo.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedFileInfo.kt
@@ -27,38 +27,38 @@ data class EncryptedFileInfo(
          * Required. The URL to the file.
          */
         @Json(name = "url")
-        var url: String? = null,
+        val url: String? = null,
 
         /**
          * Not documented
          */
         @Json(name = "mimetype")
-        var mimetype: String? = null,
+        val mimetype: String? = null,
 
         /**
          * Required. A JSON Web Key object.
          */
         @Json(name = "key")
-        var key: EncryptedFileKey? = null,
+        val key: EncryptedFileKey? = null,
 
         /**
          * Required. The Initialisation Vector used by AES-CTR, encoded as unpadded base64.
          */
         @Json(name = "iv")
-        var iv: String? = null,
+        val iv: String? = null,
 
         /**
          * Required. A map from an algorithm name to a hash of the ciphertext, encoded as unpadded base64.
          * Clients should support the SHA-256 hash, which uses the key "sha256".
          */
         @Json(name = "hashes")
-        var hashes: Map<String, String>? = null,
+        val hashes: Map<String, String>? = null,
 
         /**
          * Required. Version of the encrypted attachments protocol. Must be "v2".
          */
         @Json(name = "v")
-        var v: String? = null
+        val v: String? = null
 ) {
     /**
      * Check what the spec tells us
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedFileKey.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedFileKey.kt
index 799819ceee..fa5885de49 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedFileKey.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedFileKey.kt
@@ -24,31 +24,31 @@ data class EncryptedFileKey(
          * Required. Algorithm. Must be "A256CTR".
          */
         @Json(name = "alg")
-        var alg: String? = null,
+        val alg: String? = null,
 
         /**
          * Required. Extractable. Must be true. This is a W3C extension.
          */
         @Json(name = "ext")
-        var ext: Boolean? = null,
+        val ext: Boolean? = null,
 
         /**
          * Required. Key operations. Must at least contain "encrypt" and "decrypt".
          */
         @Json(name = "key_ops")
-        var key_ops: List<String>? = null,
+        val key_ops: List<String>? = null,
 
         /**
          * Required. Key type. Must be "oct".
          */
         @Json(name = "kty")
-        var kty: String? = null,
+        val kty: String? = null,
 
         /**
          * Required. The key, encoded as urlsafe unpadded base64.
          */
         @Json(name = "k")
-        var k: String? = null
+        val k: String? = null
 ) {
     /**
      * Check what the spec tells us
@@ -62,7 +62,7 @@ data class EncryptedFileKey(
             return false
         }
 
-        if (key_ops?.contains("encrypt") != true || key_ops?.contains("decrypt") != true) {
+        if (key_ops?.contains("encrypt") != true || !key_ops.contains("decrypt")) {
             return false
         }
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedMessage.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedMessage.kt
index c546cd04c4..e3ada0c0ab 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedMessage.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/EncryptedMessage.kt
@@ -21,11 +21,12 @@ import com.squareup.moshi.JsonClass
 
 @JsonClass(generateAdapter = true)
 data class EncryptedMessage(
-        var algorithm: String? = null,
+        @Json(name = "algorithm")
+        val algorithm: String? = null,
 
         @Json(name = "sender_key")
-        var senderKey: String? = null,
+        val senderKey: String? = null,
 
         @Json(name = "ciphertext")
-        var cipherText: Map<String, Any>? = null
+        val cipherText: Map<String, Any>? = null
 ) : SendToDeviceObject
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyChangesResponse.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyChangesResponse.kt
index 12d27a023f..3af7d7c8c5 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyChangesResponse.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyChangesResponse.kt
@@ -25,9 +25,9 @@ import com.squareup.moshi.JsonClass
 internal data class KeyChangesResponse(
         // list of user ids which have new devices
         @Json(name = "changed")
-        var changed: List<String>? = null,
+        val changed: List<String>? = null,
 
         //  List of user ids who are no more tracked.
         @Json(name = "left")
-        var left: List<String>? = null
+        val left: List<String>? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationDone.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationDone.kt
index c0a72d29db..bdce77b31d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationDone.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationDone.kt
@@ -24,7 +24,7 @@ import im.vector.matrix.android.internal.crypto.verification.VerificationInfoDon
  */
 @JsonClass(generateAdapter = true)
 internal data class KeyVerificationDone(
-        @Json(name = "transaction_id") override var transactionID: String? = null
+        @Json(name = "transaction_id") override val transactionID: String? = null
 ) : SendToDeviceObject, VerificationInfoDone {
 
     override fun toSendToDeviceObject() = this
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationRequest.kt
index 5bd09658b5..fcddb5c3d4 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationRequest.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeyVerificationRequest.kt
@@ -27,7 +27,7 @@ internal data class KeyVerificationRequest(
         @Json(name = "from_device") override val fromDevice: String?,
         @Json(name = "methods") override val methods: List<String>,
         @Json(name = "timestamp") override val timestamp: Long?,
-        @Json(name = "transaction_id") override var transactionID: String? = null
+        @Json(name = "transaction_id") override val transactionID: String? = null
 
 ) : SendToDeviceObject, VerificationInfoRequest {
 
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysClaimBody.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysClaimBody.kt
index 38f6615dad..26ee1ebe38 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysClaimBody.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysClaimBody.kt
@@ -24,16 +24,15 @@ import com.squareup.moshi.JsonClass
  */
 @JsonClass(generateAdapter = true)
 internal data class KeysClaimBody(
-
         /**
          * The time (in milliseconds) to wait when downloading keys from remote servers. 10 seconds is the recommended default.
          */
         @Json(name = "timeout")
-        var timeout: Int? = null,
+        val timeout: Int? = null,
 
         /**
          * Required. The keys to be claimed. A map from user ID, to a map from device ID to algorithm name.
          */
         @Json(name = "one_time_keys")
-        var oneTimeKeys: Map<String, Map<String, String>>
+        val oneTimeKeys: Map<String, Map<String, String>>
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysClaimResponse.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysClaimResponse.kt
index 59567ba77a..3483873fbb 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysClaimResponse.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysClaimResponse.kt
@@ -24,11 +24,10 @@ import com.squareup.moshi.JsonClass
  */
 @JsonClass(generateAdapter = true)
 internal data class KeysClaimResponse(
-
         /**
          * The requested keys ordered by device by user.
          * TODO Type does not match spec, should be Map<String, JsonDict>
          */
         @Json(name = "one_time_keys")
-        var oneTimeKeys: Map<String, Map<String, Map<String, Map<String, Any>>>>? = null
+        val oneTimeKeys: Map<String, Map<String, Map<String, Map<String, Any>>>>? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysQueryBody.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysQueryBody.kt
index 3dca696fcd..da2dd781dd 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysQueryBody.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysQueryBody.kt
@@ -25,12 +25,11 @@ import com.squareup.moshi.JsonClass
  */
 @JsonClass(generateAdapter = true)
 internal data class KeysQueryBody(
-
         /**
          * The time (in milliseconds) to wait when downloading keys from remote servers. 10 seconds is the recommended default.
          */
         @Json(name = "timeout")
-        var timeout: Int? = null,
+        val timeout: Int? = null,
 
         /**
          * Required. The keys to be downloaded.
@@ -45,6 +44,5 @@ internal data class KeysQueryBody(
          * by the notification in that sync.
          */
         @Json(name = "token")
-        var token: String? = null
-
+        val token: String? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysUploadResponse.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysUploadResponse.kt
index 38360fa1cd..cd71749acf 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysUploadResponse.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/KeysUploadResponse.kt
@@ -23,13 +23,11 @@ import com.squareup.moshi.JsonClass
  */
 @JsonClass(generateAdapter = true)
 internal data class KeysUploadResponse(
-
         /**
          * The count per algorithm as returned by the home server: a map (algorithm to count).
          */
         @Json(name = "one_time_key_counts")
-        var oneTimeKeyCounts: Map<String, Int>? = null
-
+        val oneTimeKeyCounts: Map<String, Int>? = null
 ) {
     /**
      * Helper methods to extract information from 'oneTimeKeyCounts'
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyRequestBody.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyRequestBody.kt
index 06f70ee25b..3eb6600e5e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyRequestBody.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyRequestBody.kt
@@ -25,14 +25,14 @@ import com.squareup.moshi.JsonClass
 @JsonClass(generateAdapter = true)
 data class RoomKeyRequestBody(
         @Json(name = "algorithm")
-        var algorithm: String? = null,
+        val algorithm: String? = null,
 
         @Json(name = "room_id")
-        var roomId: String? = null,
+        val roomId: String? = null,
 
         @Json(name = "sender_key")
-        var senderKey: String? = null,
+        val senderKey: String? = null,
 
         @Json(name = "session_id")
-        var sessionId: String? = null
+        val sessionId: String? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShare.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShare.kt
index de2345e002..4ea95d84ae 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShare.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShare.kt
@@ -15,21 +15,17 @@
  */
 package im.vector.matrix.android.internal.crypto.model.rest
 
-import com.squareup.moshi.Json
-
 /**
- * Parent class representing an room key action request
+ * Interface representing an room key action request
  * Note: this class cannot be abstract because of [org.matrix.androidsdk.core.JsonUtils.toRoomKeyShare]
  */
-internal open class RoomKeyShare : SendToDeviceObject {
+internal interface RoomKeyShare : SendToDeviceObject {
 
-    var action: String? = null
+    val action: String?
 
-    @Json(name = "requesting_device_id")
-    var requestingDeviceId: String? = null
+    val requestingDeviceId: String?
 
-    @Json(name = "request_id")
-    var requestId: String? = null
+    val requestId: String?
 
     companion object {
         const val ACTION_SHARE_REQUEST = "request"
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShareCancellation.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShareCancellation.kt
index fcfbfccbac..110eed04c1 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShareCancellation.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShareCancellation.kt
@@ -15,14 +15,21 @@
  */
 package im.vector.matrix.android.internal.crypto.model.rest
 
+import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
+import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyShare.Companion.ACTION_SHARE_CANCELLATION
 
 /**
- * Class representing an room key request cancellation content
+ * Class representing a room key request cancellation content
  */
 @JsonClass(generateAdapter = true)
-internal class RoomKeyShareCancellation : RoomKeyShare() {
-    init {
-        action = ACTION_SHARE_CANCELLATION
-    }
-}
+internal data class RoomKeyShareCancellation(
+        @Json(name = "action")
+        override val action: String? = ACTION_SHARE_CANCELLATION,
+
+        @Json(name = "requesting_device_id")
+        override val requestingDeviceId: String? = null,
+
+        @Json(name = "request_id")
+        override val requestId: String? = null
+) : RoomKeyShare
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShareRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShareRequest.kt
index 3b9d210812..d92bc03aab 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShareRequest.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/RoomKeyShareRequest.kt
@@ -16,16 +16,23 @@
  */
 package im.vector.matrix.android.internal.crypto.model.rest
 
+import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
 
 /**
- * Class representing an room key request content
+ * Class representing a room key request content
  */
 @JsonClass(generateAdapter = true)
-internal class RoomKeyShareRequest : RoomKeyShare() {
-    var body: RoomKeyRequestBody? = null
+internal data class RoomKeyShareRequest(
+        @Json(name = "action")
+        override val action: String? = RoomKeyShare.ACTION_SHARE_REQUEST,
 
-    init {
-        action = ACTION_SHARE_REQUEST
-    }
-}
+        @Json(name = "requesting_device_id")
+        override val requestingDeviceId: String? = null,
+
+        @Json(name = "request_id")
+        override val requestId: String? = null,
+
+        @Json(name = "body")
+        val body: RoomKeyRequestBody? = null
+) : RoomKeyShare
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/UpdateDeviceInfoBody.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/UpdateDeviceInfoBody.kt
index f2ea24a960..8ae373ba8c 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/UpdateDeviceInfoBody.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/model/rest/UpdateDeviceInfoBody.kt
@@ -25,5 +25,5 @@ internal data class UpdateDeviceInfoBody(
          * The new display name for this device. If not given, the display name is unchanged.
          */
         @Json(name = "display_name")
-        var displayName: String? = null
+        val displayName: String? = null
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt
index 3a12df2cd7..7262eb5bb1 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/IMXCryptoStore.kt
@@ -20,6 +20,7 @@ package im.vector.matrix.android.internal.crypto.store
 import androidx.lifecycle.LiveData
 import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo
 import im.vector.matrix.android.api.util.Optional
+import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequestCommon
 import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequest
 import im.vector.matrix.android.internal.crypto.NewSessionListener
 import im.vector.matrix.android.internal.crypto.OutgoingRoomKeyRequest
@@ -382,7 +383,7 @@ internal interface IMXCryptoStore {
      *
      * @param incomingRoomKeyRequest the incoming key request
      */
-    fun deleteIncomingRoomKeyRequest(incomingRoomKeyRequest: IncomingRoomKeyRequest)
+    fun deleteIncomingRoomKeyRequest(incomingRoomKeyRequest: IncomingRoomKeyRequestCommon)
 
     /**
      * Search an IncomingRoomKeyRequest
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt
index 00a496cae4..8552868252 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/RealmCryptoStore.kt
@@ -23,6 +23,7 @@ import im.vector.matrix.android.api.auth.data.Credentials
 import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo
 import im.vector.matrix.android.api.util.Optional
 import im.vector.matrix.android.api.util.toOptional
+import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequestCommon
 import im.vector.matrix.android.internal.crypto.IncomingRoomKeyRequest
 import im.vector.matrix.android.internal.crypto.NewSessionListener
 import im.vector.matrix.android.internal.crypto.OutgoingRoomKeyRequest
@@ -888,7 +889,7 @@ internal class RealmCryptoStore @Inject constructor(
         }
     }
 
-    override fun deleteIncomingRoomKeyRequest(incomingRoomKeyRequest: IncomingRoomKeyRequest) {
+    override fun deleteIncomingRoomKeyRequest(incomingRoomKeyRequest: IncomingRoomKeyRequestCommon) {
         doRealmTransaction(realmConfiguration) {
             it.where<IncomingRoomKeyRequestEntity>()
                     .equalTo(IncomingRoomKeyRequestEntityFields.USER_ID, incomingRoomKeyRequest.userId)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/model/IncomingRoomKeyRequestEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/model/IncomingRoomKeyRequestEntity.kt
index 9b1d116aa9..38cece99ac 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/model/IncomingRoomKeyRequestEntity.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/model/IncomingRoomKeyRequestEntity.kt
@@ -32,17 +32,17 @@ internal open class IncomingRoomKeyRequestEntity(
 ) : RealmObject() {
 
     fun toIncomingRoomKeyRequest(): IncomingRoomKeyRequest {
-        return IncomingRoomKeyRequest().also {
-            it.requestId = requestId
-            it.userId = userId
-            it.deviceId = deviceId
-            it.requestBody = RoomKeyRequestBody().apply {
-                algorithm = requestBodyAlgorithm
-                roomId = requestBodyRoomId
-                senderKey = requestBodySenderKey
-                sessionId = requestBodySessionId
-            }
-        }
+        return IncomingRoomKeyRequest(
+                requestId = requestId,
+                userId = userId,
+                deviceId = deviceId,
+                requestBody = RoomKeyRequestBody(
+                        algorithm = requestBodyAlgorithm,
+                        roomId = requestBodyRoomId,
+                        senderKey = requestBodySenderKey,
+                        sessionId = requestBodySessionId
+                )
+        )
     }
 
     fun putRequestBody(requestBody: RoomKeyRequestBody?) {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/model/OutgoingRoomKeyRequestEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/model/OutgoingRoomKeyRequestEntity.kt
index 3130bd2f89..86fc177f2b 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/model/OutgoingRoomKeyRequestEntity.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/store/db/model/OutgoingRoomKeyRequestEntity.kt
@@ -43,12 +43,12 @@ internal open class OutgoingRoomKeyRequestEntity(
     fun toOutgoingRoomKeyRequest(): OutgoingRoomKeyRequest {
         val cancellationTxnId = this.cancellationTxnId
         return OutgoingRoomKeyRequest(
-                RoomKeyRequestBody().apply {
-                    algorithm = requestBodyAlgorithm
-                    roomId = requestBodyRoomId
-                    senderKey = requestBodySenderKey
-                    sessionId = requestBodySessionId
-                },
+                RoomKeyRequestBody(
+                        algorithm = requestBodyAlgorithm,
+                        roomId = requestBodyRoomId,
+                        senderKey = requestBodySenderKey,
+                        sessionId = requestBodySessionId
+                ),
                 getRecipients()!!,
                 requestId!!,
                 OutgoingRoomKeyRequest.RequestState.from(state)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt
index 2e11bb1b3e..94fe3c1e8d 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/tasks/DownloadKeysForUsersTask.kt
@@ -29,7 +29,8 @@ internal interface DownloadKeysForUsersTask : Task<DownloadKeysForUsersTask.Para
             // the list of users to get keys for.
             val userIds: List<String>?,
             // the up-to token
-            val token: String?)
+            val token: String?
+    )
 }
 
 internal class DefaultDownloadKeysForUsers @Inject constructor(
@@ -41,13 +42,10 @@ internal class DefaultDownloadKeysForUsers @Inject constructor(
         val downloadQuery = params.userIds?.associateWith { emptyMap<String, Any>() }.orEmpty()
 
         val body = KeysQueryBody(
-                deviceKeys = downloadQuery
+                deviceKeys = downloadQuery,
+                token = params.token?.takeIf { it.isNotEmpty() }
         )
 
-        if (!params.token.isNullOrEmpty()) {
-            body.token = params.token
-        }
-
         return executeRequest(eventBus) {
             apiCall = cryptoApi.downloadKeysForUsers(body)
         }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt
index cd4e9abbc1..3164bf75c0 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt
@@ -17,7 +17,21 @@
 package im.vector.matrix.android.internal.di
 
 import com.squareup.moshi.Moshi
-import im.vector.matrix.android.api.session.room.model.message.*
+import im.vector.matrix.android.api.session.room.model.message.MessageAudioContent
+import im.vector.matrix.android.api.session.room.model.message.MessageContent
+import im.vector.matrix.android.api.session.room.model.message.MessageDefaultContent
+import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent
+import im.vector.matrix.android.api.session.room.model.message.MessageFileContent
+import im.vector.matrix.android.api.session.room.model.message.MessageImageContent
+import im.vector.matrix.android.api.session.room.model.message.MessageLocationContent
+import im.vector.matrix.android.api.session.room.model.message.MessageNoticeContent
+import im.vector.matrix.android.api.session.room.model.message.MessageOptionsContent
+import im.vector.matrix.android.api.session.room.model.message.MessagePollResponseContent
+import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
+import im.vector.matrix.android.api.session.room.model.message.MessageType
+import im.vector.matrix.android.api.session.room.model.message.MessageVerificationRequestContent
+import im.vector.matrix.android.api.session.room.model.message.MessageVideoContent
+import im.vector.matrix.android.internal.network.parsing.ForceToBooleanJsonAdapter
 import im.vector.matrix.android.internal.network.parsing.RuntimeJsonAdapterFactory
 import im.vector.matrix.android.internal.network.parsing.UriMoshiAdapter
 import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
@@ -31,6 +45,7 @@ object MoshiProvider {
 
     private val moshi: Moshi = Moshi.Builder()
             .add(UriMoshiAdapter())
+            .add(ForceToBooleanJsonAdapter())
             .add(RuntimeJsonAdapterFactory.of(UserAccountData::class.java, "type", UserAccountDataEvent::class.java)
                     .registerSubtype(UserAccountDataDirectMessages::class.java, UserAccountData.TYPE_DIRECT_MESSAGES)
                     .registerSubtype(UserAccountDataIgnoredUsers::class.java, UserAccountData.TYPE_IGNORED_USER_LIST)
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/parsing/ForceToBoolean.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/parsing/ForceToBoolean.kt
new file mode 100644
index 0000000000..b823104b4d
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/parsing/ForceToBoolean.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.matrix.android.internal.network.parsing
+
+import com.squareup.moshi.FromJson
+import com.squareup.moshi.JsonQualifier
+import com.squareup.moshi.JsonReader
+import com.squareup.moshi.ToJson
+import timber.log.Timber
+
+@JsonQualifier
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION)
+annotation class ForceToBoolean
+
+internal class ForceToBooleanJsonAdapter {
+    @ToJson
+    fun toJson(@ForceToBoolean b: Boolean): Boolean {
+        return b
+    }
+
+    @FromJson
+    @ForceToBoolean
+    fun fromJson(reader: JsonReader): Boolean {
+        return when (val token = reader.peek()) {
+            JsonReader.Token.NUMBER  -> reader.nextInt() != 0
+            JsonReader.Token.BOOLEAN -> reader.nextBoolean()
+            else                     -> {
+                Timber.e("Expecting a boolean or a int but get: $token")
+                reader.skipValue()
+                false
+            }
+        }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
index e7cb963c5f..c4ddaec98e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/DefaultSession.kt
@@ -217,4 +217,9 @@ internal class DefaultSession @Inject constructor(
     override fun removeListener(listener: Session.Listener) {
         sessionListeners.removeListener(listener)
     }
+
+    // For easy debugging
+    override fun toString(): String {
+        return "$myUserId - ${sessionParams.credentials.deviceId}"
+    }
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/Filter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/Filter.kt
index 9acdacd897..fc0472e32f 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/Filter.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/Filter.kt
@@ -24,13 +24,13 @@ import com.squareup.moshi.JsonClass
  */
 @JsonClass(generateAdapter = true)
 data class Filter(
-        @Json(name = "limit") var limit: Int? = null,
-        @Json(name = "senders") var senders: MutableList<String>? = null,
-        @Json(name = "not_senders") var notSenders: MutableList<String>? = null,
-        @Json(name = "types") var types: MutableList<String>? = null,
-        @Json(name = "not_types") var notTypes: MutableList<String>? = null,
-        @Json(name = "rooms") var rooms: MutableList<String>? = null,
-        @Json(name = "not_rooms") var notRooms: MutableList<String>? = null
+        @Json(name = "limit") val limit: Int? = null,
+        @Json(name = "senders") val senders: List<String>? = null,
+        @Json(name = "not_senders") val notSenders: List<String>? = null,
+        @Json(name = "types") val types: List<String>? = null,
+        @Json(name = "not_types") val notTypes: List<String>? = null,
+        @Json(name = "rooms") val rooms: List<String>? = null,
+        @Json(name = "not_rooms") val notRooms: List<String>? = null
 ) {
     fun hasData(): Boolean {
         return (limit != null
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterBody.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterBody.kt
index fa66470c9b..535c66f637 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterBody.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterBody.kt
@@ -26,11 +26,11 @@ import im.vector.matrix.android.internal.di.MoshiProvider
  */
 @JsonClass(generateAdapter = true)
 internal data class FilterBody(
-        @Json(name = "event_fields") var eventFields: List<String>? = null,
-        @Json(name = "event_format") var eventFormat: String? = null,
-        @Json(name = "presence") var presence: Filter? = null,
-        @Json(name = "account_data") var accountData: Filter? = null,
-        @Json(name = "room") var room: RoomFilter? = null
+        @Json(name = "event_fields") val eventFields: List<String>? = null,
+        @Json(name = "event_format") val eventFormat: String? = null,
+        @Json(name = "presence") val presence: Filter? = null,
+        @Json(name = "account_data") val accountData: Filter? = null,
+        @Json(name = "room") val room: RoomFilter? = null
 ) {
 
     fun toJSONString(): String {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterFactory.kt
index 86c94d3dfa..a070759de9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterFactory.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterFactory.kt
@@ -21,32 +21,30 @@ import im.vector.matrix.android.api.session.events.model.EventType
 internal object FilterFactory {
 
     fun createDefaultFilterBody(): FilterBody {
-        val filterBody = FilterBody()
-        FilterUtil.enableLazyLoading(filterBody, true)
-        return filterBody
+        return FilterUtil.enableLazyLoading(FilterBody(), true)
     }
 
     fun createRiotFilterBody(): FilterBody {
-        val filterBody = FilterBody()
-        filterBody.room = RoomFilter().apply {
-            timeline = createRiotTimelineFilter()
-            state = createRiotStateFilter()
-        }
-        return filterBody
+        return FilterBody(
+                room = RoomFilter(
+                        timeline = createRiotTimelineFilter(),
+                        state = createRiotStateFilter()
+                )
+        )
     }
 
     fun createDefaultRoomFilter(): RoomEventFilter {
-        return RoomEventFilter().apply {
-            lazyLoadMembers = true
-        }
+        return RoomEventFilter(
+                lazyLoadMembers = true
+        )
     }
 
     fun createRiotRoomFilter(): RoomEventFilter {
-        return RoomEventFilter().apply {
-            lazyLoadMembers = true
-            // TODO Enable this for optimization
-            // types = (listOfSupportedEventTypes + listOfSupportedStateEventTypes).toMutableList()
-        }
+        return RoomEventFilter(
+                lazyLoadMembers = true
+                // TODO Enable this for optimization
+                // types = (listOfSupportedEventTypes + listOfSupportedStateEventTypes).toMutableList()
+        )
     }
 
     private fun createRiotTimelineFilter(): RoomEventFilter {
@@ -57,9 +55,9 @@ internal object FilterFactory {
     }
 
     private fun createRiotStateFilter(): RoomEventFilter {
-        return RoomEventFilter().apply {
-            lazyLoadMembers = true
-        }
+        return RoomEventFilter(
+                lazyLoadMembers = true
+        )
     }
 
     // Get only managed types by Riot
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterResponse.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterResponse.kt
index b27ddae9d3..75e2c23da9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterResponse.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterResponse.kt
@@ -24,5 +24,5 @@ import com.squareup.moshi.JsonClass
  */
 @JsonClass(generateAdapter = true)
 data class FilterResponse(
-        @Json(name = "filter_id") var filterId: String
+        @Json(name = "filter_id") val filterId: String
 )
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterUtil.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterUtil.kt
index d3020b3fa6..3f4e61e6b5 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterUtil.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/FilterUtil.kt
@@ -21,7 +21,6 @@ internal object FilterUtil {
     /**
      * Patch the filterBody to enable or disable the data save mode
      *
-     *
      * If data save mode is on, FilterBody will contains
      * FIXME New expected filter:
      * "{\"room\": {\"ephemeral\": {\"notTypes\": [\"m.typing\"]}}, \"presence\":{\"notTypes\": [\"*\"]}}"
@@ -29,6 +28,7 @@ internal object FilterUtil {
      * @param filterBody      filterBody to patch
      * @param useDataSaveMode true to enable data save mode
      */
+    /*
     fun enableDataSaveMode(filterBody: FilterBody, useDataSaveMode: Boolean) {
         if (useDataSaveMode) {
             // Enable data save mode
@@ -78,10 +78,10 @@ internal object FilterUtil {
                 filterBody.presence = null
             }
         }
-    }
+    } */
 
     /**
-     * Patch the filterBody to enable or disable the lazy loading
+     * Compute a new filterBody to enable or disable the lazy loading
      *
      *
      * If lazy loading is on, the filterBody will looks like
@@ -90,29 +90,23 @@ internal object FilterUtil {
      * @param filterBody     filterBody to patch
      * @param useLazyLoading true to enable lazy loading
      */
-    fun enableLazyLoading(filterBody: FilterBody, useLazyLoading: Boolean) {
+    fun enableLazyLoading(filterBody: FilterBody, useLazyLoading: Boolean): FilterBody {
         if (useLazyLoading) {
             // Enable lazy loading
-            if (filterBody.room == null) {
-                filterBody.room = RoomFilter()
-            }
-            if (filterBody.room!!.state == null) {
-                filterBody.room!!.state = RoomEventFilter()
-            }
-
-            filterBody.room!!.state!!.lazyLoadMembers = true
+            return filterBody.copy(
+                    room = filterBody.room?.copy(
+                            state = filterBody.room.state?.copy(lazyLoadMembers = true)
+                                    ?: RoomEventFilter(lazyLoadMembers = true)
+                    )
+                            ?: RoomFilter(state = RoomEventFilter(lazyLoadMembers = true))
+            )
         } else {
-            if (filterBody.room != null && filterBody.room!!.state != null) {
-                filterBody.room!!.state!!.lazyLoadMembers = null
+            val newRoomEventFilter = filterBody.room?.state?.copy(lazyLoadMembers = null)?.takeIf { it.hasData() }
+            val newRoomFilter = filterBody.room?.copy(state = newRoomEventFilter)?.takeIf { it.hasData() }
 
-                if (!filterBody.room!!.state!!.hasData()) {
-                    filterBody.room!!.state = null
-                }
-
-                if (!filterBody.room!!.hasData()) {
-                    filterBody.room = null
-                }
-            }
+            return filterBody.copy(
+                    room = newRoomFilter
+            )
         }
     }
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/RoomEventFilter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/RoomEventFilter.kt
index ee81e399ee..9cdccc5c8b 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/RoomEventFilter.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/RoomEventFilter.kt
@@ -26,14 +26,14 @@ import im.vector.matrix.android.internal.di.MoshiProvider
 @JsonClass(generateAdapter = true)
 data class RoomEventFilter(
         @Json(name = "limit") var limit: Int? = null,
-        @Json(name = "not_senders") var notSenders: MutableList<String>? = null,
-        @Json(name = "not_types") var notTypes: MutableList<String>? = null,
-        @Json(name = "senders") var senders: MutableList<String>? = null,
-        @Json(name = "types") var types: MutableList<String>? = null,
-        @Json(name = "rooms") var rooms: MutableList<String>? = null,
-        @Json(name = "not_rooms") var notRooms: List<String>? = null,
-        @Json(name = "contains_url") var containsUrl: Boolean? = null,
-        @Json(name = "lazy_load_members") var lazyLoadMembers: Boolean? = null
+        @Json(name = "not_senders") val notSenders: List<String>? = null,
+        @Json(name = "not_types") val notTypes: List<String>? = null,
+        @Json(name = "senders") val senders: List<String>? = null,
+        @Json(name = "types") val types: List<String>? = null,
+        @Json(name = "rooms") val rooms: List<String>? = null,
+        @Json(name = "not_rooms") val notRooms: List<String>? = null,
+        @Json(name = "contains_url") val containsUrl: Boolean? = null,
+        @Json(name = "lazy_load_members") val lazyLoadMembers: Boolean? = null
 ) {
 
     fun toJSONString(): String {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/RoomFilter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/RoomFilter.kt
index 4742bdb988..3109763570 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/RoomFilter.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/filter/RoomFilter.kt
@@ -24,13 +24,13 @@ import com.squareup.moshi.JsonClass
  */
 @JsonClass(generateAdapter = true)
 data class RoomFilter(
-        @Json(name = "not_rooms") var notRooms: List<String>? = null,
-        @Json(name = "rooms") var rooms: List<String>? = null,
-        @Json(name = "ephemeral") var ephemeral: RoomEventFilter? = null,
-        @Json(name = "include_leave") var includeLeave: Boolean? = null,
-        @Json(name = "state") var state: RoomEventFilter? = null,
-        @Json(name = "timeline") var timeline: RoomEventFilter? = null,
-        @Json(name = "account_data") var accountData: RoomEventFilter? = null
+        @Json(name = "not_rooms") val notRooms: List<String>? = null,
+        @Json(name = "rooms") val rooms: List<String>? = null,
+        @Json(name = "ephemeral") val ephemeral: RoomEventFilter? = null,
+        @Json(name = "include_leave") val includeLeave: Boolean? = null,
+        @Json(name = "state") val state: RoomEventFilter? = null,
+        @Json(name = "timeline") val timeline: RoomEventFilter? = null,
+        @Json(name = "account_data") val accountData: RoomEventFilter? = null
 ) {
 
     fun hasData(): Boolean {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/GroupSyncProfile.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/GroupSyncProfile.kt
index 6d31e84d61..00e3377aa9 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/GroupSyncProfile.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/GroupSyncProfile.kt
@@ -24,10 +24,10 @@ internal data class GroupSyncProfile(
         /**
          * The name of the group, if any. May be nil.
          */
-        @Json(name = "name") var name: String? = null,
+        @Json(name = "name") val name: String? = null,
 
         /**
          * The URL for the group's avatar. May be nil.
          */
-        @Json(name = "avatar_url") var avatarUrl: String? = null
+        @Json(name = "avatar_url") val avatarUrl: String? = null
 )
diff --git a/tools/check/forbidden_strings_in_code.txt b/tools/check/forbidden_strings_in_code.txt
index 5c5b600828..a0bd725118 100644
--- a/tools/check/forbidden_strings_in_code.txt
+++ b/tools/check/forbidden_strings_in_code.txt
@@ -67,9 +67,10 @@ DO NOT COMMIT
 
 ### invalid formatting
 \s{8}/\*\n     \*
-[^\w]if\(
-while\(
-for\(
+# Now checked by ktlint
+# [^\w]if\(
+# while\(
+# for\(
 
 # Add space after //
 # DISABLED To re-enable when code will be formatted globally